postgresql-syntax-0.5.0.2: library-internal/PostgresqlSyntax/Ast/SelectClause.hs
module PostgresqlSyntax.Ast.SelectClause where
import PostgresqlSyntax.Algebra
import {-# SOURCE #-} PostgresqlSyntax.Ast.SelectWithParens (SelectWithParens)
import {-# SOURCE #-} PostgresqlSyntax.Ast.SimpleSelect (SimpleSelect)
import qualified PostgresqlSyntax.Helpers.Gens as Gens
import PostgresqlSyntax.Prelude
import qualified Test.QuickCheck as Qc
-- |
-- ==== References
-- @
-- select_clause:
-- | simple_select
-- | select_with_parens
-- @
--
-- This type's own 'IsAst' instance is a plain, non-recursive-suffix-aware
-- dispatch — the real @UNION@\/@INTERSECT@\/@EXCEPT@-chaining grammar
-- (where a @select_clause@ extends into a bigger
-- 'PostgresqlSyntax.Ast.SimpleSelect' via its @BinSimpleSelect@
-- constructor) is hosted in "PostgresqlSyntax.Ast.SimpleSelect" instead,
-- since only that module can construct @BinSimpleSelect@ values. See its
-- module documentation.
data SelectClause
= SimpleSelectSelectClause SimpleSelect
| WithParensSelectClause SelectWithParens
deriving (Show, Generic, Eq, Ord, Data)
instance IsAst SelectClause where
toTextBuilder settings = \case
SimpleSelectSelectClause a -> toTextBuilder settings a
WithParensSelectClause a -> toTextBuilder settings a
-- ==== Law
--
-- @parser = parseMaybeExtended \@SelectClause@ — see
-- 'PostgresqlSyntax.Ast.SimpleSelect'\'s 'PostgresqlSyntax.Algebra.Extends'
-- instance for the real @select_clause@ grammar, including
-- @UNION@\/@INTERSECT@\/@EXCEPT@-chaining.
parser settings = parseMaybeExtended @SimpleSelect settings
-- |
-- Every @select_clause@ production except the left-recursive ones (those
-- are the @UNION@\/@INTERSECT@\/@EXCEPT@ continuations, hosted by
-- "PostgresqlSyntax.Ast.SimpleSelect"\'s
-- 'PostgresqlSyntax.Algebra.Extends' instance).
instance LeftRecursive SelectClause where
parseBase settings =
asum
[ WithParensSelectClause <$> parser settings,
SimpleSelectSelectClause <$> parseBase @SimpleSelect settings
]
-- |
-- A 'SimpleSelect' embeds trivially into a 'SelectClause' (it's one of its
-- two alternatives), and a 'SelectClause' of that exact shape is
-- recognizable back as one. Needed so
-- "PostgresqlSyntax.Ast.SimpleSelect"\'s
-- 'PostgresqlSyntax.Algebra.Extends' instance can fold a chain of
-- @UNION@\/@INTERSECT@\/@EXCEPT@ items onto a leading 'SelectClause'.
instance Refines SimpleSelect SelectClause where
embed = SimpleSelectSelectClause
project = \case
SimpleSelectSelectClause a -> Just a
_ -> Nothing
instance Qc.Arbitrary SelectClause where
shrink = Qc.genericShrink
arbitrary =
Qc.frequency
[ (3, SimpleSelectSelectClause <$> Gens.downscale Qc.arbitrary),
(1, WithParensSelectClause <$> Gens.downscale Qc.arbitrary)
]