add support for limit and offset
This commit is contained in:
parent
1a8551825d
commit
a81f62b940
|
@ -73,7 +73,8 @@ digitse[+-]digits
|
||||||
> blacklist :: [String]
|
> blacklist :: [String]
|
||||||
> blacklist = ["as", "from", "where", "having", "group", "order"
|
> blacklist = ["as", "from", "where", "having", "group", "order"
|
||||||
> ,"inner", "left", "right", "full", "natural", "join"
|
> ,"inner", "left", "right", "full", "natural", "join"
|
||||||
> ,"on", "using", "when", "then", "case", "end", "order"]
|
> ,"on", "using", "when", "then", "case", "end", "order"
|
||||||
|
> ,"limit", "offset"]
|
||||||
|
|
||||||
TODO: talk about what must be in the blacklist, and what doesn't need
|
TODO: talk about what must be in the blacklist, and what doesn't need
|
||||||
to be.
|
to be.
|
||||||
|
@ -209,12 +210,16 @@ to be.
|
||||||
|
|
||||||
= query expressions
|
= query expressions
|
||||||
|
|
||||||
|
> duplicates :: P Duplicates
|
||||||
|
> duplicates = option All $ try $ choice [All <$ keyword_ "all"
|
||||||
|
> ,Distinct <$ keyword "distinct"]
|
||||||
|
|
||||||
> selectItem :: P (Maybe String, ScalarExpr)
|
> selectItem :: P (Maybe String, ScalarExpr)
|
||||||
> selectItem = flip (,) <$> scalarExpr <*> optionMaybe (try alias)
|
> selectItem = flip (,) <$> scalarExpr <*> optionMaybe (try alias)
|
||||||
> where alias = optional (try (keyword_ "as")) *> identifierString
|
> where alias = optional (try (keyword_ "as")) *> identifierString
|
||||||
|
|
||||||
> selectList :: P [(Maybe String,ScalarExpr)]
|
> selectList :: P [(Maybe String,ScalarExpr)]
|
||||||
> selectList = try (keyword_ "select") *> commaSep1 selectItem
|
> selectList = commaSep1 selectItem
|
||||||
|
|
||||||
> from :: P [TableRef]
|
> from :: P [TableRef]
|
||||||
> from = option [] (try (keyword_ "from") *> commaSep1 tref)
|
> from = option [] (try (keyword_ "from") *> commaSep1 tref)
|
||||||
|
@ -256,8 +261,11 @@ to be.
|
||||||
> alias j = let a1 = optional (try (keyword_ "as")) *> identifierString
|
> alias j = let a1 = optional (try (keyword_ "as")) *> identifierString
|
||||||
> in option j (JoinAlias j <$> try a1)
|
> in option j (JoinAlias j <$> try a1)
|
||||||
|
|
||||||
|
> optionalScalarExpr :: String -> P (Maybe ScalarExpr)
|
||||||
|
> optionalScalarExpr k = optionMaybe (try (keyword_ k) *> scalarExpr)
|
||||||
|
|
||||||
> swhere :: P (Maybe ScalarExpr)
|
> swhere :: P (Maybe ScalarExpr)
|
||||||
> swhere = optionMaybe (try (keyword_ "where") *> scalarExpr)
|
> swhere = optionalScalarExpr "where"
|
||||||
|
|
||||||
> sgroupBy :: P [ScalarExpr]
|
> sgroupBy :: P [ScalarExpr]
|
||||||
> sgroupBy = option [] (try (keyword_ "group")
|
> sgroupBy = option [] (try (keyword_ "group")
|
||||||
|
@ -265,7 +273,7 @@ to be.
|
||||||
> *> commaSep1 scalarExpr)
|
> *> commaSep1 scalarExpr)
|
||||||
|
|
||||||
> having :: P (Maybe ScalarExpr)
|
> having :: P (Maybe ScalarExpr)
|
||||||
> having = optionMaybe (try (keyword_ "having") *> scalarExpr)
|
> having = optionalScalarExpr "having"
|
||||||
|
|
||||||
> orderBy :: P [(ScalarExpr,Direction)]
|
> orderBy :: P [(ScalarExpr,Direction)]
|
||||||
> orderBy = option [] (try (keyword_ "order")
|
> orderBy = option [] (try (keyword_ "order")
|
||||||
|
@ -276,16 +284,26 @@ to be.
|
||||||
> <*> option Asc (choice [Asc <$ keyword_ "asc"
|
> <*> option Asc (choice [Asc <$ keyword_ "asc"
|
||||||
> ,Desc <$ keyword_ "desc"])
|
> ,Desc <$ keyword_ "desc"])
|
||||||
|
|
||||||
|
> limit :: P (Maybe ScalarExpr)
|
||||||
|
> limit = optionalScalarExpr "limit"
|
||||||
|
|
||||||
|
> offset :: P (Maybe ScalarExpr)
|
||||||
|
> offset = optionalScalarExpr "offset"
|
||||||
|
|
||||||
|
|
||||||
> queryExpr :: P QueryExpr
|
> queryExpr :: P QueryExpr
|
||||||
> queryExpr =
|
> queryExpr =
|
||||||
|
> try (keyword_ "select") >>
|
||||||
> Select
|
> Select
|
||||||
> <$> selectList
|
> <$> duplicates
|
||||||
|
> <*> selectList
|
||||||
> <*> from
|
> <*> from
|
||||||
> <*> swhere
|
> <*> swhere
|
||||||
> <*> sgroupBy
|
> <*> sgroupBy
|
||||||
> <*> having
|
> <*> having
|
||||||
> <*> orderBy
|
> <*> orderBy
|
||||||
|
> <*> limit
|
||||||
|
> <*> offset
|
||||||
|
|
||||||
------------------------------------------------
|
------------------------------------------------
|
||||||
|
|
||||||
|
|
|
@ -51,14 +51,20 @@ back into SQL source text. It attempts to format the output nicely.
|
||||||
= query expressions
|
= query expressions
|
||||||
|
|
||||||
> queryExpr :: QueryExpr -> Doc
|
> queryExpr :: QueryExpr -> Doc
|
||||||
> queryExpr (Select sl fr wh gb hv od) =
|
> queryExpr (Select d sl fr wh gb hv od lm off) =
|
||||||
> sep [text "select"
|
> sep [text "select"
|
||||||
|
> ,case d of
|
||||||
|
> All -> empty
|
||||||
|
> Distinct -> text "distinct"
|
||||||
> ,nest 4 $ sep [selectList sl]
|
> ,nest 4 $ sep [selectList sl]
|
||||||
> ,from fr
|
> ,from fr
|
||||||
> ,whr wh
|
> ,maybeScalarExpr "where" wh
|
||||||
> ,grpBy gb
|
> ,grpBy gb
|
||||||
> ,having hv
|
> ,maybeScalarExpr "having" hv
|
||||||
> ,orderBy od]
|
> ,orderBy od
|
||||||
|
> ,maybeScalarExpr "limit" lm
|
||||||
|
> ,maybeScalarExpr "offset" off
|
||||||
|
> ]
|
||||||
|
|
||||||
> selectList :: [(Maybe String, ScalarExpr)] -> Doc
|
> selectList :: [(Maybe String, ScalarExpr)] -> Doc
|
||||||
> selectList is = commaSep $ map si is
|
> selectList is = commaSep $ map si is
|
||||||
|
@ -97,20 +103,16 @@ back into SQL source text. It attempts to format the output nicely.
|
||||||
> joinCond Nothing = empty
|
> joinCond Nothing = empty
|
||||||
> joinCond (Just JoinNatural) = empty
|
> joinCond (Just JoinNatural) = empty
|
||||||
|
|
||||||
> whr :: Maybe ScalarExpr -> Doc
|
> maybeScalarExpr :: String -> Maybe ScalarExpr -> Doc
|
||||||
> whr = maybe empty
|
> maybeScalarExpr k = maybe empty
|
||||||
> (\w -> sep [text "where"
|
> (\e -> sep [text k
|
||||||
> ,nest 4 $ scalarExpr w])
|
> ,nest 4 $ scalarExpr e])
|
||||||
|
|
||||||
> grpBy :: [ScalarExpr] -> Doc
|
> grpBy :: [ScalarExpr] -> Doc
|
||||||
> grpBy [] = empty
|
> grpBy [] = empty
|
||||||
> grpBy gs = sep [text "group by"
|
> grpBy gs = sep [text "group by"
|
||||||
> ,nest 4 $ commaSep $ map scalarExpr gs]
|
> ,nest 4 $ commaSep $ map scalarExpr gs]
|
||||||
|
|
||||||
> having :: Maybe ScalarExpr -> Doc
|
|
||||||
> having = maybe empty
|
|
||||||
> (\w -> sep [text "having"
|
|
||||||
> ,nest 4 $ scalarExpr w])
|
|
||||||
> orderBy :: [(ScalarExpr,Direction)] -> Doc
|
> orderBy :: [(ScalarExpr,Direction)] -> Doc
|
||||||
> orderBy [] = empty
|
> orderBy [] = empty
|
||||||
> orderBy os = sep [text "order by"
|
> orderBy os = sep [text "order by"
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
> ,TableRef(..)
|
> ,TableRef(..)
|
||||||
> ,JoinType(..)
|
> ,JoinType(..)
|
||||||
> ,JoinCondition(..)
|
> ,JoinCondition(..)
|
||||||
|
> ,Duplicates(..)
|
||||||
> ,Direction(..)
|
> ,Direction(..)
|
||||||
> ) where
|
> ) where
|
||||||
|
|
||||||
|
@ -26,23 +27,30 @@
|
||||||
|
|
||||||
> data QueryExpr
|
> data QueryExpr
|
||||||
> = Select
|
> = Select
|
||||||
> {qeSelectList :: [(Maybe String,ScalarExpr)]
|
> {qeDuplicates :: Duplicates
|
||||||
|
> ,qeSelectList :: [(Maybe String,ScalarExpr)]
|
||||||
> ,qeFrom :: [TableRef]
|
> ,qeFrom :: [TableRef]
|
||||||
> ,qeWhere :: Maybe ScalarExpr
|
> ,qeWhere :: Maybe ScalarExpr
|
||||||
> ,qeGroupBy :: [ScalarExpr]
|
> ,qeGroupBy :: [ScalarExpr]
|
||||||
> ,qeHaving :: Maybe ScalarExpr
|
> ,qeHaving :: Maybe ScalarExpr
|
||||||
> ,qeOrderBy :: [(ScalarExpr,Direction)]
|
> ,qeOrderBy :: [(ScalarExpr,Direction)]
|
||||||
|
> ,qeLimit :: Maybe ScalarExpr
|
||||||
|
> ,qeOffset :: Maybe ScalarExpr
|
||||||
> } deriving (Eq,Show)
|
> } deriving (Eq,Show)
|
||||||
|
|
||||||
|
> data Duplicates = Distinct | All deriving (Eq,Show)
|
||||||
> data Direction = Asc | Desc deriving (Eq,Show)
|
> data Direction = Asc | Desc deriving (Eq,Show)
|
||||||
|
|
||||||
> makeSelect :: QueryExpr
|
> makeSelect :: QueryExpr
|
||||||
> makeSelect = Select {qeSelectList = []
|
> makeSelect = Select {qeDuplicates = All
|
||||||
|
> ,qeSelectList = []
|
||||||
> ,qeFrom = []
|
> ,qeFrom = []
|
||||||
> ,qeWhere = Nothing
|
> ,qeWhere = Nothing
|
||||||
> ,qeGroupBy = []
|
> ,qeGroupBy = []
|
||||||
> ,qeHaving = Nothing
|
> ,qeHaving = Nothing
|
||||||
> ,qeOrderBy = []}
|
> ,qeOrderBy = []
|
||||||
|
> ,qeLimit = Nothing
|
||||||
|
> ,qeOffset = Nothing}
|
||||||
|
|
||||||
|
|
||||||
> data TableRef = SimpleTableRef String
|
> data TableRef = SimpleTableRef String
|
||||||
|
|
17
TODO
17
TODO
|
@ -22,12 +22,7 @@ emacs parse error formatting
|
||||||
|
|
||||||
= sql support
|
= sql support
|
||||||
|
|
||||||
distinct/all
|
|
||||||
limit,offset, top
|
|
||||||
|
|
||||||
scalar function syntax:
|
scalar function syntax:
|
||||||
aggregate app
|
|
||||||
window app
|
|
||||||
cast
|
cast
|
||||||
exists, in subquery
|
exists, in subquery
|
||||||
scalar subquery
|
scalar subquery
|
||||||
|
@ -35,16 +30,20 @@ scalar function syntax:
|
||||||
any/some/all
|
any/some/all
|
||||||
between
|
between
|
||||||
is null/ is not null
|
is null/ is not null
|
||||||
review all ansi sql operators
|
|
||||||
interval literal
|
interval literal
|
||||||
typed string lit?
|
typed string lit
|
||||||
|
|
||||||
|
aggregate app
|
||||||
|
window app
|
||||||
|
review all ansi sql operators
|
||||||
placeholder/positional arg
|
placeholder/positional arg
|
||||||
|
|
||||||
other missing operators
|
other missing operators
|
||||||
unary + -
|
|
||||||
row constructors?
|
|
||||||
extract
|
extract
|
||||||
substring
|
substring
|
||||||
|
unary + -
|
||||||
|
|
||||||
|
row constructors?
|
||||||
|
|
||||||
except, intersect, union
|
except, intersect, union
|
||||||
|
|
||||||
|
|
32
Tests.lhs
32
Tests.lhs
|
@ -89,15 +89,31 @@
|
||||||
|
|
||||||
> queryExprParserTests :: TestItem
|
> queryExprParserTests :: TestItem
|
||||||
> queryExprParserTests = Group "queryExprParserTests"
|
> queryExprParserTests = Group "queryExprParserTests"
|
||||||
> [selectLists
|
> [duplicates
|
||||||
|
> ,selectLists
|
||||||
> ,from
|
> ,from
|
||||||
> ,whereClause
|
> ,whereClause
|
||||||
> ,groupByClause
|
> ,groupByClause
|
||||||
> ,having
|
> ,having
|
||||||
> ,orderBy
|
> ,orderBy
|
||||||
|
> ,limit
|
||||||
> ,fullQueries
|
> ,fullQueries
|
||||||
> ]
|
> ]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
> duplicates :: TestItem
|
||||||
|
> duplicates = Group "duplicates" $ map (uncurry TestQueryExpr)
|
||||||
|
> [("select a from t" ,ms All)
|
||||||
|
> ,("select all a from t" ,ms All)
|
||||||
|
> ,("select distinct a from t", ms Distinct)
|
||||||
|
> ]
|
||||||
|
> where
|
||||||
|
> ms d = makeSelect
|
||||||
|
> {qeDuplicates = d
|
||||||
|
> ,qeSelectList = [(Nothing,Iden "a")]
|
||||||
|
> ,qeFrom = [SimpleTableRef "t"]}
|
||||||
|
|
||||||
> selectLists :: TestItem
|
> selectLists :: TestItem
|
||||||
> selectLists = Group "selectLists" $ map (uncurry TestQueryExpr)
|
> selectLists = Group "selectLists" $ map (uncurry TestQueryExpr)
|
||||||
> [("select 1",
|
> [("select 1",
|
||||||
|
@ -212,6 +228,20 @@
|
||||||
> ,qeFrom = [SimpleTableRef "t"]
|
> ,qeFrom = [SimpleTableRef "t"]
|
||||||
> ,qeOrderBy = o}
|
> ,qeOrderBy = o}
|
||||||
|
|
||||||
|
> limit :: TestItem
|
||||||
|
> limit = Group "limit" $ map (uncurry TestQueryExpr)
|
||||||
|
> [("select a from t limit 10"
|
||||||
|
> ,ms (Just $ NumLit "10") Nothing)
|
||||||
|
> ,("select a from t limit 10 offset 10"
|
||||||
|
> ,ms (Just $ NumLit "10") (Just $ NumLit "10"))
|
||||||
|
> ]
|
||||||
|
> where
|
||||||
|
> ms l o = makeSelect
|
||||||
|
> {qeSelectList = [(Nothing,Iden "a")]
|
||||||
|
> ,qeFrom = [SimpleTableRef "t"]
|
||||||
|
> ,qeLimit = l
|
||||||
|
> ,qeOffset = o}
|
||||||
|
|
||||||
> fullQueries :: TestItem
|
> fullQueries :: TestItem
|
||||||
> fullQueries = Group "queries" $ map (uncurry TestQueryExpr)
|
> fullQueries = Group "queries" $ map (uncurry TestQueryExpr)
|
||||||
> [("select count(*) from t"
|
> [("select count(*) from t"
|
||||||
|
|
Loading…
Reference in a new issue