2Module: Squeal.PostgreSQL.Query
3Description: Squeal queries
4Copyright: (c) Eitan Chatav, 2017
5Maintainer: eitan@morphism.tech
17 , GeneralizedNewtypeDeriving
19 , MultiParamTypeClasses
28 , UndecidableInstances
31module Squeal.PostgreSQL.Query
53 , CommonTableExpression (..)
54 , renderCommonTableExpression
55 , renderCommonTableExpressions
65 , jsonPopulateRecordSet
66 , jsonbPopulateRecordSet
71 -- * Table Expressions
72 , TableExpression (..)
97 -- * Subquery Expressions
126import Control.DeepSeq
127import Data.ByteString (ByteString)
128import Data.Kind (Type)
131import Generics.SOP hiding (from)
134import qualified GHC.Generics as GHC
136import Squeal.PostgreSQL.Expression
137import Squeal.PostgreSQL.Render
138import Squeal.PostgreSQL.Schema
141The process of retrieving or the command to retrieve data from a database
142is called a `Query`. Let's see some examples of queries.
146>>> type Columns = '["col1" ::: 'NoDef :=> 'NotNull 'PGint4, "col2" ::: 'NoDef :=> 'NotNull 'PGint4]
147>>> type Schema = '["tab" ::: 'Table ('[] :=> Columns)]
150 query :: Query '[] (Public Schema) '[] '["col1" ::: 'NotNull 'PGint4, "col2" ::: 'NotNull 'PGint4]
151 query = select Star (from (table #tab))
154SELECT * FROM "tab" AS "tab"
160 query :: Query '[] (Public Schema) '[] '["sum" ::: 'NotNull 'PGint4, "col1" ::: 'NotNull 'PGint4]
162 select_ ((#col1 + #col2) `as` #sum :* #col1)
164 & where_ (#col1 .> #col2)
165 & where_ (#col2 .> 0) )
168SELECT ("col1" + "col2") AS "sum", "col1" AS "col1" FROM "tab" AS "tab" WHERE (("col1" > "col2") AND ("col2" > 0))
174 query :: Query '[] (Public Schema) '[] '["col1" ::: 'NotNull 'PGint4, "col2" ::: 'NotNull 'PGint4]
175 query = select Star (from (subquery (select Star (from (table #tab)) `as` #sub)))
178SELECT * FROM (SELECT * FROM "tab" AS "tab") AS "sub"
184 query :: Query '[] (Public Schema) '[] '["col1" ::: 'NotNull 'PGint4, "col2" ::: 'NotNull 'PGint4]
185 query = select Star (from (table #tab) & limit 100 & offset 2 & limit 50 & offset 2)
188SELECT * FROM "tab" AS "tab" LIMIT 50 OFFSET 4
194 query :: Query '[] (Public Schema) '[ 'NotNull 'PGint4] '["col1" ::: 'NotNull 'PGint4, "col2" ::: 'NotNull 'PGint4]
195 query = select Star (from (table #tab) & where_ (#col1 .> param @1))
198SELECT * FROM "tab" AS "tab" WHERE ("col1" > ($1 :: int4))
204 query :: Query '[] (Public Schema) '[] '["sum" ::: 'NotNull 'PGint4, "col1" ::: 'NotNull 'PGint4 ]
206 select_ (sum_ #col2 `as` #sum :* #col1)
207 ( from (table (#tab `as` #table1))
209 & having (#col1 + sum_ #col2 .> 1) )
212SELECT sum("col2") AS "sum", "col1" AS "col1" FROM "tab" AS "table1" GROUP BY "col1" HAVING (("col1" + sum("col2")) > 1)
218 query :: Query '[] (Public Schema) '[] '["col1" ::: 'NotNull 'PGint4, "col2" ::: 'NotNull 'PGint4]
219 query = select Star (from (table #tab) & orderBy [#col1 & Asc])
222SELECT * FROM "tab" AS "tab" ORDER BY "col1" ASC
226>>> :set -XFlexibleContexts
229 '[ "id" ::: 'NoDef :=> 'NotNull 'PGint4
230 , "price" ::: 'NoDef :=> 'NotNull 'PGfloat4
231 , "customer_id" ::: 'NoDef :=> 'NotNull 'PGint4
232 , "shipper_id" ::: 'NoDef :=> 'NotNull 'PGint4
237type OrdersConstraints =
238 '["pk_orders" ::: PrimaryKey '["id"]
239 ,"fk_customers" ::: ForeignKey '["customer_id"] "customers" '["id"]
240 ,"fk_shippers" ::: ForeignKey '["shipper_id"] "shippers" '["id"] ]
243>>> type NamesColumns = '["id" ::: 'NoDef :=> 'NotNull 'PGint4, "name" ::: 'NoDef :=> 'NotNull 'PGtext]
244>>> type CustomersConstraints = '["pk_customers" ::: PrimaryKey '["id"]]
245>>> type ShippersConstraints = '["pk_shippers" ::: PrimaryKey '["id"]]
248 '[ "orders" ::: 'Table (OrdersConstraints :=> OrdersColumns)
249 , "customers" ::: 'Table (CustomersConstraints :=> NamesColumns)
250 , "shippers" ::: 'Table (ShippersConstraints :=> NamesColumns) ]
255 query :: Query '[] (Public OrdersSchema)
257 '[ "order_price" ::: 'NotNull 'PGfloat4
258 , "customer_name" ::: 'NotNull 'PGtext
259 , "shipper_name" ::: 'NotNull 'PGtext
262 ( #o ! #price `as` #order_price :*
263 #c ! #name `as` #customer_name :*
264 #s ! #name `as` #shipper_name )
265 ( from (table (#orders `as` #o)
266 & innerJoin (table (#customers `as` #c))
267 (#o ! #customer_id .== #c ! #id)
268 & innerJoin (table (#shippers `as` #s))
269 (#o ! #shipper_id .== #s ! #id)) )
272SELECT "o"."price" AS "order_price", "c"."name" AS "customer_name", "s"."name" AS "shipper_name" FROM "orders" AS "o" INNER JOIN "customers" AS "c" ON ("o"."customer_id" = "c"."id") INNER JOIN "shippers" AS "s" ON ("o"."shipper_id" = "s"."id")
278 query :: Query '[] (Public Schema) '[] '["col1" ::: 'NotNull 'PGint4, "col2" ::: 'NotNull 'PGint4]
279 query = select (#t1 & DotStar) (from (table (#tab `as` #t1) & crossJoin (table (#tab `as` #t2))))
282SELECT "t1".* FROM "tab" AS "t1" CROSS JOIN "tab" AS "t2"
288 query :: Query commons schemas '[] '["foo" ::: 'NotNull 'PGint2, "bar" ::: 'NotNull 'PGbool]
289 query = values (1 `as` #foo :* true `as` #bar) [2 `as` #foo :* false `as` #bar]
292SELECT * FROM (VALUES (1, TRUE), (2, FALSE)) AS t ("foo", "bar")
298 query :: Query '[] (Public Schema) '[] '["col1" ::: 'NotNull 'PGint4, "col2" ::: 'NotNull 'PGint4]
299 query = select Star (from (table #tab)) `unionAll` select Star (from (table #tab))
302(SELECT * FROM "tab" AS "tab") UNION ALL (SELECT * FROM "tab" AS "tab")
308 query :: Query '[] (Public Schema) '[] '["col1" ::: 'NotNull 'PGint4, "col2" ::: 'NotNull 'PGint4]
310 select Star (from (table #tab)) `as` #cte1 :>>
311 select Star (from (common #cte1)) `as` #cte2
312 ) (select Star (from (common #cte2)))
315WITH "cte1" AS (SELECT * FROM "tab" AS "tab"), "cte2" AS (SELECT * FROM "cte1" AS "cte1") SELECT * FROM "cte2" AS "cte2"
318 (commons :: FromType)
319 (schemas :: SchemasType)
320 (params :: [NullityType])
322 = UnsafeQuery { renderQuery :: ByteString }
323 deriving (GHC.Generic,Show,Eq,Ord,NFData)
324instance RenderSQL (Query commons schemas params row) where renderSQL = renderQuery
326type family Query_ (schemas :: SchemasType) (params :: Type) (row :: Type) where
327 Query_ schemas params row = Query '[] schemas (TuplePG params) (RowPG row)
329-- | The results of two queries can be combined using the set operation
330-- `union`. Duplicate rows are eliminated.
332 :: Query commons schemas params columns
333 -> Query commons schemas params columns
334 -> Query commons schemas params columns
335q1 `union` q2 = UnsafeQuery $
336 parenthesized (renderSQL q1)
338 <+> parenthesized (renderSQL q2)
340-- | The results of two queries can be combined using the set operation
341-- `unionAll`, the disjoint union. Duplicate rows are retained.
343 :: Query commons schemas params columns
344 -> Query commons schemas params columns
345 -> Query commons schemas params columns
346q1 `unionAll` q2 = UnsafeQuery $
347 parenthesized (renderSQL q1)
348 <+> "UNION" <+> "ALL"
349 <+> parenthesized (renderSQL q2)
351-- | The results of two queries can be combined using the set operation
352-- `intersect`, the intersection. Duplicate rows are eliminated.
354 :: Query commons schemas params columns
355 -> Query commons schemas params columns
356 -> Query commons schemas params columns
357q1 `intersect` q2 = UnsafeQuery $
358 parenthesized (renderSQL q1)
360 <+> parenthesized (renderSQL q2)
362-- | The results of two queries can be combined using the set operation
363-- `intersectAll`, the intersection. Duplicate rows are retained.
365 :: Query commons schemas params columns
366 -> Query commons schemas params columns
367 -> Query commons schemas params columns
368q1 `intersectAll` q2 = UnsafeQuery $
369 parenthesized (renderSQL q1)
370 <+> "INTERSECT" <+> "ALL"
371 <+> parenthesized (renderSQL q2)
373-- | The results of two queries can be combined using the set operation
374-- `except`, the set difference. Duplicate rows are eliminated.
376 :: Query commons schemas params columns
377 -> Query commons schemas params columns
378 -> Query commons schemas params columns
379q1 `except` q2 = UnsafeQuery $
380 parenthesized (renderSQL q1)
382 <+> parenthesized (renderSQL q2)
384-- | The results of two queries can be combined using the set operation
385-- `exceptAll`, the set difference. Duplicate rows are retained.
387 :: Query commons schemas params columns
388 -> Query commons schemas params columns
389 -> Query commons schemas params columns
390q1 `exceptAll` q2 = UnsafeQuery $
391 parenthesized (renderSQL q1)
392 <+> "EXCEPT" <+> "ALL"
393 <+> parenthesized (renderSQL q2)
395{-----------------------------------------
397-----------------------------------------}
399data Selection commons schemas params grp from row where
402 => NP (Aliased (Expression commons schemas params grp from)) row
403 -> Selection commons schemas params grp from row
405 :: HasUnique tab from row
406 => Selection commons schemas params 'Ungrouped from row
410 -> Selection commons schemas params 'Ungrouped from row
412 :: Selection commons schemas params grp from right
413 -> Selection commons schemas params grp from left
414 -> Selection commons schemas params grp from (Join left right)
415instance (KnownSymbol col, row ~ '[col ::: ty])
417 (Expression commons schemas params grp from ty)
418 (Selection commons schemas params grp from row) where
419 expr `as` col = List (expr `as` col)
420instance (Has tab from row0, Has col row0 ty, row1 ~ '[col ::: ty])
421 => IsQualified tab col (Selection commons schemas params 'Ungrouped from row1) where
422 tab ! col = tab ! col `as` col
426 , row1 ~ '[col ::: ty]
427 , GroupedBy tab col bys )
428 => IsQualified tab col (Selection commons schemas params ('Grouped bys) from row1) where
429 tab ! col = tab ! col `as` col
430instance (HasUnique tab from row0, Has col row0 ty, row1 ~ '[col ::: ty])
431 => IsLabel col (Selection commons schemas params 'Ungrouped from row1) where
432 fromLabel = fromLabel @col `as` Alias
434 ( HasUnique tab from row0
436 , row1 ~ '[col ::: ty]
437 , GroupedBy tab col bys )
438 => IsLabel col (Selection commons schemas params ('Grouped bys) from row1) where
439 fromLabel = fromLabel @col `as` Alias
441instance RenderSQL (Selection commons schemas params grp from row) where
443 List list -> renderCommaSeparated (renderAliased renderSQL) list
445 DotStar tab -> renderSQL tab <> ".*"
446 Also right left -> renderSQL left <> ", " <> renderSQL right
448-- | the `TableExpression` in the `select` command constructs an intermediate
449-- virtual table by possibly combining tables, views, eliminating rows,
450-- grouping, etc. This table is finally passed on to processing by
451-- the select list. The `Selection` determines which columns of
452-- the intermediate table are actually output.
454 :: (SListI row, row ~ (x ': xs))
455 => Selection commons schemas params grp from row
457 -> TableExpression commons schemas params grp from
458 -- ^ intermediate virtual table
459 -> Query commons schemas params row
460select selection tabexpr = UnsafeQuery $
462 <+> renderSQL selection
463 <+> renderSQL tabexpr
466 :: (SListI row, row ~ (x ': xs))
467 => NP (Aliased (Expression commons schemas params grp from)) row
468 -> TableExpression commons schemas params grp from
469 -> Query commons schemas params row
470select_ list = select (List list)
472-- | After the select list has been processed, the result table can
473-- be subject to the elimination of duplicate rows using `selectDistinct`.
475 :: (SListI columns, columns ~ (col ': cols))
476 => Selection commons schemas params 'Ungrouped from columns
478 -> TableExpression commons schemas params 'Ungrouped from
479 -- ^ intermediate virtual table
480 -> Query commons schemas params columns
481selectDistinct selection tabexpr = UnsafeQuery $
483 <+> renderSQL selection
484 <+> renderSQL tabexpr
487 :: (SListI columns, columns ~ (col ': cols))
488 => NP (Aliased (Expression commons schemas params 'Ungrouped from)) columns
490 -> TableExpression commons schemas params 'Ungrouped from
491 -- ^ intermediate virtual table
492 -> Query commons schemas params columns
493selectDistinct_ list = select (List list)
495-- | `values` computes a row value or set of row values
496-- specified by value expressions. It is most commonly used
497-- to generate a “constant table” within a larger command,
498-- but it can be used on its own.
500-- >>> type Row = '["a" ::: 'NotNull 'PGint4, "b" ::: 'NotNull 'PGtext]
501-- >>> let query = values (1 `as` #a :* "one" `as` #b) [] :: Query commons schemas '[] Row
503-- SELECT * FROM (VALUES (1, E'one')) AS t ("a", "b")
506 => NP (Aliased (Expression commons schemas params 'Ungrouped '[] )) cols
507 -> [NP (Aliased (Expression commons schemas params 'Ungrouped '[] )) cols]
508 -- ^ When more than one row is specified, all the rows must
509 -- must have the same number of elements
510 -> Query commons schemas params cols
511values rw rws = UnsafeQuery $ "SELECT * FROM"
516 . renderCommaSeparated renderValuePart <$> rw:rws )
518 <+> parenthesized (renderCommaSeparated renderAliasPart rw)
520 renderAliasPart, renderValuePart
521 :: Aliased (Expression commons schemas params 'Ungrouped '[] ) ty -> ByteString
522 renderAliasPart (_ `As` name) = renderSQL name
523 renderValuePart (value `As` _) = renderSQL value
525-- | `values_` computes a row value or set of row values
526-- specified by value expressions.
529 => NP (Aliased (Expression commons schemas params 'Ungrouped '[] )) cols
530 -- ^ one row of values
531 -> Query commons schemas params cols
532values_ rw = values rw []
534{-----------------------------------------
536-----------------------------------------}
538-- | A `TableExpression` computes a table. The table expression contains
539-- a `fromClause` that is optionally followed by a `whereClause`,
540-- `groupByClause`, `havingClause`, `orderByClause`, `limitClause`
541-- and `offsetClause`s. Trivial table expressions simply refer
542-- to a table on disk, a so-called base table, but more complex expressions
543-- can be used to modify or combine base tables in various ways.
545 (commons :: FromType)
546 (schemas :: SchemasType)
547 (params :: [NullityType])
551 { fromClause :: FromClause commons schemas params from
552 -- ^ A table reference that can be a table name, or a derived table such
553 -- as a subquery, a @JOIN@ construct, or complex combinations of these.
554 , whereClause :: [Condition commons schemas params 'Ungrouped from]
555 -- ^ optional search coditions, combined with `.&&`. After the processing
556 -- of the `fromClause` is done, each row of the derived virtual table
557 -- is checked against the search condition. If the result of the
558 -- condition is true, the row is kept in the output table,
559 -- otherwise it is discarded. The search condition typically references
560 -- at least one column of the table generated in the `fromClause`;
561 -- this is not required, but otherwise the WHERE clause will
562 -- be fairly useless.
563 , groupByClause :: GroupByClause grp from
564 -- ^ The `groupByClause` is used to group together those rows in a table
565 -- that have the same values in all the columns listed. The order in which
566 -- the columns are listed does not matter. The effect is to combine each
567 -- set of rows having common values into one group row that represents all
568 -- rows in the group. This is done to eliminate redundancy in the output
569 -- and/or compute aggregates that apply to these groups.
570 , havingClause :: HavingClause commons schemas params grp from
571 -- ^ If a table has been grouped using `groupBy`, but only certain groups
572 -- are of interest, the `havingClause` can be used, much like a
573 -- `whereClause`, to eliminate groups from the result. Expressions in the
574 -- `havingClause` can refer both to grouped expressions and to ungrouped
575 -- expressions (which necessarily involve an aggregate function).
576 , orderByClause :: [SortExpression commons schemas params grp from]
577 -- ^ The `orderByClause` is for optional sorting. When more than one
578 -- `SortExpression` is specified, the later (right) values are used to sort
579 -- rows that are equal according to the earlier (left) values.
580 , limitClause :: [Word64]
581 -- ^ The `limitClause` is combined with `min` to give a limit count
582 -- if nonempty. If a limit count is given, no more than that many rows
583 -- will be returned (but possibly fewer, if the query itself yields
585 , offsetClause :: [Word64]
586 -- ^ The `offsetClause` is combined with `+` to give an offset count
587 -- if nonempty. The offset count says to skip that many rows before
588 -- beginning to return rows. The rows are skipped before the limit count
592-- | Render a `TableExpression`
593instance RenderSQL (TableExpression commons schemas params grp from) where
595 (TableExpression frm' whs' grps' hvs' srts' lims' offs') = mconcat
596 [ "FROM ", renderSQL frm'
600 , renderOrderByClause srts'
602 , renderOffsets offs'
607 wh:[] -> " WHERE" <+> renderSQL wh
608 wh:whs -> " WHERE" <+> renderSQL (foldr (.&&) wh whs)
609 renderOrderByClause = \case
612 <+> commaSeparated (renderSQL <$> srts)
615 lims -> " LIMIT" <+> fromString (show (minimum lims))
616 renderOffsets = \case
618 offs -> " OFFSET" <+> fromString (show (sum offs))
620-- | A `from` generates a `TableExpression` from a table reference that can be
621-- a table name, or a derived table such as a subquery, a JOIN construct,
622-- or complex combinations of these. A `from` may be transformed by `where_`,
623-- `group`, `having`, `orderBy`, `limit` and `offset`, using the `&` operator
624-- to match the left-to-right sequencing of their placement in SQL.
626 :: FromClause commons schemas params from -- ^ table reference
627 -> TableExpression commons schemas params 'Ungrouped from
628from rels = TableExpression rels [] NoGroups NoHaving [] [] []
630-- | A `where_` is an endomorphism of `TableExpression`s which adds a
631-- search condition to the `whereClause`.
633 :: Condition commons schemas params 'Ungrouped from -- ^ filtering condition
634 -> TableExpression commons schemas params grp from
635 -> TableExpression commons schemas params grp from
636where_ wh rels = rels {whereClause = wh : whereClause rels}
638-- | A `groupBy` is a transformation of `TableExpression`s which switches
639-- its `Grouping` from `Ungrouped` to `Grouped`. Use @group Nil@ to perform
640-- a "grand total" aggregation query.
643 => NP (By from) bys -- ^ grouped columns
644 -> TableExpression commons schemas params 'Ungrouped from
645 -> TableExpression commons schemas params ('Grouped bys) from
646groupBy bys rels = TableExpression
647 { fromClause = fromClause rels
648 , whereClause = whereClause rels
649 , groupByClause = Group bys
650 , havingClause = Having []
652 , limitClause = limitClause rels
653 , offsetClause = offsetClause rels
656-- | A `having` is an endomorphism of `TableExpression`s which adds a
657-- search condition to the `havingClause`.
659 :: Condition commons schemas params ('Grouped bys) from -- ^ having condition
660 -> TableExpression commons schemas params ('Grouped bys) from
661 -> TableExpression commons schemas params ('Grouped bys) from
663 { havingClause = case havingClause rels of Having hvs -> Having (hv:hvs) }
665-- | An `orderBy` is an endomorphism of `TableExpression`s which appends an
666-- ordering to the right of the `orderByClause`.
668 :: [SortExpression commons schemas params grp from] -- ^ sort expressions
669 -> TableExpression commons schemas params grp from
670 -> TableExpression commons schemas params grp from
671orderBy srts rels = rels {orderByClause = orderByClause rels ++ srts}
673-- | A `limit` is an endomorphism of `TableExpression`s which adds to the
676 :: Word64 -- ^ limit parameter
677 -> TableExpression commons schemas params grp from
678 -> TableExpression commons schemas params grp from
679limit lim rels = rels {limitClause = lim : limitClause rels}
681-- | An `offset` is an endomorphism of `TableExpression`s which adds to the
684 :: Word64 -- ^ offset parameter
685 -> TableExpression commons schemas params grp from
686 -> TableExpression commons schemas params grp from
687offset off rels = rels {offsetClause = off : offsetClause rels}
689{-----------------------------------------
691-----------------------------------------}
695 -> Expression commons schemas params 'Ungrouped '[] ty
696 -> Query commons schemas params row
697unsafeSetOfFunction fun expr = UnsafeQuery $
698 "SELECT * FROM " <> fun <> "(" <> renderSQL expr <> ")"
700-- | Expands the outermost JSON object into a set of key/value pairs.
702 :: Expression commons schemas params 'Ungrouped '[] (nullity 'PGjson) -- ^ json object
703 -> Query commons schemas params
704 '["key" ::: 'NotNull 'PGtext, "value" ::: 'NotNull 'PGjson]
705jsonEach = unsafeSetOfFunction "json_each"
707-- | Expands the outermost binary JSON object into a set of key/value pairs.
709 :: Expression commons schemas params 'Ungrouped '[] (nullity 'PGjsonb) -- ^ jsonb object
710 -> Query commons schemas params
711 '["key" ::: 'NotNull 'PGtext, "value" ::: 'NotNull 'PGjsonb]
712jsonbEach = unsafeSetOfFunction "jsonb_each"
714-- | Expands the outermost JSON object into a set of key/value pairs.
716 :: Expression commons schemas params 'Ungrouped '[] (nullity 'PGjson) -- ^ json object
717 -> Query commons schemas params
718 '["key" ::: 'NotNull 'PGtext, "value" ::: 'NotNull 'PGtext]
719jsonEachAsText = unsafeSetOfFunction "json_each_text"
721-- | Expands the outermost binary JSON object into a set of key/value pairs.
723 :: Expression commons schemas params 'Ungrouped '[] (nullity 'PGjsonb) -- ^ jsonb object
724 -> Query commons schemas params
725 '["key" ::: 'NotNull 'PGtext, "value" ::: 'NotNull 'PGtext]
726jsonbEachAsText = unsafeSetOfFunction "jsonb_each_text"
728-- | Returns set of keys in the outermost JSON object.
730 :: Expression commons schemas params 'Ungrouped '[] (nullity 'PGjson) -- ^ json object
731 -> Query commons schemas params '["json_object_keys" ::: 'NotNull 'PGtext]
732jsonObjectKeys = unsafeSetOfFunction "json_object_keys"
734-- | Returns set of keys in the outermost JSON object.
736 :: Expression commons schemas params 'Ungrouped '[] (nullity 'PGjsonb) -- ^ jsonb object
737 -> Query commons schemas params '["jsonb_object_keys" ::: 'NotNull 'PGtext]
738jsonbObjectKeys = unsafeSetOfFunction "jsonb_object_keys"
740unsafePopulateFunction
742 -> TypeExpression schemas (nullity ('PGcomposite row))
743 -> Expression commons schemas params 'Ungrouped '[] ty
744 -> Query commons schemas params row
745unsafePopulateFunction fun ty expr = UnsafeQuery $
746 "SELECT * FROM " <> fun <> "("
747 <> "null::" <> renderSQL ty <> ", "
748 <> renderSQL expr <> ")"
750-- | Expands the JSON expression to a row whose columns match the record
751-- type defined by the given table.
753 :: TypeExpression schemas (nullity ('PGcomposite row)) -- ^ row type
754 -> Expression commons schemas params 'Ungrouped '[] (nullity 'PGjson) -- ^ json object
755 -> Query commons schemas params row
756jsonPopulateRecord = unsafePopulateFunction "json_populate_record"
758-- | Expands the binary JSON expression to a row whose columns match the record
759-- type defined by the given table.
761 :: TypeExpression schemas (nullity ('PGcomposite row)) -- ^ row type
762 -> Expression commons schemas params 'Ungrouped '[] (nullity 'PGjsonb) -- ^ jsonb object
763 -> Query commons schemas params row
764jsonbPopulateRecord = unsafePopulateFunction "jsonb_populate_record"
766-- | Expands the outermost array of objects in the given JSON expression to a
767-- set of rows whose columns match the record type defined by the given table.
769 :: TypeExpression schemas (nullity ('PGcomposite row)) -- ^ row type
770 -> Expression commons schemas params 'Ungrouped '[] (nullity 'PGjson) -- ^ json array
771 -> Query commons schemas params row
772jsonPopulateRecordSet = unsafePopulateFunction "json_populate_record_set"
774-- | Expands the outermost array of objects in the given binary JSON expression
775-- to a set of rows whose columns match the record type defined by the given
777jsonbPopulateRecordSet
778 :: TypeExpression schemas (nullity ('PGcomposite row)) -- ^ row type
779 -> Expression commons schemas params 'Ungrouped '[] (nullity 'PGjsonb) -- ^ jsonb array
780 -> Query commons schemas params row
781jsonbPopulateRecordSet = unsafePopulateFunction "jsonb_populate_record_set"
784 :: (SListI record, json `In` PGJsonType)
786 -> Expression commons schemas params 'Ungrouped '[] (nullity json)
787 -> NP (Aliased (TypeExpression schemas)) record
788 -> Query commons schemas params record
789unsafeRecordFunction fun expr types = UnsafeQuery $
790 "SELECT * FROM " <> fun <> "("
791 <> renderSQL expr <> ")"
792 <+> "AS" <+> "x" <> parenthesized (renderCommaSeparated renderTy types)
794 renderTy :: Aliased (TypeExpression schemas) ty -> ByteString
795 renderTy (ty `As` alias) =
796 renderSQL alias <+> renderSQL ty
798-- | Builds an arbitrary record from a JSON object.
801 => Expression commons schemas params 'Ungrouped '[] (nullity 'PGjson) -- ^ json object
802 -> NP (Aliased (TypeExpression schemas)) record -- ^ record types
803 -> Query commons schemas params record
804jsonToRecord = unsafeRecordFunction "json_to_record"
806-- | Builds an arbitrary record from a binary JSON object.
809 => Expression commons schemas params 'Ungrouped '[] (nullity 'PGjsonb) -- ^ jsonb object
810 -> NP (Aliased (TypeExpression schemas)) record -- ^ record types
811 -> Query commons schemas params record
812jsonbToRecord = unsafeRecordFunction "jsonb_to_record"
814-- | Builds an arbitrary set of records from a JSON array of objects.
817 => Expression commons schemas params 'Ungrouped '[] (nullity 'PGjson) -- ^ json array
818 -> NP (Aliased (TypeExpression schemas)) record -- ^ record types
819 -> Query commons schemas params record
820jsonToRecordSet = unsafeRecordFunction "json_to_record_set"
822-- | Builds an arbitrary set of records from a binary JSON array of objects.
825 => Expression commons schemas params 'Ungrouped '[] (nullity 'PGjsonb) -- ^ jsonb array
826 -> NP (Aliased (TypeExpression schemas)) record -- ^ record types
827 -> Query commons schemas params record
828jsonbToRecordSet = unsafeRecordFunction "jsonb_to_record_set"
830{-----------------------------------------
832-----------------------------------------}
835A `FromClause` can be a table name, or a derived table such
836as a subquery, a @JOIN@ construct, or complex combinations of these.
838newtype FromClause commons schemas params from
839 = UnsafeFromClause { renderFromClause :: ByteString }
840 deriving (GHC.Generic,Show,Eq,Ord,NFData)
841instance RenderSQL (FromClause commons schemas params from) where
842 renderSQL = renderFromClause
844-- | A real `table` is a table from the database.
846 :: (Has sch schemas schema, Has tab schema ('Table table))
847 => Aliased (QualifiedAlias sch) (alias ::: tab)
848 -> FromClause commons schemas params '[alias ::: TableToRow table]
849table (tab `As` alias) = UnsafeFromClause $
850 renderSQL tab <+> "AS" <+> renderSQL alias
852-- | `subquery` derives a table from a `Query`.
854 :: Aliased (Query commons schemas params) query
855 -> FromClause commons schemas params '[query]
856subquery = UnsafeFromClause . renderAliased (parenthesized . renderQuery)
858-- | `view` derives a table from a `View`.
860 :: (Has sch schemas schema, Has vw schema ('View view))
861 => Aliased (QualifiedAlias sch) (alias ::: vw)
862 -> FromClause commons schemas params '[alias ::: view]
863view (vw `As` alias) = UnsafeFromClause $
864 renderSQL vw <+> "AS" <+> renderSQL alias
867 :: Has cte commons common
868 => Aliased Alias (alias ::: cte)
869 -> FromClause commons schemas params '[alias ::: common]
870common (cte `As` alias) = UnsafeFromClause $
871 renderSQL cte <+> "AS" <+> renderSQL alias
873{- | @left & crossJoin right@. For every possible combination of rows from
874 @left@ and @right@ (i.e., a Cartesian product), the joined table will contain
875 a row consisting of all columns in @left@ followed by all columns in @right@.
876 If the tables have @n@ and @m@ rows respectively, the joined table will
880 :: FromClause commons schemas params right
882 -> FromClause commons schemas params left
884 -> FromClause commons schemas params (Join left right)
885crossJoin right left = UnsafeFromClause $
886 renderSQL left <+> "CROSS JOIN" <+> renderSQL right
888{- | @left & innerJoin right on@. The joined table is filtered by
892 :: FromClause commons schemas params right
894 -> Condition commons schemas params 'Ungrouped (Join left right)
896 -> FromClause commons schemas params left
898 -> FromClause commons schemas params (Join left right)
899innerJoin right on left = UnsafeFromClause $
900 renderSQL left <+> "INNER JOIN" <+> renderSQL right
901 <+> "ON" <+> renderSQL on
903{- | @left & leftOuterJoin right on@. First, an inner join is performed.
904 Then, for each row in @left@ that does not satisfy the @on@ condition with
905 any row in @right@, a joined row is added with null values in columns of @right@.
906 Thus, the joined table always has at least one row for each row in @left@.
909 :: FromClause commons schemas params right
911 -> Condition commons schemas params 'Ungrouped (Join left right)
913 -> FromClause commons schemas params left
915 -> FromClause commons schemas params (Join left (NullifyFrom right))
916leftOuterJoin right on left = UnsafeFromClause $
917 renderSQL left <+> "LEFT OUTER JOIN" <+> renderSQL right
918 <+> "ON" <+> renderSQL on
920{- | @left & rightOuterJoin right on@. First, an inner join is performed.
921 Then, for each row in @right@ that does not satisfy the @on@ condition with
922 any row in @left@, a joined row is added with null values in columns of @left@.
923 This is the converse of a left join: the result table will always
924 have a row for each row in @right@.
927 :: FromClause commons schemas params right
929 -> Condition commons schemas params 'Ungrouped (Join left right)
931 -> FromClause commons schemas params left
933 -> FromClause commons schemas params (Join (NullifyFrom left) right)
934rightOuterJoin right on left = UnsafeFromClause $
935 renderSQL left <+> "RIGHT OUTER JOIN" <+> renderSQL right
936 <+> "ON" <+> renderSQL on
938{- | @left & fullOuterJoin right on@. First, an inner join is performed.
939 Then, for each row in @left@ that does not satisfy the @on@ condition with
940 any row in @right@, a joined row is added with null values in columns of @right@.
941 Also, for each row of @right@ that does not satisfy the join condition
942 with any row in @left@, a joined row with null values in the columns of @left@
946 :: FromClause commons schemas params right
948 -> Condition commons schemas params 'Ungrouped (Join left right)
950 -> FromClause commons schemas params left
952 -> FromClause commons schemas params
953 (Join (NullifyFrom left) (NullifyFrom right))
954fullOuterJoin right on left = UnsafeFromClause $
955 renderSQL left <+> "FULL OUTER JOIN" <+> renderSQL right
956 <+> "ON" <+> renderSQL on
958{-----------------------------------------
960-----------------------------------------}
962-- | `By`s are used in `group` to reference a list of columns which are then
963-- used to group together those rows in a table that have the same values
964-- in all the columns listed. @By \#col@ will reference an unambiguous
965-- column @col@; otherwise @By2 (\#tab \! \#col)@ will reference a table
966-- qualified column @tab.col@.
969 (by :: (Symbol,Symbol)) where
971 :: (HasUnique table from columns, Has column columns ty)
973 -> By from '(table, column)
975 :: (Has table from columns, Has column columns ty)
978 -> By from '(table, column)
979deriving instance Show (By from by)
980deriving instance Eq (By from by)
981deriving instance Ord (By from by)
982instance RenderSQL (By from by) where
984 By1 column -> renderSQL column
985 By2 rel column -> renderSQL rel <> "." <> renderSQL column
987instance (HasUnique rel rels cols, Has col cols ty, by ~ '(rel, col))
988 => IsLabel col (By rels by) where fromLabel = By1 fromLabel
989instance (HasUnique rel rels cols, Has col cols ty, bys ~ '[ '(rel, col)])
990 => IsLabel col (NP (By rels) bys) where fromLabel = By1 fromLabel :* Nil
991instance (Has rel rels cols, Has col cols ty, by ~ '(rel, col))
992 => IsQualified rel col (By rels by) where (!) = By2
993instance (Has rel rels cols, Has col cols ty, bys ~ '[ '(rel, col)])
994 => IsQualified rel col (NP (By rels) bys) where
995 rel ! col = By2 rel col :* Nil
997-- | A `GroupByClause` indicates the `Grouping` of a `TableExpression`.
998-- A `NoGroups` indicates `Ungrouped` while a `Group` indicates `Grouped`.
999-- @NoGroups@ is distinguised from @Group Nil@ since no aggregation can be
1000-- done on @NoGroups@ while all output `Expression`s must be aggregated
1001-- in @Group Nil@. In general, all output `Expression`s in the
1002-- complement of @bys@ must be aggregated in @Group bys@.
1003data GroupByClause grp from where
1004 NoGroups :: GroupByClause 'Ungrouped from
1008 -> GroupByClause ('Grouped bys) from
1010-- | Renders a `GroupByClause`.
1011instance RenderSQL (GroupByClause grp from) where
1015 Group bys -> " GROUP BY" <+> renderCommaSeparated renderSQL bys
1017-- | A `HavingClause` is used to eliminate groups that are not of interest.
1018-- An `Ungrouped` `TableExpression` may only use `NoHaving` while a `Grouped`
1019-- `TableExpression` must use `Having` whose conditions are combined with
1021data HavingClause commons schemas params grp from where
1022 NoHaving :: HavingClause commons schemas params 'Ungrouped from
1024 :: [Condition commons schemas params ('Grouped bys) from]
1025 -> HavingClause commons schemas params ('Grouped bys) from
1026deriving instance Show (HavingClause commons schemas params grp from)
1027deriving instance Eq (HavingClause commons schemas params grp from)
1028deriving instance Ord (HavingClause commons schemas params grp from)
1030-- | Render a `HavingClause`.
1031instance RenderSQL (HavingClause commons schemas params grp from) where
1035 Having conditions ->
1036 " HAVING" <+> commaSeparated (renderSQL <$> conditions)
1038{-----------------------------------------
1040-----------------------------------------}
1042-- | `SortExpression`s are used by `sortBy` to optionally sort the results
1043-- of a `Query`. `Asc` or `Desc` set the sort direction of a `NotNull` result
1044-- column to ascending or descending. Ascending order puts smaller values
1045-- first, where "smaller" is defined in terms of the `.<` operator. Similarly,
1046-- descending order is determined with the `.>` operator. `AscNullsFirst`,
1047-- `AscNullsLast`, `DescNullsFirst` and `DescNullsLast` options are used to
1048-- determine whether nulls appear before or after non-null values in the sort
1049-- ordering of a `Null` result column.
1050data SortExpression commons schemas params grp from where
1052 :: Expression commons schemas params grp from ('NotNull ty)
1053 -> SortExpression commons schemas params grp from
1055 :: Expression commons schemas params grp from ('NotNull ty)
1056 -> SortExpression commons schemas params grp from
1058 :: Expression commons schemas params grp from ('Null ty)
1059 -> SortExpression commons schemas params grp from
1061 :: Expression commons schemas params grp from ('Null ty)
1062 -> SortExpression commons schemas params grp from
1064 :: Expression commons schemas params grp from ('Null ty)
1065 -> SortExpression commons schemas params grp from
1067 :: Expression commons schemas params grp from ('Null ty)
1068 -> SortExpression commons schemas params grp from
1069deriving instance Show (SortExpression commons schemas params grp from)
1071-- | Render a `SortExpression`.
1072instance RenderSQL (SortExpression commons schemas params grp from) where
1074 Asc expression -> renderSQL expression <+> "ASC"
1075 Desc expression -> renderSQL expression <+> "DESC"
1076 AscNullsFirst expression -> renderSQL expression
1077 <+> "ASC NULLS FIRST"
1078 DescNullsFirst expression -> renderSQL expression
1079 <+> "DESC NULLS FIRST"
1080 AscNullsLast expression -> renderSQL expression <+> "ASC NULLS LAST"
1081 DescNullsLast expression -> renderSQL expression <+> "DESC NULLS LAST"
1083unsafeSubqueryExpression
1085 -> Expression commons schemas params grp from ty
1086 -> Query commons schemas params '[alias ::: ty]
1087 -> Expression commons schemas params grp from (nullity 'PGbool)
1088unsafeSubqueryExpression op x q = UnsafeExpression $
1089 renderSQL x <+> op <+> parenthesized (renderSQL q)
1091unsafeRowSubqueryExpression
1094 -> NP (Aliased (Expression commons schemas params grp from)) row
1095 -> Query commons schemas params row
1096 -> Expression commons schemas params grp from (nullity 'PGbool)
1097unsafeRowSubqueryExpression op xs q = UnsafeExpression $
1098 renderSQL (row xs) <+> op <+> parenthesized (renderSQL q)
1100-- | The right-hand side is a sub`Query`, which must return exactly one column.
1101-- The left-hand expression is evaluated and compared to each row of the
1102-- sub`Query` result. The result of `in_` is `true` if any equal subquery row is found.
1103-- The result is `false` if no equal row is found
1104-- (including the case where the subquery returns no rows).
1106-- >>> printSQL $ true `in_` values_ (true `as` #foo)
1107-- TRUE IN (SELECT * FROM (VALUES (TRUE)) AS t ("foo"))
1109 :: Expression commons schemas params grp from ty -- ^ expression
1110 -> Query commons schemas params '[alias ::: ty] -- ^ subquery
1111 -> Expression commons schemas params grp from (nullity 'PGbool)
1112in_ = unsafeSubqueryExpression "IN"
1114{- | The left-hand side of this form of `rowIn` is a row constructor.
1115The right-hand side is a sub`Query`,
1116which must return exactly as many columns as
1117there are expressions in the left-hand row.
1118The left-hand expressions are evaluated and compared row-wise to each row
1119of the subquery result. The result of `rowIn`
1120is `true` if any equal subquery row is found.
1121The result is `false` if no equal row is found
1122(including the case where the subquery returns no rows).
1124>>> let myRow = 1 `as` #foo :* false `as` #bar :: NP (Aliased (Expression commons schemas params grp from)) '["foo" ::: 'NotNull 'PGint2, "bar" ::: 'NotNull 'PGbool]
1125>>> printSQL $ myRow `rowIn` values_ myRow
1126ROW(1, FALSE) IN (SELECT * FROM (VALUES (1, FALSE)) AS t ("foo", "bar"))
1130 => NP (Aliased (Expression commons schemas params grp from)) row -- ^ row constructor
1131 -> Query commons schemas params row -- ^ subquery
1132 -> Expression commons schemas params grp from (nullity 'PGbool)
1133rowIn = unsafeRowSubqueryExpression "IN"
1135-- | >>> printSQL $ true `eqAll` values_ (true `as` #foo)
1136-- TRUE = ALL (SELECT * FROM (VALUES (TRUE)) AS t ("foo"))
1138 :: Expression commons schemas params grp from ty -- ^ expression
1139 -> Query commons schemas params '[alias ::: ty] -- ^ subquery
1140 -> Expression commons schemas params grp from (nullity 'PGbool)
1141eqAll = unsafeSubqueryExpression "= ALL"
1143-- | >>> let myRow = 1 `as` #foo :* false `as` #bar :: NP (Aliased (Expression commons schemas params grp from)) '["foo" ::: 'NotNull 'PGint2, "bar" ::: 'NotNull 'PGbool]
1144-- >>> printSQL $ myRow `rowEqAll` values_ myRow
1145-- ROW(1, FALSE) = ALL (SELECT * FROM (VALUES (1, FALSE)) AS t ("foo", "bar"))
1148 => NP (Aliased (Expression commons schemas params grp from)) row -- ^ row constructor
1149 -> Query commons schemas params row -- ^ subquery
1150 -> Expression commons schemas params grp from (nullity 'PGbool)
1151rowEqAll = unsafeRowSubqueryExpression "= ALL"
1153-- | >>> printSQL $ true `eqAny` values_ (true `as` #foo)
1154-- TRUE = ANY (SELECT * FROM (VALUES (TRUE)) AS t ("foo"))
1156 :: Expression commons schemas params grp from ty -- ^ expression
1157 -> Query commons schemas params '[alias ::: ty] -- ^ subquery
1158 -> Expression commons schemas params grp from (nullity 'PGbool)
1159eqAny = unsafeSubqueryExpression "= ANY"
1161-- | >>> let myRow = 1 `as` #foo :* false `as` #bar :: NP (Aliased (Expression commons schemas params grp from)) '["foo" ::: 'NotNull 'PGint2, "bar" ::: 'NotNull 'PGbool]
1162-- >>> printSQL $ myRow `rowEqAny` values_ myRow
1163-- ROW(1, FALSE) = ANY (SELECT * FROM (VALUES (1, FALSE)) AS t ("foo", "bar"))
1166 => NP (Aliased (Expression commons schemas params grp from)) row -- ^ row constructor
1167 -> Query commons schemas params row -- ^ subquery
1168 -> Expression commons schemas params grp from (nullity 'PGbool)
1169rowEqAny = unsafeRowSubqueryExpression "= ANY"
1171-- | >>> printSQL $ true `neqAll` values_ (true `as` #foo)
1172-- TRUE <> ALL (SELECT * FROM (VALUES (TRUE)) AS t ("foo"))
1174 :: Expression commons schemas params grp from ty -- ^ expression
1175 -> Query commons schemas params '[alias ::: ty] -- ^ subquery
1176 -> Expression commons schemas params grp from (nullity 'PGbool)
1177neqAll = unsafeSubqueryExpression "<> ALL"
1179-- | >>> let myRow = 1 `as` #foo :* false `as` #bar :: NP (Aliased (Expression commons schemas params grp from)) '["foo" ::: 'NotNull 'PGint2, "bar" ::: 'NotNull 'PGbool]
1180-- >>> printSQL $ myRow `rowNeqAll` values_ myRow
1181-- ROW(1, FALSE) <> ALL (SELECT * FROM (VALUES (1, FALSE)) AS t ("foo", "bar"))
1184 => NP (Aliased (Expression commons schemas params grp from)) row -- ^ row constructor
1185 -> Query commons schemas params row -- ^ subquery
1186 -> Expression commons schemas params grp from (nullity 'PGbool)
1187rowNeqAll = unsafeRowSubqueryExpression "<> ALL"
1189-- | >>> printSQL $ true `neqAny` values_ (true `as` #foo)
1190-- TRUE <> ANY (SELECT * FROM (VALUES (TRUE)) AS t ("foo"))
1192 :: Expression commons schemas params grp from ty -- ^ expression
1193 -> Query commons schemas params '[alias ::: ty] -- ^ subquery
1194 -> Expression commons schemas params grp from (nullity 'PGbool)
1195neqAny = unsafeSubqueryExpression "<> ANY"
1197-- | >>> let myRow = 1 `as` #foo :* false `as` #bar :: NP (Aliased (Expression commons schemas params grp from)) '["foo" ::: 'NotNull 'PGint2, "bar" ::: 'NotNull 'PGbool]
1198-- >>> printSQL $ myRow `rowNeqAny` values_ myRow
1199-- ROW(1, FALSE) <> ANY (SELECT * FROM (VALUES (1, FALSE)) AS t ("foo", "bar"))
1202 => NP (Aliased (Expression commons schemas params grp from)) row -- ^ row constructor
1203 -> Query commons schemas params row -- ^ subquery
1204 -> Expression commons schemas params grp from (nullity 'PGbool)
1205rowNeqAny = unsafeRowSubqueryExpression "<> ANY"
1207-- | >>> printSQL $ true `allLt` values_ (true `as` #foo)
1208-- TRUE ALL < (SELECT * FROM (VALUES (TRUE)) AS t ("foo"))
1210 :: Expression commons schemas params grp from ty -- ^ expression
1211 -> Query commons schemas params '[alias ::: ty] -- ^ subquery
1212 -> Expression commons schemas params grp from (nullity 'PGbool)
1213allLt = unsafeSubqueryExpression "ALL <"
1215-- | >>> let myRow = 1 `as` #foo :* false `as` #bar :: NP (Aliased (Expression commons schemas params grp from)) '["foo" ::: 'NotNull 'PGint2, "bar" ::: 'NotNull 'PGbool]
1216-- >>> printSQL $ myRow `rowLtAll` values_ myRow
1217-- ROW(1, FALSE) ALL < (SELECT * FROM (VALUES (1, FALSE)) AS t ("foo", "bar"))
1220 => NP (Aliased (Expression commons schemas params grp from)) row -- ^ row constructor
1221 -> Query commons schemas params row -- ^ subquery
1222 -> Expression commons schemas params grp from (nullity 'PGbool)
1223rowLtAll = unsafeRowSubqueryExpression "ALL <"
1225-- | >>> printSQL $ true `ltAny` values_ (true `as` #foo)
1226-- TRUE ANY < (SELECT * FROM (VALUES (TRUE)) AS t ("foo"))
1228 :: Expression commons schemas params grp from ty -- ^ expression
1229 -> Query commons schemas params '[alias ::: ty] -- ^ subquery
1230 -> Expression commons schemas params grp from (nullity 'PGbool)
1231ltAny = unsafeSubqueryExpression "ANY <"
1233-- | >>> let myRow = 1 `as` #foo :* false `as` #bar :: NP (Aliased (Expression commons schemas params grp from)) '["foo" ::: 'NotNull 'PGint2, "bar" ::: 'NotNull 'PGbool]
1234-- >>> printSQL $ myRow `rowLtAll` values_ myRow
1235-- ROW(1, FALSE) ALL < (SELECT * FROM (VALUES (1, FALSE)) AS t ("foo", "bar"))
1238 => NP (Aliased (Expression commons schemas params grp from)) row -- ^ row constructor
1239 -> Query commons schemas params row -- ^ subquery
1240 -> Expression commons schemas params grp from (nullity 'PGbool)
1241rowLtAny = unsafeRowSubqueryExpression "ANY <"
1243-- | >>> printSQL $ true `lteAll` values_ (true `as` #foo)
1244-- TRUE <= ALL (SELECT * FROM (VALUES (TRUE)) AS t ("foo"))
1246 :: Expression commons schemas params grp from ty -- ^ expression
1247 -> Query commons schemas params '[alias ::: ty] -- ^ subquery
1248 -> Expression commons schemas params grp from (nullity 'PGbool)
1249lteAll = unsafeSubqueryExpression "<= ALL"
1251-- | >>> let myRow = 1 `as` #foo :* false `as` #bar :: NP (Aliased (Expression commons schemas params grp from)) '["foo" ::: 'NotNull 'PGint2, "bar" ::: 'NotNull 'PGbool]
1252-- >>> printSQL $ myRow `rowLteAll` values_ myRow
1253-- ROW(1, FALSE) <= ALL (SELECT * FROM (VALUES (1, FALSE)) AS t ("foo", "bar"))
1256 => NP (Aliased (Expression commons schemas params grp from)) row -- ^ row constructor
1257 -> Query commons schemas params row -- ^ subquery
1258 -> Expression commons schemas params grp from (nullity 'PGbool)
1259rowLteAll = unsafeRowSubqueryExpression "<= ALL"
1261-- | >>> printSQL $ true `lteAny` values_ (true `as` #foo)
1262-- TRUE <= ANY (SELECT * FROM (VALUES (TRUE)) AS t ("foo"))
1264 :: Expression commons schemas params grp from ty -- ^ expression
1265 -> Query commons schemas params '[alias ::: ty] -- ^ subquery
1266 -> Expression commons schemas params grp from (nullity 'PGbool)
1267lteAny = unsafeSubqueryExpression "<= ANY"
1269-- | >>> let myRow = 1 `as` #foo :* false `as` #bar :: NP (Aliased (Expression commons schemas params grp from)) '["foo" ::: 'NotNull 'PGint2, "bar" ::: 'NotNull 'PGbool]
1270-- >>> printSQL $ myRow `rowLteAny` values_ myRow
1271-- ROW(1, FALSE) <= ANY (SELECT * FROM (VALUES (1, FALSE)) AS t ("foo", "bar"))
1274 => NP (Aliased (Expression commons schemas params grp from)) row -- ^ row constructor
1275 -> Query commons schemas params row -- ^ subquery
1276 -> Expression commons schemas params grp from (nullity 'PGbool)
1277rowLteAny = unsafeRowSubqueryExpression "<= ANY"
1279-- | >>> printSQL $ true `gtAll` values_ (true `as` #foo)
1280-- TRUE > ALL (SELECT * FROM (VALUES (TRUE)) AS t ("foo"))
1282 :: Expression commons schemas params grp from ty -- ^ expression
1283 -> Query commons schemas params '[alias ::: ty] -- ^ subquery
1284 -> Expression commons schemas params grp from (nullity 'PGbool)
1285gtAll = unsafeSubqueryExpression "> ALL"
1287-- | >>> let myRow = 1 `as` #foo :* false `as` #bar :: NP (Aliased (Expression commons schemas params grp from)) '["foo" ::: 'NotNull 'PGint2, "bar" ::: 'NotNull 'PGbool]
1288-- >>> printSQL $ myRow `rowGtAll` values_ myRow
1289-- ROW(1, FALSE) > ALL (SELECT * FROM (VALUES (1, FALSE)) AS t ("foo", "bar"))
1292 => NP (Aliased (Expression commons schemas params grp from)) row -- ^ row constructor
1293 -> Query commons schemas params row -- ^ subquery
1294 -> Expression commons schemas params grp from (nullity 'PGbool)
1295rowGtAll = unsafeRowSubqueryExpression "> ALL"
1297-- | >>> printSQL $ true `gtAny` values_ (true `as` #foo)
1298-- TRUE > ANY (SELECT * FROM (VALUES (TRUE)) AS t ("foo"))
1300 :: Expression commons schemas params grp from ty -- ^ expression
1301 -> Query commons schemas params '[alias ::: ty] -- ^ subquery
1302 -> Expression commons schemas params grp from (nullity 'PGbool)
1303gtAny = unsafeSubqueryExpression "> ANY"
1305-- | >>> let myRow = 1 `as` #foo :* false `as` #bar :: NP (Aliased (Expression commons schemas params grp from)) '["foo" ::: 'NotNull 'PGint2, "bar" ::: 'NotNull 'PGbool]
1306-- >>> printSQL $ myRow `rowGtAny` values_ myRow
1307-- ROW(1, FALSE) > ANY (SELECT * FROM (VALUES (1, FALSE)) AS t ("foo", "bar"))
1310 => NP (Aliased (Expression commons schemas params grp from)) row -- ^ row constructor
1311 -> Query commons schemas params row -- ^ subquery
1312 -> Expression commons schemas params grp from (nullity 'PGbool)
1313rowGtAny = unsafeRowSubqueryExpression "> ANY"
1315-- | >>> printSQL $ true `gteAll` values_ (true `as` #foo)
1316-- TRUE >= ALL (SELECT * FROM (VALUES (TRUE)) AS t ("foo"))
1318 :: Expression commons schemas params grp from ty -- ^ expression
1319 -> Query commons schemas params '[alias ::: ty] -- ^ subquery
1320 -> Expression commons schemas params grp from (nullity 'PGbool)
1321gteAll = unsafeSubqueryExpression ">= ALL"
1323-- | >>> let myRow = 1 `as` #foo :* false `as` #bar :: NP (Aliased (Expression commons schemas params grp from)) '["foo" ::: 'NotNull 'PGint2, "bar" ::: 'NotNull 'PGbool]
1324-- >>> printSQL $ myRow `rowGteAll` values_ myRow
1325-- ROW(1, FALSE) >= ALL (SELECT * FROM (VALUES (1, FALSE)) AS t ("foo", "bar"))
1328 => NP (Aliased (Expression commons schemas params grp from)) row -- ^ row constructor
1329 -> Query commons schemas params row -- ^ subquery
1330 -> Expression commons schemas params grp from (nullity 'PGbool)
1331rowGteAll = unsafeRowSubqueryExpression ">= ALL"
1333-- | >>> printSQL $ true `gteAny` values_ (true `as` #foo)
1334-- TRUE >= ANY (SELECT * FROM (VALUES (TRUE)) AS t ("foo"))
1336 :: Expression commons schemas params grp from ty -- ^ expression
1337 -> Query commons schemas params '[alias ::: ty] -- ^ subquery
1338 -> Expression commons schemas params grp from (nullity 'PGbool)
1339gteAny = unsafeSubqueryExpression ">= ANY"
1341-- | >>> let myRow = 1 `as` #foo :* false `as` #bar :: NP (Aliased (Expression commons schemas params grp from)) '["foo" ::: 'NotNull 'PGint2, "bar" ::: 'NotNull 'PGbool]
1342-- >>> printSQL $ myRow `rowGteAny` values_ myRow
1343-- ROW(1, FALSE) >= ANY (SELECT * FROM (VALUES (1, FALSE)) AS t ("foo", "bar"))
1346 => NP (Aliased (Expression commons schemas params grp from)) row -- ^ row constructor
1347 -> Query commons schemas params row -- ^ subquery
1348 -> Expression commons schemas params grp from (nullity 'PGbool)
1349rowGteAny = unsafeRowSubqueryExpression ">= ANY"
1351-- | A `CommonTableExpression` is an auxiliary statement in a `with` clause.
1352data CommonTableExpression statement
1353 (schemas :: SchemasType)
1354 (params :: [NullityType])
1355 (commons0 :: FromType)
1356 (commons1 :: FromType) where
1357 CommonTableExpression
1358 :: Aliased (statement commons schemas params) (cte ::: common)
1359 -> CommonTableExpression statement schemas params commons (cte ::: common ': commons)
1362 , commons1 ~ (cte ::: common ': commons)
1364 (statement commons schemas params common)
1365 (CommonTableExpression statement schemas params commons commons1) where
1366 statement `as` cte = CommonTableExpression (statement `as` cte)
1369 , commons1 ~ (cte ::: common ': commons)
1371 (statement commons schemas params common)
1372 (AlignedList (CommonTableExpression statement schemas params) commons commons1) where
1373 statement `as` cte = single (statement `as` cte)
1375-- | render a `CommonTableExpression`.
1376renderCommonTableExpression
1377 :: (forall cs ss ps row. statement cs ss ps row -> ByteString) -- ^ render statement
1378 -> CommonTableExpression statement schemas params commons0 commons1 -> ByteString
1379renderCommonTableExpression renderStatement
1380 (CommonTableExpression (statement `As` alias)) =
1381 renderSQL alias <+> "AS" <+> parenthesized (renderStatement statement)
1383-- | render a non-empty `AlignedList` of `CommonTableExpression`s.
1384renderCommonTableExpressions
1385 :: (forall cs ss ps row. statement cs ss ps row -> ByteString) -- ^ render statement
1386 -> CommonTableExpression statement schemas params commons0 commons1
1387 -> AlignedList (CommonTableExpression statement schemas params) commons1 commons2
1389renderCommonTableExpressions renderStatement cte ctes =
1390 renderCommonTableExpression renderStatement cte <> case ctes of
1392 cte' :>> ctes' -> "," <+>
1393 renderCommonTableExpressions renderStatement cte' ctes'
1395-- | `with` provides a way to write auxiliary statements for use in a larger query.
1396-- These statements, referred to as `CommonTableExpression`s, can be thought of as
1397-- defining temporary tables that exist just for one query.
1398class With statement where
1400 :: AlignedList (CommonTableExpression statement schemas params) commons0 commons1
1401 -- ^ common table expressions
1402 -> statement commons1 schemas params row
1404 -> statement commons0 schemas params row
1405instance With Query where
1406 with Done query = query
1407 with (cte :>> ctes) query = UnsafeQuery $
1408 "WITH" <+> renderCommonTableExpressions renderSQL cte ctes
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list