add support for nulls first/last
This commit is contained in:
parent
e85ab8b831
commit
ebe522b21d
|
@ -84,15 +84,15 @@ the fixity code.
|
||||||
> Star -> str ('v':show e)
|
> Star -> str ('v':show e)
|
||||||
> AggregateApp nm d es od ->
|
> AggregateApp nm d es od ->
|
||||||
> HSE.App (var ('a':name nm))
|
> HSE.App (var ('a':name nm))
|
||||||
> $ HSE.List [str $ show (d,map snd od)
|
> $ HSE.List [str $ show (d,orderInf od)
|
||||||
> ,HSE.List $ map toHaskell es
|
> ,HSE.List $ map toHaskell es
|
||||||
> ,HSE.List $ map (toHaskell . fst) od]
|
> ,HSE.List $ orderExps od]
|
||||||
> WindowApp nm es pb od r ->
|
> WindowApp nm es pb od r ->
|
||||||
> HSE.App (var ('w':name nm))
|
> HSE.App (var ('w':name nm))
|
||||||
> $ HSE.List [str $ show (map snd od, r)
|
> $ HSE.List [str $ show (orderInf od, r)
|
||||||
> ,HSE.List $ map toHaskell es
|
> ,HSE.List $ map toHaskell es
|
||||||
> ,HSE.List $ map toHaskell pb
|
> ,HSE.List $ map toHaskell pb
|
||||||
> ,HSE.List $ map (toHaskell . fst) od]
|
> ,HSE.List $ orderExps od]
|
||||||
> PrefixOp nm e0 ->
|
> PrefixOp nm e0 ->
|
||||||
> HSE.App (HSE.Var $ sym $ name nm) (toHaskell e0)
|
> HSE.App (HSE.Var $ sym $ name nm) (toHaskell e0)
|
||||||
> PostfixOp nm e0 ->
|
> PostfixOp nm e0 ->
|
||||||
|
@ -119,6 +119,10 @@ the fixity code.
|
||||||
> name n = case n of
|
> name n = case n of
|
||||||
> QName q -> "\"" ++ q
|
> QName q -> "\"" ++ q
|
||||||
> Name m -> m
|
> Name m -> m
|
||||||
|
> orderExps = map (toHaskell . (\(OrderField a _ _) -> a))
|
||||||
|
> orderInf = map (\(OrderField _ b c) -> (b,c))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
> toSql :: HSE.Exp -> ScalarExpr
|
> toSql :: HSE.Exp -> ScalarExpr
|
||||||
|
@ -135,17 +139,17 @@ the fixity code.
|
||||||
> (HSE.List [HSE.Lit (HSE.String vs)
|
> (HSE.List [HSE.Lit (HSE.String vs)
|
||||||
> ,HSE.List es
|
> ,HSE.List es
|
||||||
> ,HSE.List od]) ->
|
> ,HSE.List od]) ->
|
||||||
> let (d,dir) = read vs
|
> let (d,oinf) = read vs
|
||||||
> in AggregateApp (unname i) d (map toSql es)
|
> in AggregateApp (unname i) d (map toSql es)
|
||||||
> $ zip (map toSql od) dir
|
> $ sord oinf od
|
||||||
> HSE.App (HSE.Var (HSE.UnQual (HSE.Ident ('w':i))))
|
> HSE.App (HSE.Var (HSE.UnQual (HSE.Ident ('w':i))))
|
||||||
> (HSE.List [HSE.Lit (HSE.String vs)
|
> (HSE.List [HSE.Lit (HSE.String vs)
|
||||||
> ,HSE.List es
|
> ,HSE.List es
|
||||||
> ,HSE.List pb
|
> ,HSE.List pb
|
||||||
> ,HSE.List od]) ->
|
> ,HSE.List od]) ->
|
||||||
> let (dir,r) = read vs
|
> let (oinf,r) = read vs
|
||||||
> in WindowApp (unname i) (map toSql es) (map toSql pb)
|
> in WindowApp (unname i) (map toSql es) (map toSql pb)
|
||||||
> (zip (map toSql od) dir) r
|
> (sord oinf od) r
|
||||||
> HSE.App (HSE.Var (HSE.UnQual (HSE.Symbol ('p':nm)))) e0 ->
|
> HSE.App (HSE.Var (HSE.UnQual (HSE.Symbol ('p':nm)))) e0 ->
|
||||||
> PostfixOp (unname nm) $ toSql e0
|
> PostfixOp (unname nm) $ toSql e0
|
||||||
> HSE.App (HSE.Var (HSE.UnQual (HSE.Symbol nm))) e0 ->
|
> HSE.App (HSE.Var (HSE.UnQual (HSE.Symbol nm))) e0 ->
|
||||||
|
@ -165,6 +169,7 @@ the fixity code.
|
||||||
> in In b (toSql e0) sq
|
> in In b (toSql e0) sq
|
||||||
> _ -> err e
|
> _ -> err e
|
||||||
> where
|
> where
|
||||||
|
> sord = zipWith (\(i0,i1) ce -> OrderField (toSql ce) i0 i1)
|
||||||
> ltom (HSE.List []) = Nothing
|
> ltom (HSE.List []) = Nothing
|
||||||
> ltom (HSE.List [ex]) = Just $ toSql ex
|
> ltom (HSE.List [ex]) = Just $ toSql ex
|
||||||
> ltom ex = err ex
|
> ltom ex = err ex
|
||||||
|
|
|
@ -605,12 +605,17 @@ where, having, limit, offset).
|
||||||
> having :: P ScalarExpr
|
> having :: P ScalarExpr
|
||||||
> having = keywordScalarExpr "having"
|
> having = keywordScalarExpr "having"
|
||||||
|
|
||||||
> orderBy :: P [(ScalarExpr,Direction)]
|
> orderBy :: P [OrderField]
|
||||||
> orderBy = try (keyword_ "order") *> keyword_ "by" *> commaSep1 ob
|
> orderBy = try (keyword_ "order") *> keyword_ "by" *> commaSep1 ob
|
||||||
> where
|
> where
|
||||||
> ob = (,) <$> scalarExpr
|
> ob = OrderField
|
||||||
> <*> option Asc (choice [Asc <$ keyword_ "asc"
|
> <$> scalarExpr
|
||||||
> ,Desc <$ keyword_ "desc"])
|
> <*> option Asc (choice [Asc <$ keyword_ "asc"
|
||||||
|
> ,Desc <$ keyword_ "desc"])
|
||||||
|
> <*> option NullsOrderDefault
|
||||||
|
> (try (keyword_ "nulls" >>
|
||||||
|
> choice [NullsFirst <$ keyword "first"
|
||||||
|
> ,NullsLast <$ keyword "last"]))
|
||||||
|
|
||||||
allows offset and fetch in either order
|
allows offset and fetch in either order
|
||||||
+ postgresql offset without row(s) and limit instead of fetch also
|
+ postgresql offset without row(s) and limit instead of fetch also
|
||||||
|
|
|
@ -260,13 +260,18 @@
|
||||||
> grpBy gs = sep [text "group by"
|
> grpBy gs = sep [text "group by"
|
||||||
> ,nest 9 $ commaSep $ map scalarExpr gs]
|
> ,nest 9 $ commaSep $ map scalarExpr gs]
|
||||||
|
|
||||||
> orderBy :: [(ScalarExpr,Direction)] -> Doc
|
> orderBy :: [OrderField] -> Doc
|
||||||
> orderBy [] = empty
|
> orderBy [] = empty
|
||||||
> orderBy os = sep [text "order by"
|
> orderBy os = sep [text "order by"
|
||||||
> ,nest 9 $ commaSep $ map f os]
|
> ,nest 9 $ commaSep $ map f os]
|
||||||
> where
|
> where
|
||||||
> f (e,Asc) = scalarExpr e
|
> f (OrderField e d n) =
|
||||||
> f (e,Desc) = scalarExpr e <+> text "desc"
|
> scalarExpr e
|
||||||
|
> <+> (if d == Asc then empty else text "desc")
|
||||||
|
> <+> (case n of
|
||||||
|
> NullsOrderDefault -> empty
|
||||||
|
> NullsFirst -> text "nulls" <+> text "first"
|
||||||
|
> NullsLast -> text "nulls" <+> text "last")
|
||||||
|
|
||||||
= utils
|
= utils
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,9 @@
|
||||||
> ,Name(..)
|
> ,Name(..)
|
||||||
> ,TypeName(..)
|
> ,TypeName(..)
|
||||||
> ,Duplicates(..)
|
> ,Duplicates(..)
|
||||||
|
> ,OrderField(..)
|
||||||
> ,Direction(..)
|
> ,Direction(..)
|
||||||
|
> ,NullsOrder(..)
|
||||||
> ,InThing(..)
|
> ,InThing(..)
|
||||||
> ,SubQueryExprType(..)
|
> ,SubQueryExprType(..)
|
||||||
> ,Frame(..)
|
> ,Frame(..)
|
||||||
|
@ -65,7 +67,7 @@
|
||||||
> {aggName :: Name -- ^ aggregate function name
|
> {aggName :: Name -- ^ aggregate function name
|
||||||
> ,aggDistinct :: (Maybe Duplicates)-- ^ distinct
|
> ,aggDistinct :: (Maybe Duplicates)-- ^ distinct
|
||||||
> ,aggArgs :: [ScalarExpr]-- ^ args
|
> ,aggArgs :: [ScalarExpr]-- ^ args
|
||||||
> ,aggOrderBy :: [(ScalarExpr,Direction)] -- ^ order by
|
> ,aggOrderBy :: [OrderField] -- ^ order by
|
||||||
> }
|
> }
|
||||||
> -- | window application, which adds over (partition by a order
|
> -- | window application, which adds over (partition by a order
|
||||||
> -- by b) to regular function application. Explicit frames are
|
> -- by b) to regular function application. Explicit frames are
|
||||||
|
@ -74,7 +76,7 @@
|
||||||
> {wnName :: Name -- ^ window function name
|
> {wnName :: Name -- ^ window function name
|
||||||
> ,wnArgs :: [ScalarExpr] -- ^ args
|
> ,wnArgs :: [ScalarExpr] -- ^ args
|
||||||
> ,wnPartition :: [ScalarExpr] -- ^ partition by
|
> ,wnPartition :: [ScalarExpr] -- ^ partition by
|
||||||
> ,wnOrderBy :: [(ScalarExpr,Direction)] -- ^ order by
|
> ,wnOrderBy :: [OrderField] -- ^ order by
|
||||||
> ,wnFrame :: Maybe Frame -- ^ frame clause
|
> ,wnFrame :: Maybe Frame -- ^ frame clause
|
||||||
> }
|
> }
|
||||||
> -- | Infix binary operators. This is used for symbol operators
|
> -- | Infix binary operators. This is used for symbol operators
|
||||||
|
@ -141,6 +143,14 @@
|
||||||
> | SqAny
|
> | SqAny
|
||||||
> deriving (Eq,Show,Read)
|
> deriving (Eq,Show,Read)
|
||||||
|
|
||||||
|
> data OrderField = OrderField ScalarExpr Direction NullsOrder
|
||||||
|
> deriving (Eq,Show,Read)
|
||||||
|
|
||||||
|
> data NullsOrder = NullsOrderDefault
|
||||||
|
> | NullsFirst
|
||||||
|
> | NullsLast
|
||||||
|
> deriving (Eq,Show,Read)
|
||||||
|
|
||||||
> -- | Represents the frame clause of a window
|
> -- | Represents the frame clause of a window
|
||||||
> -- this can be [range | rows] frame_start
|
> -- this can be [range | rows] frame_start
|
||||||
> -- or [range | rows] between frame_start and frame_end
|
> -- or [range | rows] between frame_start and frame_end
|
||||||
|
@ -181,7 +191,7 @@
|
||||||
> ,qeWhere :: Maybe ScalarExpr
|
> ,qeWhere :: Maybe ScalarExpr
|
||||||
> ,qeGroupBy :: [ScalarExpr]
|
> ,qeGroupBy :: [ScalarExpr]
|
||||||
> ,qeHaving :: Maybe ScalarExpr
|
> ,qeHaving :: Maybe ScalarExpr
|
||||||
> ,qeOrderBy :: [(ScalarExpr,Direction)]
|
> ,qeOrderBy :: [OrderField]
|
||||||
> ,qeOffset :: Maybe ScalarExpr
|
> ,qeOffset :: Maybe ScalarExpr
|
||||||
> ,qeFetch :: Maybe ScalarExpr
|
> ,qeFetch :: Maybe ScalarExpr
|
||||||
> }
|
> }
|
||||||
|
|
|
@ -33,7 +33,7 @@ Some tests for parsing full queries.
|
||||||
> ,qeGroupBy = [Iden "a"]
|
> ,qeGroupBy = [Iden "a"]
|
||||||
> ,qeHaving = Just $ BinOp (App "count" [NumLit "1"])
|
> ,qeHaving = Just $ BinOp (App "count" [NumLit "1"])
|
||||||
> ">" (NumLit "5")
|
> ">" (NumLit "5")
|
||||||
> ,qeOrderBy = [(Iden "s", Asc)]
|
> ,qeOrderBy = [OrderField (Iden "s") Asc NullsOrderDefault]
|
||||||
> }
|
> }
|
||||||
> )
|
> )
|
||||||
> ]
|
> ]
|
||||||
|
|
|
@ -108,16 +108,23 @@ These are a few misc tests which don't fit anywhere else.
|
||||||
> orderBy :: TestItem
|
> orderBy :: TestItem
|
||||||
> orderBy = Group "orderBy" $ map (uncurry TestQueryExpr)
|
> orderBy = Group "orderBy" $ map (uncurry TestQueryExpr)
|
||||||
> [("select a from t order by a"
|
> [("select a from t order by a"
|
||||||
> ,ms [(Iden "a", Asc)])
|
> ,ms [OrderField (Iden "a") Asc NullsOrderDefault])
|
||||||
|
|
||||||
> ,("select a from t order by a, b"
|
> ,("select a from t order by a, b"
|
||||||
> ,ms [(Iden "a", Asc), (Iden "b", Asc)])
|
> ,ms [OrderField (Iden "a") Asc NullsOrderDefault
|
||||||
|
> ,OrderField (Iden "b") Asc NullsOrderDefault])
|
||||||
|
|
||||||
> ,("select a from t order by a asc"
|
> ,("select a from t order by a asc"
|
||||||
> ,ms [(Iden "a", Asc)])
|
> ,ms [OrderField (Iden "a") Asc NullsOrderDefault])
|
||||||
|
|
||||||
> ,("select a from t order by a desc, b desc"
|
> ,("select a from t order by a desc, b desc"
|
||||||
> ,ms [(Iden "a", Desc), (Iden "b", Desc)])
|
> ,ms [OrderField (Iden "a") Desc NullsOrderDefault
|
||||||
|
> ,OrderField (Iden "b") Desc NullsOrderDefault])
|
||||||
|
|
||||||
|
> ,("select a from t order by a desc nulls first, b desc nulls last"
|
||||||
|
> ,ms [OrderField (Iden "a") Desc NullsFirst
|
||||||
|
> ,OrderField (Iden "b") Desc NullsLast])
|
||||||
|
|
||||||
> ]
|
> ]
|
||||||
> where
|
> where
|
||||||
> ms o = makeSelect {qeSelectList = [(Nothing,Iden "a")]
|
> ms o = makeSelect {qeSelectList = [(Nothing,Iden "a")]
|
||||||
|
|
|
@ -213,7 +213,7 @@ Tests for parsing scalar expressions
|
||||||
> [("count(*)",App "count" [Star])
|
> [("count(*)",App "count" [Star])
|
||||||
|
|
||||||
> ,("sum(a order by a)"
|
> ,("sum(a order by a)"
|
||||||
> ,AggregateApp "sum" Nothing [Iden "a"] [(Iden "a", Asc)])
|
> ,AggregateApp "sum" Nothing [Iden "a"] [(OrderField (Iden "a") Asc NullsOrderDefault)])
|
||||||
|
|
||||||
> ,("sum(all a)"
|
> ,("sum(all a)"
|
||||||
> ,AggregateApp "sum" (Just All) [Iden "a"] [])
|
> ,AggregateApp "sum" (Just All) [Iden "a"] [])
|
||||||
|
@ -234,37 +234,37 @@ Tests for parsing scalar expressions
|
||||||
> ,WindowApp "max" [Iden "a"] [Iden "b",Iden "c"] [] Nothing)
|
> ,WindowApp "max" [Iden "a"] [Iden "b",Iden "c"] [] Nothing)
|
||||||
|
|
||||||
> ,("sum(a) over (order by b)"
|
> ,("sum(a) over (order by b)"
|
||||||
> ,WindowApp "sum" [Iden "a"] [] [(Iden "b", Asc)] Nothing)
|
> ,WindowApp "sum" [Iden "a"] [] [(OrderField (Iden "b") Asc NullsOrderDefault)] Nothing)
|
||||||
|
|
||||||
> ,("sum(a) over (order by b desc,c)"
|
> ,("sum(a) over (order by b desc,c)"
|
||||||
> ,WindowApp "sum" [Iden "a"] [] [(Iden "b", Desc)
|
> ,WindowApp "sum" [Iden "a"] [] [(OrderField (Iden "b") Desc NullsOrderDefault)
|
||||||
> ,(Iden "c", Asc)] Nothing)
|
> ,(OrderField (Iden "c") Asc NullsOrderDefault)] Nothing)
|
||||||
|
|
||||||
> ,("sum(a) over (partition by b order by c)"
|
> ,("sum(a) over (partition by b order by c)"
|
||||||
> ,WindowApp "sum" [Iden "a"] [Iden "b"] [(Iden "c", Asc)] Nothing)
|
> ,WindowApp "sum" [Iden "a"] [Iden "b"] [OrderField (Iden "c") Asc NullsOrderDefault] Nothing)
|
||||||
|
|
||||||
> ,("sum(a) over (partition by b order by c range unbounded preceding)"
|
> ,("sum(a) over (partition by b order by c range unbounded preceding)"
|
||||||
> ,WindowApp "sum" [Iden "a"] [Iden "b"] [(Iden "c", Asc)]
|
> ,WindowApp "sum" [Iden "a"] [Iden "b"] [OrderField (Iden "c") Asc NullsOrderDefault]
|
||||||
> $ Just $ FrameFrom FrameRange UnboundedPreceding)
|
> $ Just $ FrameFrom FrameRange UnboundedPreceding)
|
||||||
|
|
||||||
> ,("sum(a) over (partition by b order by c range 5 preceding)"
|
> ,("sum(a) over (partition by b order by c range 5 preceding)"
|
||||||
> ,WindowApp "sum" [Iden "a"] [Iden "b"] [(Iden "c", Asc)]
|
> ,WindowApp "sum" [Iden "a"] [Iden "b"] [OrderField (Iden "c") Asc NullsOrderDefault]
|
||||||
> $ Just $ FrameFrom FrameRange $ Preceding (NumLit "5"))
|
> $ Just $ FrameFrom FrameRange $ Preceding (NumLit "5"))
|
||||||
|
|
||||||
> ,("sum(a) over (partition by b order by c range current row)"
|
> ,("sum(a) over (partition by b order by c range current row)"
|
||||||
> ,WindowApp "sum" [Iden "a"] [Iden "b"] [(Iden "c", Asc)]
|
> ,WindowApp "sum" [Iden "a"] [Iden "b"] [OrderField (Iden "c") Asc NullsOrderDefault]
|
||||||
> $ Just $ FrameFrom FrameRange Current)
|
> $ Just $ FrameFrom FrameRange Current)
|
||||||
|
|
||||||
> ,("sum(a) over (partition by b order by c rows 5 following)"
|
> ,("sum(a) over (partition by b order by c rows 5 following)"
|
||||||
> ,WindowApp "sum" [Iden "a"] [Iden "b"] [(Iden "c", Asc)]
|
> ,WindowApp "sum" [Iden "a"] [Iden "b"] [OrderField (Iden "c") Asc NullsOrderDefault]
|
||||||
> $ Just $ FrameFrom FrameRows $ Following (NumLit "5"))
|
> $ Just $ FrameFrom FrameRows $ Following (NumLit "5"))
|
||||||
|
|
||||||
> ,("sum(a) over (partition by b order by c range unbounded following)"
|
> ,("sum(a) over (partition by b order by c range unbounded following)"
|
||||||
> ,WindowApp "sum" [Iden "a"] [Iden "b"] [(Iden "c", Asc)]
|
> ,WindowApp "sum" [Iden "a"] [Iden "b"] [OrderField (Iden "c") Asc NullsOrderDefault]
|
||||||
> $ Just $ FrameFrom FrameRange UnboundedFollowing)
|
> $ Just $ FrameFrom FrameRange UnboundedFollowing)
|
||||||
|
|
||||||
> ,("sum(a) over (partition by b order by c range between 5 preceding and 5 following)"
|
> ,("sum(a) over (partition by b order by c range between 5 preceding and 5 following)"
|
||||||
> ,WindowApp "sum" [Iden "a"] [Iden "b"] [(Iden "c", Asc)]
|
> ,WindowApp "sum" [Iden "a"] [Iden "b"] [OrderField (Iden "c") Asc NullsOrderDefault]
|
||||||
> $ Just $ FrameBetween FrameRange (Preceding (NumLit "5")) (Following (NumLit "5")))
|
> $ Just $ FrameBetween FrameRange (Preceding (NumLit "5")) (Following (NumLit "5")))
|
||||||
|
|
||||||
> ]
|
> ]
|
||||||
|
|
Loading…
Reference in a new issue