diff --git a/TODO b/TODO index dd1fb8b..cf6af47 100644 --- a/TODO +++ b/TODO @@ -34,7 +34,7 @@ keyword tree support prefix mode so can start from already parsed do the final big left factor: typenames, interval lits, iden + suffixes -left factor/try removal summary (needs updating): +left factor/try removal summary (this list needs updating): identifier starts: interval literal @@ -61,19 +61,24 @@ rules for changing the multi keyword parsing: if the keyword is optionally followed by another, e.g. with recursive, then don't do this. +change join defaults to be defaults rough SQL 2011 todo, including tests to write: review the commented out reserved keyword entries and work out how to fix +test case insensitvity and case preservation + big areas: window functions nested window functions case -table ref -joined table -group by + +table ref: tablesample, time period spec, only, unnest, table, lateral + bug +joined table: partitioned joins +group by: set quantifier window clause other areas: @@ -113,11 +118,15 @@ member submultiset period -create list of unsupported syntax: xml, ref, subtypes, modules? +alias for * in select list +create list of unsupported syntax: xml, ref, subtypes, modules? +only --- + + after next release review areas where this parser is too permissive, e.g. value diff --git a/tools/Language/SQL/SimpleSQL/SQL2011.lhs b/tools/Language/SQL/SimpleSQL/SQL2011.lhs index d88ea48..0df8588 100644 --- a/tools/Language/SQL/SimpleSQL/SQL2011.lhs +++ b/tools/Language/SQL/SimpleSQL/SQL2011.lhs @@ -2501,10 +2501,12 @@ Specify construction of a multiset. > [rowValueConstructor > ,rowValueExpression > ,tableValueConstructor +> ,fromClause > ,tableReference > ,joinedTable > ,whereClause > ,groupByClause +> ,havingClause > ,windowClause > ,querySpecification > ,withQueryExpression @@ -2635,11 +2637,26 @@ Specify a table derived from one or more tables. ::=
[ {
}... ] +> fromClause :: TestItem +> fromClause = Group "fromClause" +> $ map (uncurry TestQueryExpr) +> [("select * from tbl1,tbl2" +> ,makeSelect +> {qeSelectList = [(Star, Nothing)] +> ,qeFrom = [TRSimple [Name "tbl1"], TRSimple [Name "tbl2"]] +> })] + + == 7.6
Function Reference a table. +> tableReference :: TestItem +> tableReference = Group "table reference" +> $ map (uncurry TestQueryExpr) +> [("select * from t", sel) +
::=
|
::=
[ ] @@ -2657,7 +2674,7 @@ Reference a table. ::=
::= -
[ ] +
[ ] [ [ AS ] [ ] ] | [ AS ] @@ -2680,6 +2697,8 @@ Reference a table. AND | FOR SYSTEM_TIME FROM TO +TODO: query system time period spec + ::= ::= @@ -2688,6 +2707,8 @@ Reference a table. ::= ONLY
+TODO: only + ::= LATERAL
::= @@ -2721,10 +2742,53 @@ Reference a table. | -> tableReference :: TestItem -> tableReference = Group "table reference" -> [-- todo: table reference + +> -- table or query name +> ,("select * from t u", a sel) +> ,("select * from t as u", a sel) +> ,("select * from t u(a,b)", sel1 ) +> ,("select * from t as u(a,b)", sel1) +> -- derived table TODO: realistic example +> ,("select * from (select * from t) u" +> ,a $ sel {qeFrom = [TRQueryExpr sel]}) +> -- lateral TODO: realistic example +> ,("select * from lateral t" +> ,af TRLateral sel) +> -- TODO: bug, lateral should bind more tightly than the alias +> --,("select * from lateral t u" +> -- ,a $ af sel TRLateral) +> -- collection TODO: realistic example +> -- TODO: make it work +> --,("select * from unnest(a)", undefined) +> --,("select * from unnest(a,b)", undefined) +> --,("select * from unnest(a,b) with ordinality", undefined) +> --,("select * from unnest(a,b) with ordinality u", undefined) +> --,("select * from unnest(a,b) with ordinality as u", undefined) +> -- table fn TODO: realistic example +> -- TODO: make it work +> --,("select * from table(a)", undefined) +> -- parens +> ,("select * from (a join b)", jsel) +> ,("select * from (a join b) u", a jsel) +> ,("select * from ((a join b)) u", a $ af TRParens jsel) +> ,("select * from ((a join b) u) u", a $ af TRParens $ a jsel) > ] +> where +> sel = makeSelect +> {qeSelectList = [(Star, Nothing)] +> ,qeFrom = [TRSimple [Name "t"]]} +> af f s = s {qeFrom = map f (qeFrom s)} +> a s = af (\x -> TRAlias x $ Alias (Name "u") Nothing) s +> sel1 = makeSelect +> {qeSelectList = [(Star, Nothing)] +> ,qeFrom = [TRAlias (TRSimple [Name "t"]) +> $ Alias (Name "u") $ Just [Name "a", Name "b"]]} +> jsel = sel {qeFrom = +> [TRParens $ TRJoin (TRSimple [Name "a"]) +> False +> JInner +> (TRSimple [Name "b"]) +> Nothing]} == 7.7 @@ -2771,8 +2835,51 @@ Specify a table derived from a Cartesian product, inner join, or outer join. > joinedTable :: TestItem > joinedTable = Group "joined table" -> [-- todo: joined table +> $ map (uncurry TestQueryExpr) +> [("select * from a cross join b" +> ,sel $ TRJoin a False JCross b Nothing) +> ,("select * from a join b on true" +> ,sel $ TRJoin a False JInner b +> (Just $ JoinOn $ Iden [Name "true"])) +> ,("select * from a join b using (c)" +> ,sel $ TRJoin a False JInner b +> (Just $ JoinUsing [Name "c"])) +> ,("select * from a inner join b on true" +> ,sel $ TRJoin a False JInner b +> (Just $ JoinOn $ Iden [Name "true"])) +> ,("select * from a left join b on true" +> ,sel $ TRJoin a False JLeft b +> (Just $ JoinOn $ Iden [Name "true"])) +> ,("select * from a left outer join b on true" +> ,sel $ TRJoin a False JLeft b +> (Just $ JoinOn $ Iden [Name "true"])) +> ,("select * from a right join b on true" +> ,sel $ TRJoin a False JRight b +> (Just $ JoinOn $ Iden [Name "true"])) +> ,("select * from a full join b on true" +> ,sel $ TRJoin a False JFull b +> (Just $ JoinOn $ Iden [Name "true"])) +> ,("select * from a natural join b" +> ,sel $ TRJoin a True JInner b Nothing) +> ,("select * from a natural inner join b" +> ,sel $ TRJoin a True JInner b Nothing) +> ,("select * from a natural left join b" +> ,sel $ TRJoin a True JLeft b Nothing) +> ,("select * from a natural left outer join b" +> ,sel $ TRJoin a True JLeft b Nothing) +> ,("select * from a natural right join b" +> ,sel $ TRJoin a True JRight b Nothing) +> ,("select * from a natural full join b" +> ,sel $ TRJoin a True JFull b Nothing) > ] +> where +> sel t = makeSelect +> {qeSelectList = [(Star, Nothing)] +> ,qeFrom = [t]} +> a = TRSimple [Name "a"] +> b = TRSimple [Name "b"] + +TODO: partitioned joins == 7.8 @@ -2842,6 +2949,46 @@ clause> to the result of the previously specified clause. ::= + +> groupByClause :: TestItem +> groupByClause = Group "group by clause" +> $ map (uncurry TestQueryExpr) +> [("select a,sum(x) from t group by a" +> ,qe [SimpleGroup $ Iden [Name "a"]]) +> ,("select a,sum(x) from t group by a collate c" +> ,qe [SimpleGroup $ Collate (Iden [Name "a"]) [Name "c"]]) +> ,("select a,b,sum(x) from t group by a,b" +> ,qex [SimpleGroup $ Iden [Name "a"] +> ,SimpleGroup $ Iden [Name "b"]]) +> -- todo: group by set quantifier +> --,("select a,sum(x) from t group by distinct a" +> --,undefined) +> --,("select a,sum(x) from t group by all a" +> -- ,undefined) +> ,("select a,b,sum(x) from t group by rollup(a,b)" +> ,qex [Rollup [SimpleGroup $ Iden [Name "a"] +> ,SimpleGroup $ Iden [Name "b"]]]) +> ,("select a,b,sum(x) from t group by cube(a,b)" +> ,qex [Cube [SimpleGroup $ Iden [Name "a"] +> ,SimpleGroup $ Iden [Name "b"]]]) +> ,("select a,b,sum(x) from t group by grouping sets((),(a,b))" +> ,qex [GroupingSets [GroupingParens [] +> ,GroupingParens [SimpleGroup $ Iden [Name "a"] +> ,SimpleGroup $ Iden [Name "b"]]]]) +> ,("select sum(x) from t group by ()" +> ,let x = qe [GroupingParens []] +> in x {qeSelectList = tail $ qeSelectList x}) +> ] +> where +> qe g = makeSelect +> {qeSelectList = [(Iden [Name "a"], Nothing) +> ,(App [Name "sum"] [Iden [Name "x"]], Nothing)] +> ,qeFrom = [TRSimple [Name "t"]] +> ,qeGroupBy = g} +> qex g = let x = qe g +> in x {qeSelectList = let [a,b] = qeSelectList x +> in [a,(Iden [Name "b"],Nothing),b]} + == 7.10 Function @@ -2851,9 +2998,18 @@ not satisfy a . ::= HAVING -> groupByClause :: TestItem -> groupByClause = Group "group by clause" -> [-- todo: group by clause +> havingClause :: TestItem +> havingClause = Group "having clause" +> $ map (uncurry TestQueryExpr) +> [("select a,sum(x) from t group by a having sum(x) > 1000" +> ,makeSelect +> {qeSelectList = [(Iden [Name "a"], Nothing) +> ,(App [Name "sum"] [Iden [Name "x"]], Nothing)] +> ,qeFrom = [TRSimple [Name "t"]] +> ,qeGroupBy = [SimpleGroup $ Iden [Name "a"]] +> ,qeHaving = Just $ BinOp (App [Name "sum"] [Iden [Name "x"]]) +> [Name ">"] +> (NumLit "1000")}) > ] == 7.11