postgresql-syntax-0.5.0.0: library-internal/PostgresqlSyntax/Ast/LimitClause.hs
module PostgresqlSyntax.Ast.LimitClause where
import qualified HeadedMegaparsec as Parser
import {-# SOURCE #-} PostgresqlSyntax.Ast.AExpr (AExpr)
import PostgresqlSyntax.Ast.SelectFetchFirstValue
import PostgresqlSyntax.Ast.SelectLimitValue
import qualified PostgresqlSyntax.Helpers.Gens as Gens
import qualified PostgresqlSyntax.Helpers.Parsers as Parsers
import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders
import PostgresqlSyntax.IsAst
import PostgresqlSyntax.Prelude
import qualified Test.QuickCheck as Qc
-- |
-- ==== References
-- @
-- limit_clause:
-- | LIMIT select_limit_value
-- | LIMIT select_limit_value ',' select_offset_value
-- | FETCH first_or_next select_fetch_first_value row_or_rows ONLY
-- | FETCH first_or_next row_or_rows ONLY
-- select_offset_value:
-- | a_expr
-- first_or_next:
-- | FIRST_P
-- | NEXT
-- row_or_rows:
-- | ROW
-- | ROWS
-- @
data LimitClause
= LimitLimitClause SelectLimitValue (Maybe AExpr)
| FetchOnlyLimitClause Bool (Maybe SelectFetchFirstValue) Bool
deriving (Show, Generic, Eq, Ord, Data)
instance IsAst LimitClause where
toTextBuilder settings = \case
LimitLimitClause a b -> "LIMIT " <> toTextBuilder settings a <> foldMap (mappend ", " . toTextBuilder settings) b
FetchOnlyLimitClause a b c ->
TextBuilders.optLexemes
[ Just "FETCH",
Just (firstOrNext a),
fmap (toTextBuilder settings) b,
Just (rowOrRows c),
Just "ONLY"
]
where
firstOrNext = bool "FIRST" "NEXT"
rowOrRows = bool "ROW" "ROWS"
parser settings =
( do
Parsers.keyword "limit"
Parser.endHead
Parsers.space1
a <- parser settings
b <- optional $ do
Parsers.commaSeparator
parser settings
return (LimitLimitClause a b)
)
<|> ( do
Parsers.keyword "fetch"
Parser.endHead
Parsers.space1
a <- firstOrNext
Parsers.space1
asum
[ do
b <- rowOrRows
Parsers.space1
Parsers.keyword "only"
return (FetchOnlyLimitClause a Nothing b),
do
b <- parser settings
Parsers.space1
c <- rowOrRows
Parsers.space1
Parsers.keyword "only"
return (FetchOnlyLimitClause a (Just b) c)
]
)
where
firstOrNext =
False
<$ Parsers.keyword "first"
<|> True
<$ Parsers.keyword "next"
rowOrRows =
True
<$ Parsers.keyword "rows"
<|> False
<$ Parsers.keyword "row"
instance Qc.Arbitrary LimitClause where
shrink = Qc.genericShrink
arbitrary =
Qc.oneof
[ LimitLimitClause <$> Qc.arbitrary <*> Gens.terminatingMaybe (Gens.downscale Qc.arbitrary),
FetchOnlyLimitClause <$> Qc.arbitrary <*> Gens.terminatingMaybe Qc.arbitrary <*> Qc.arbitrary
]