2013-12-13 11:39:26 +01:00
|
|
|
|
2013-12-16 12:33:05 +01:00
|
|
|
TODO:
|
|
|
|
|
|
|
|
split into multiple files:
|
|
|
|
scalar expressions
|
|
|
|
tablerefs
|
|
|
|
other queryexpr parts: not enough to split into multiple files
|
|
|
|
full queries
|
|
|
|
tpch tests
|
|
|
|
|
|
|
|
postgres queries - take all the examples from the postgres docs which
|
|
|
|
aren't too postgres specific and create tests from them
|
|
|
|
|
|
|
|
postgres queries:
|
|
|
|
SELECT 'foo'
|
|
|
|
'bar'; -> if there is a newline, this parses to select 'foobar'
|
|
|
|
|
|
|
|
SELECT name, (SELECT max(pop) FROM cities WHERE cities.state = states.name)
|
|
|
|
FROM states;
|
|
|
|
|
|
|
|
SELECT ROW(1,2.5,'this is a test');
|
|
|
|
|
|
|
|
SELECT ROW(t.*, 42) FROM t;
|
|
|
|
SELECT ROW(t.f1, t.f2, 42) FROM t;
|
|
|
|
Note: Before PostgreSQL 8.2, the .* syntax was not expanded
|
|
|
|
SELECT getf1(CAST(ROW(11,'this is a test',2.5) AS myrowtype));
|
|
|
|
|
|
|
|
SELECT ROW(1,2.5,'this is a test') = ROW(1, 3, 'not the same');
|
|
|
|
|
|
|
|
SELECT ROW(table.*) IS NULL FROM table;
|
|
|
|
|
|
|
|
SELECT true OR somefunc();
|
|
|
|
|
|
|
|
SELECT somefunc() OR true;
|
|
|
|
|
|
|
|
|
2013-12-14 19:42:01 +01:00
|
|
|
> module Language.SQL.SimpleSQL.Tests
|
|
|
|
> (testData
|
|
|
|
> ,tests
|
|
|
|
> ,TestItem(..)
|
|
|
|
> ) where
|
2013-12-13 11:39:26 +01:00
|
|
|
|
2013-12-13 15:04:48 +01:00
|
|
|
> import Language.SQL.SimpleSQL.Syntax
|
|
|
|
> import Language.SQL.SimpleSQL.Pretty
|
|
|
|
> import Language.SQL.SimpleSQL.Parser
|
2013-12-13 13:08:33 +01:00
|
|
|
> import qualified Test.HUnit as H
|
2013-12-13 17:50:41 +01:00
|
|
|
> import Tpch
|
2013-12-14 19:42:01 +01:00
|
|
|
> import Test.Framework
|
|
|
|
> import Test.Framework.Providers.HUnit
|
2013-12-13 11:39:26 +01:00
|
|
|
|
|
|
|
> data TestItem = Group String [TestItem]
|
|
|
|
> | TestScalarExpr String ScalarExpr
|
|
|
|
> | TestQueryExpr String QueryExpr
|
2013-12-14 10:59:29 +01:00
|
|
|
> | TestQueryExprs String [QueryExpr]
|
2013-12-13 17:50:41 +01:00
|
|
|
> | ParseQueryExpr String
|
2013-12-13 11:39:26 +01:00
|
|
|
> deriving (Eq,Show)
|
|
|
|
|
|
|
|
> scalarExprParserTests :: TestItem
|
2013-12-13 13:08:33 +01:00
|
|
|
> scalarExprParserTests = Group "scalarExprParserTests"
|
|
|
|
> [literals
|
|
|
|
> ,identifiers
|
|
|
|
> ,star
|
|
|
|
> ,app
|
|
|
|
> ,caseexp
|
|
|
|
> ,operators
|
|
|
|
> ,parens
|
2013-12-13 17:50:41 +01:00
|
|
|
> ,subqueries
|
|
|
|
> ,aggregates
|
|
|
|
> ,windowFunctions
|
2013-12-13 13:08:33 +01:00
|
|
|
> ]
|
|
|
|
|
|
|
|
> literals :: TestItem
|
|
|
|
> literals = Group "literals" $ map (uncurry TestScalarExpr)
|
2013-12-13 16:00:22 +01:00
|
|
|
> [("3", NumLit "3")
|
|
|
|
> ,("3.", NumLit "3.")
|
|
|
|
> ,("3.3", NumLit "3.3")
|
|
|
|
> ,(".3", NumLit ".3")
|
|
|
|
> ,("3.e3", NumLit "3.e3")
|
|
|
|
> ,("3.3e3", NumLit "3.3e3")
|
|
|
|
> ,(".3e3", NumLit ".3e3")
|
|
|
|
> ,("3e3", NumLit "3e3")
|
|
|
|
> ,("3e+3", NumLit "3e+3")
|
|
|
|
> ,("3e-3", NumLit "3e-3")
|
2013-12-13 23:07:45 +01:00
|
|
|
> ,("'string'", StringLit "string")
|
|
|
|
> ,("'1'", StringLit "1")
|
|
|
|
> ,("interval '3' day", IntervalLit "3" "day" Nothing)
|
|
|
|
> ,("interval '3' day (3)", IntervalLit "3" "day" $ Just 3)
|
2013-12-13 13:08:33 +01:00
|
|
|
> ]
|
|
|
|
|
|
|
|
> identifiers :: TestItem
|
|
|
|
> identifiers = Group "identifiers" $ map (uncurry TestScalarExpr)
|
2013-12-13 16:00:22 +01:00
|
|
|
> [("iden1", Iden "iden1")
|
|
|
|
> ,("t.a", Iden2 "t" "a")
|
2013-12-13 13:08:33 +01:00
|
|
|
> ]
|
|
|
|
|
|
|
|
> star :: TestItem
|
|
|
|
> star = Group "star" $ map (uncurry TestScalarExpr)
|
|
|
|
> [("*", Star)
|
|
|
|
> ,("t.*", Star2 "t")
|
|
|
|
> ]
|
|
|
|
|
|
|
|
> app :: TestItem
|
|
|
|
> app = Group "app" $ map (uncurry TestScalarExpr)
|
|
|
|
> [("f()", App "f" [])
|
2013-12-13 16:00:22 +01:00
|
|
|
> ,("f(a)", App "f" [Iden "a"])
|
|
|
|
> ,("f(a,b)", App "f" [Iden "a", Iden "b"])
|
2013-12-13 13:08:33 +01:00
|
|
|
> ]
|
|
|
|
|
|
|
|
> caseexp :: TestItem
|
|
|
|
> caseexp = Group "caseexp" $ map (uncurry TestScalarExpr)
|
|
|
|
> [("case a when 1 then 2 end"
|
2013-12-13 16:00:22 +01:00
|
|
|
> ,Case (Just $ Iden "a") [(NumLit "1"
|
2013-12-16 09:03:46 +01:00
|
|
|
> ,NumLit "2")] Nothing)
|
|
|
|
|
2013-12-13 13:08:33 +01:00
|
|
|
> ,("case a when 1 then 2 when 3 then 4 end"
|
2013-12-13 16:00:22 +01:00
|
|
|
> ,Case (Just $ Iden "a") [(NumLit "1", NumLit "2")
|
2013-12-16 09:03:46 +01:00
|
|
|
> ,(NumLit "3", NumLit "4")] Nothing)
|
|
|
|
|
2013-12-13 13:08:33 +01:00
|
|
|
> ,("case a when 1 then 2 when 3 then 4 else 5 end"
|
2013-12-13 16:00:22 +01:00
|
|
|
> ,Case (Just $ Iden "a") [(NumLit "1", NumLit "2")
|
2013-12-16 09:03:46 +01:00
|
|
|
> ,(NumLit "3", NumLit "4")] (Just $ NumLit "5"))
|
|
|
|
|
2013-12-13 13:08:33 +01:00
|
|
|
> ,("case when a=1 then 2 when a=3 then 4 else 5 end"
|
2013-12-14 12:33:15 +01:00
|
|
|
> ,Case Nothing [(BinOp (Iden "a") "=" (NumLit "1"), NumLit "2")
|
|
|
|
> ,(BinOp (Iden "a") "=" (NumLit "3"), NumLit "4")]
|
2013-12-13 16:00:22 +01:00
|
|
|
> (Just $ NumLit "5"))
|
2013-12-16 09:03:46 +01:00
|
|
|
|
2013-12-13 13:08:33 +01:00
|
|
|
> ]
|
|
|
|
|
|
|
|
> operators :: TestItem
|
2013-12-13 17:50:41 +01:00
|
|
|
> operators = Group "operators"
|
|
|
|
> [binaryOperators
|
|
|
|
> ,unaryOperators
|
|
|
|
> ,casts
|
|
|
|
> ,miscOps]
|
|
|
|
|
|
|
|
> binaryOperators :: TestItem
|
|
|
|
> binaryOperators = Group "binaryOperators" $ map (uncurry TestScalarExpr)
|
2013-12-14 12:33:15 +01:00
|
|
|
> [("a + b", BinOp (Iden "a") "+" (Iden "b"))
|
2013-12-13 17:50:41 +01:00
|
|
|
> -- sanity check fixities
|
|
|
|
> -- todo: add more fixity checking
|
2013-12-16 09:03:46 +01:00
|
|
|
|
2013-12-14 15:34:57 +01:00
|
|
|
> ,("a + b * c"
|
|
|
|
> ,BinOp (Iden "a") "+"
|
|
|
|
> (BinOp (Iden "b") "*" (Iden "c")))
|
2013-12-16 09:03:46 +01:00
|
|
|
|
2013-12-13 17:50:41 +01:00
|
|
|
> ,("a * b + c"
|
2013-12-14 15:34:57 +01:00
|
|
|
> ,BinOp (BinOp (Iden "a") "*" (Iden "b"))
|
|
|
|
> "+" (Iden "c"))
|
2013-12-13 17:50:41 +01:00
|
|
|
> ]
|
|
|
|
|
|
|
|
> unaryOperators :: TestItem
|
|
|
|
> unaryOperators = Group "unaryOperators" $ map (uncurry TestScalarExpr)
|
2013-12-13 20:26:14 +01:00
|
|
|
> [("not a", PrefixOp "not" $ Iden "a")
|
|
|
|
> ,("not not a", PrefixOp "not" $ PrefixOp "not" $ Iden "a")
|
|
|
|
> ,("+a", PrefixOp "+" $ Iden "a")
|
|
|
|
> ,("-a", PrefixOp "-" $ Iden "a")
|
2013-12-13 17:50:41 +01:00
|
|
|
> ]
|
|
|
|
|
|
|
|
|
|
|
|
> casts :: TestItem
|
|
|
|
> casts = Group "operators" $ map (uncurry TestScalarExpr)
|
|
|
|
> [("cast('1' as int)"
|
|
|
|
> ,Cast (StringLit "1") $ TypeName "int")
|
2013-12-16 09:03:46 +01:00
|
|
|
|
2013-12-13 17:50:41 +01:00
|
|
|
> ,("int '3'"
|
2013-12-13 19:24:20 +01:00
|
|
|
> ,CastOp (TypeName "int") "3")
|
2013-12-16 09:03:46 +01:00
|
|
|
|
2013-12-13 17:50:41 +01:00
|
|
|
> ,("cast('1' as double precision)"
|
|
|
|
> ,Cast (StringLit "1") $ TypeName "double precision")
|
2013-12-16 09:03:46 +01:00
|
|
|
|
2013-12-13 17:50:41 +01:00
|
|
|
> ,("double precision '3'"
|
2013-12-13 19:24:20 +01:00
|
|
|
> ,CastOp (TypeName "double precision") "3")
|
2013-12-13 17:50:41 +01:00
|
|
|
> ]
|
|
|
|
|
|
|
|
> subqueries :: TestItem
|
|
|
|
> subqueries = Group "unaryOperators" $ map (uncurry TestScalarExpr)
|
2013-12-13 19:43:28 +01:00
|
|
|
> [("exists (select a from t)", SubQueryExpr SqExists ms)
|
|
|
|
> ,("(select a from t)", SubQueryExpr SqSq ms)
|
2013-12-16 09:03:46 +01:00
|
|
|
|
2013-12-13 20:00:06 +01:00
|
|
|
> ,("a in (select a from t)"
|
|
|
|
> ,In True (Iden "a") (InQueryExpr ms))
|
2013-12-16 09:03:46 +01:00
|
|
|
|
2013-12-13 20:00:06 +01:00
|
|
|
> ,("a not in (select a from t)"
|
|
|
|
> ,In False (Iden "a") (InQueryExpr ms))
|
2013-12-16 09:03:46 +01:00
|
|
|
|
2013-12-13 19:43:28 +01:00
|
|
|
> ,("a > all (select a from t)"
|
2013-12-14 12:33:15 +01:00
|
|
|
> ,BinOp (Iden "a") ">" (SubQueryExpr SqAll ms))
|
2013-12-16 09:03:46 +01:00
|
|
|
|
2013-12-13 19:43:28 +01:00
|
|
|
> ,("a = some (select a from t)"
|
2013-12-14 12:33:15 +01:00
|
|
|
> ,BinOp (Iden "a") "=" (SubQueryExpr SqSome ms))
|
2013-12-16 09:03:46 +01:00
|
|
|
|
2013-12-13 19:43:28 +01:00
|
|
|
> ,("a <= any (select a from t)"
|
2013-12-14 12:33:15 +01:00
|
|
|
> ,BinOp (Iden "a") "<=" (SubQueryExpr SqAny ms))
|
2013-12-13 17:50:41 +01:00
|
|
|
> ]
|
2013-12-13 19:43:28 +01:00
|
|
|
> where
|
|
|
|
> ms = makeSelect
|
|
|
|
> {qeSelectList = [(Nothing,Iden "a")]
|
2013-12-14 13:10:46 +01:00
|
|
|
> ,qeFrom = [TRSimple "t"]
|
2013-12-13 19:43:28 +01:00
|
|
|
> }
|
2013-12-13 17:50:41 +01:00
|
|
|
|
|
|
|
> miscOps :: TestItem
|
|
|
|
> miscOps = Group "unaryOperators" $ map (uncurry TestScalarExpr)
|
2013-12-13 20:00:06 +01:00
|
|
|
> [("a in (1,2,3)"
|
|
|
|
> ,In True (Iden "a") $ InList $ map NumLit ["1","2","3"])
|
2013-12-16 09:03:46 +01:00
|
|
|
|
2013-12-13 20:26:14 +01:00
|
|
|
> ,("a between b and c", SpecialOp "between" [Iden "a"
|
|
|
|
> ,Iden "b"
|
|
|
|
> ,Iden "c"])
|
2013-12-16 09:03:46 +01:00
|
|
|
|
2013-12-13 20:26:14 +01:00
|
|
|
> ,("a not between b and c", SpecialOp "not between" [Iden "a"
|
|
|
|
> ,Iden "b"
|
|
|
|
> ,Iden "c"])
|
2013-12-16 09:03:46 +01:00
|
|
|
|
2013-12-13 20:26:14 +01:00
|
|
|
> ,("a is null", PostfixOp "is null" (Iden "a"))
|
2013-12-13 20:34:59 +01:00
|
|
|
> ,("a is not null", PostfixOp "is not null" (Iden "a"))
|
|
|
|
> ,("a is true", PostfixOp "is true" (Iden "a"))
|
|
|
|
> ,("a is not true", PostfixOp "is not true" (Iden "a"))
|
|
|
|
> ,("a is false", PostfixOp "is false" (Iden "a"))
|
|
|
|
> ,("a is not false", PostfixOp "is not false" (Iden "a"))
|
|
|
|
> ,("a is unknown", PostfixOp "is unknown" (Iden "a"))
|
|
|
|
> ,("a is not unknown", PostfixOp "is not unknown" (Iden "a"))
|
2013-12-14 12:33:15 +01:00
|
|
|
> ,("a is distinct from b", BinOp (Iden "a") "is distinct from"(Iden "b"))
|
2013-12-16 09:03:46 +01:00
|
|
|
|
2013-12-14 12:33:15 +01:00
|
|
|
> ,("a is not distinct from b"
|
|
|
|
> ,BinOp (Iden "a") "is not distinct from" (Iden "b"))
|
2013-12-16 09:03:46 +01:00
|
|
|
|
2013-12-14 12:33:15 +01:00
|
|
|
> ,("a like b", BinOp (Iden "a") "like" (Iden "b"))
|
|
|
|
> ,("a not like b", BinOp (Iden "a") "not like" (Iden "b"))
|
|
|
|
> ,("a is similar to b", BinOp (Iden "a") "is similar to" (Iden "b"))
|
2013-12-16 09:03:46 +01:00
|
|
|
|
2013-12-14 12:33:15 +01:00
|
|
|
> ,("a is not similar to b"
|
|
|
|
> ,BinOp (Iden "a") "is not similar to" (Iden "b"))
|
2013-12-16 09:03:46 +01:00
|
|
|
|
2013-12-14 12:33:15 +01:00
|
|
|
> ,("a overlaps b", BinOp (Iden "a") "overlaps" (Iden "b"))
|
2013-12-13 21:38:43 +01:00
|
|
|
> ,("extract(day from t)", SpecialOp "extract" [Iden "day", Iden "t"])
|
2013-12-16 09:03:46 +01:00
|
|
|
|
2013-12-13 23:34:05 +01:00
|
|
|
> ,("substring(x from 1 for 2)"
|
|
|
|
> ,SpecialOp "substring" [Iden "x", NumLit "1", NumLit "2"])
|
2013-12-16 09:03:46 +01:00
|
|
|
|
2013-12-13 17:50:41 +01:00
|
|
|
> ]
|
|
|
|
|
|
|
|
> aggregates :: TestItem
|
|
|
|
> aggregates = Group "aggregates" $ map (uncurry TestScalarExpr)
|
2013-12-13 22:18:30 +01:00
|
|
|
> [("count(*)",App "count" [Star])
|
2013-12-16 09:03:46 +01:00
|
|
|
|
2013-12-13 22:18:30 +01:00
|
|
|
> ,("sum(a order by a)"
|
|
|
|
> ,AggregateApp "sum" Nothing [Iden "a"] [(Iden "a", Asc)])
|
2013-12-16 09:03:46 +01:00
|
|
|
|
2013-12-13 22:18:30 +01:00
|
|
|
> ,("sum(all a)"
|
|
|
|
> ,AggregateApp "sum" (Just All) [Iden "a"] [])
|
2013-12-16 09:03:46 +01:00
|
|
|
|
2013-12-13 22:18:30 +01:00
|
|
|
> ,("count(distinct a)"
|
|
|
|
> ,AggregateApp "count" (Just Distinct) [Iden "a"] [])
|
2013-12-13 17:50:41 +01:00
|
|
|
> ]
|
|
|
|
|
|
|
|
> windowFunctions :: TestItem
|
|
|
|
> windowFunctions = Group "windowFunctions" $ map (uncurry TestScalarExpr)
|
2013-12-13 22:31:36 +01:00
|
|
|
> [("max(a) over ()", WindowApp "max" [Iden "a"] [] [])
|
|
|
|
> ,("count(*) over ()", WindowApp "count" [Star] [] [])
|
2013-12-16 09:03:46 +01:00
|
|
|
|
2013-12-13 22:31:36 +01:00
|
|
|
> ,("max(a) over (partition by b)"
|
|
|
|
> ,WindowApp "max" [Iden "a"] [Iden "b"] [])
|
2013-12-16 09:03:46 +01:00
|
|
|
|
2013-12-13 22:31:36 +01:00
|
|
|
> ,("max(a) over (partition by b,c)"
|
|
|
|
> ,WindowApp "max" [Iden "a"] [Iden "b",Iden "c"] [])
|
2013-12-16 09:03:46 +01:00
|
|
|
|
2013-12-13 22:31:36 +01:00
|
|
|
> ,("sum(a) over (order by b)"
|
|
|
|
> ,WindowApp "sum" [Iden "a"] [] [(Iden "b", Asc)])
|
2013-12-16 09:03:46 +01:00
|
|
|
|
2013-12-13 22:31:36 +01:00
|
|
|
> ,("sum(a) over (order by b desc,c)"
|
|
|
|
> ,WindowApp "sum" [Iden "a"] [] [(Iden "b", Desc)
|
|
|
|
> ,(Iden "c", Asc)])
|
2013-12-16 09:03:46 +01:00
|
|
|
|
2013-12-13 22:31:36 +01:00
|
|
|
> ,("sum(a) over (partition by b order by c)"
|
|
|
|
> ,WindowApp "sum" [Iden "a"] [Iden "b"] [(Iden "c", Asc)])
|
2013-12-13 17:50:41 +01:00
|
|
|
> -- todo: check order by options, add frames
|
2013-12-13 13:08:33 +01:00
|
|
|
> ]
|
|
|
|
|
|
|
|
> parens :: TestItem
|
|
|
|
> parens = Group "parens" $ map (uncurry TestScalarExpr)
|
2013-12-13 16:00:22 +01:00
|
|
|
> [("(a)", Parens (Iden "a"))
|
2013-12-14 12:33:15 +01:00
|
|
|
> ,("(a + b)", Parens (BinOp (Iden "a") "+" (Iden "b")))
|
2013-12-13 13:08:33 +01:00
|
|
|
> ]
|
2013-12-13 11:39:26 +01:00
|
|
|
|
|
|
|
> queryExprParserTests :: TestItem
|
2013-12-13 13:08:33 +01:00
|
|
|
> queryExprParserTests = Group "queryExprParserTests"
|
2013-12-13 16:27:02 +01:00
|
|
|
> [duplicates
|
|
|
|
> ,selectLists
|
2013-12-13 13:08:33 +01:00
|
|
|
> ,from
|
|
|
|
> ,whereClause
|
|
|
|
> ,groupByClause
|
|
|
|
> ,having
|
|
|
|
> ,orderBy
|
2013-12-13 16:27:02 +01:00
|
|
|
> ,limit
|
2013-12-13 17:50:41 +01:00
|
|
|
> ,combos
|
2013-12-13 23:58:12 +01:00
|
|
|
> ,withQueries
|
2013-12-13 13:08:33 +01:00
|
|
|
> ,fullQueries
|
|
|
|
> ]
|
|
|
|
|
2013-12-13 16:27:02 +01:00
|
|
|
|
|
|
|
|
|
|
|
> 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")]
|
2013-12-14 13:10:46 +01:00
|
|
|
> ,qeFrom = [TRSimple "t"]}
|
2013-12-13 16:27:02 +01:00
|
|
|
|
2013-12-13 13:08:33 +01:00
|
|
|
> selectLists :: TestItem
|
|
|
|
> selectLists = Group "selectLists" $ map (uncurry TestQueryExpr)
|
|
|
|
> [("select 1",
|
2013-12-13 16:00:22 +01:00
|
|
|
> makeSelect {qeSelectList = [(Nothing,NumLit "1")]})
|
2013-12-16 09:03:46 +01:00
|
|
|
|
2013-12-13 13:08:33 +01:00
|
|
|
> ,("select a"
|
2013-12-13 16:00:22 +01:00
|
|
|
> ,makeSelect {qeSelectList = [(Nothing,Iden "a")]})
|
2013-12-16 09:03:46 +01:00
|
|
|
|
2013-12-13 13:08:33 +01:00
|
|
|
> ,("select a,b"
|
2013-12-13 16:00:22 +01:00
|
|
|
> ,makeSelect {qeSelectList = [(Nothing,Iden "a")
|
|
|
|
> ,(Nothing,Iden "b")]})
|
2013-12-16 09:03:46 +01:00
|
|
|
|
2013-12-13 13:08:33 +01:00
|
|
|
> ,("select 1+2,3+4"
|
|
|
|
> ,makeSelect {qeSelectList =
|
2013-12-14 12:33:15 +01:00
|
|
|
> [(Nothing,BinOp (NumLit "1") "+" (NumLit "2"))
|
|
|
|
> ,(Nothing,BinOp (NumLit "3") "+" (NumLit "4"))]})
|
2013-12-16 09:03:46 +01:00
|
|
|
|
2013-12-13 13:08:33 +01:00
|
|
|
> ,("select a as a, /*comment*/ b as b"
|
2013-12-13 16:00:22 +01:00
|
|
|
> ,makeSelect {qeSelectList = [(Just "a", Iden "a")
|
|
|
|
> ,(Just "b", Iden "b")]})
|
2013-12-16 09:03:46 +01:00
|
|
|
|
2013-12-13 13:08:33 +01:00
|
|
|
> ,("select a a, b b"
|
2013-12-13 16:00:22 +01:00
|
|
|
> ,makeSelect {qeSelectList = [(Just "a", Iden "a")
|
|
|
|
> ,(Just "b", Iden "b")]})
|
2013-12-13 13:08:33 +01:00
|
|
|
> ]
|
|
|
|
|
|
|
|
> from :: TestItem
|
|
|
|
> from = Group "from" $ map (uncurry TestQueryExpr)
|
|
|
|
> [("select a from t"
|
2013-12-14 13:10:46 +01:00
|
|
|
> ,ms [TRSimple "t"])
|
2013-12-16 09:03:46 +01:00
|
|
|
|
2013-12-13 13:08:33 +01:00
|
|
|
> ,("select a from t,u"
|
2013-12-14 13:10:46 +01:00
|
|
|
> ,ms [TRSimple "t", TRSimple "u"])
|
2013-12-16 09:03:46 +01:00
|
|
|
|
2013-12-13 13:08:33 +01:00
|
|
|
> ,("select a from t inner join u on expr"
|
2013-12-14 13:10:46 +01:00
|
|
|
> ,ms [TRJoin (TRSimple "t") JInner (TRSimple "u")
|
2013-12-13 16:00:22 +01:00
|
|
|
> (Just $ JoinOn $ Iden "expr")])
|
2013-12-16 09:03:46 +01:00
|
|
|
|
2013-12-13 13:08:33 +01:00
|
|
|
> ,("select a from t left join u on expr"
|
2013-12-14 13:10:46 +01:00
|
|
|
> ,ms [TRJoin (TRSimple "t") JLeft (TRSimple "u")
|
2013-12-13 16:00:22 +01:00
|
|
|
> (Just $ JoinOn $ Iden "expr")])
|
2013-12-16 09:03:46 +01:00
|
|
|
|
2013-12-13 13:08:33 +01:00
|
|
|
> ,("select a from t right join u on expr"
|
2013-12-14 13:10:46 +01:00
|
|
|
> ,ms [TRJoin (TRSimple "t") JRight (TRSimple "u")
|
2013-12-13 16:00:22 +01:00
|
|
|
> (Just $ JoinOn $ Iden "expr")])
|
2013-12-16 09:03:46 +01:00
|
|
|
|
2013-12-13 13:08:33 +01:00
|
|
|
> ,("select a from t full join u on expr"
|
2013-12-14 13:10:46 +01:00
|
|
|
> ,ms [TRJoin (TRSimple "t") JFull (TRSimple "u")
|
2013-12-13 16:00:22 +01:00
|
|
|
> (Just $ JoinOn $ Iden "expr")])
|
2013-12-16 09:03:46 +01:00
|
|
|
|
2013-12-13 13:08:33 +01:00
|
|
|
> ,("select a from t cross join u"
|
2013-12-14 13:10:46 +01:00
|
|
|
> ,ms [TRJoin (TRSimple "t")
|
|
|
|
> JCross (TRSimple "u") Nothing])
|
2013-12-16 09:03:46 +01:00
|
|
|
|
2013-12-13 13:08:33 +01:00
|
|
|
> ,("select a from t natural inner join u"
|
2013-12-14 13:10:46 +01:00
|
|
|
> ,ms [TRJoin (TRSimple "t") JInner (TRSimple "u")
|
2013-12-13 13:08:33 +01:00
|
|
|
> (Just JoinNatural)])
|
2013-12-16 09:03:46 +01:00
|
|
|
|
2013-12-13 13:08:33 +01:00
|
|
|
> ,("select a from t inner join u using(a,b)"
|
2013-12-14 13:10:46 +01:00
|
|
|
> ,ms [TRJoin (TRSimple "t") JInner (TRSimple "u")
|
2013-12-13 13:08:33 +01:00
|
|
|
> (Just $ JoinUsing ["a", "b"])])
|
2013-12-16 09:03:46 +01:00
|
|
|
|
2013-12-13 13:08:33 +01:00
|
|
|
> ,("select a from (select a from t)"
|
2013-12-14 13:10:46 +01:00
|
|
|
> ,ms [TRQueryExpr $ ms [TRSimple "t"]])
|
2013-12-16 09:03:46 +01:00
|
|
|
|
2013-12-13 13:08:33 +01:00
|
|
|
> ,("select a from t as u"
|
2013-12-14 13:10:46 +01:00
|
|
|
> ,ms [TRAlias (TRSimple "t") "u" Nothing])
|
2013-12-16 09:03:46 +01:00
|
|
|
|
2013-12-13 13:08:33 +01:00
|
|
|
> ,("select a from t u"
|
2013-12-14 13:10:46 +01:00
|
|
|
> ,ms [TRAlias (TRSimple "t") "u" Nothing])
|
2013-12-16 09:03:46 +01:00
|
|
|
|
2013-12-13 23:37:34 +01:00
|
|
|
> ,("select a from t u(b)"
|
2013-12-14 13:10:46 +01:00
|
|
|
> ,ms [TRAlias (TRSimple "t") "u" $ Just ["b"]])
|
2013-12-16 09:03:46 +01:00
|
|
|
|
2013-12-13 13:08:33 +01:00
|
|
|
> ,("select a from (t cross join u) as u"
|
2013-12-14 13:10:46 +01:00
|
|
|
> ,ms [TRAlias (TRParens $
|
|
|
|
> TRJoin (TRSimple "t") JCross (TRSimple "u") Nothing)
|
|
|
|
> "u" Nothing])
|
2013-12-14 12:05:02 +01:00
|
|
|
> -- todo: not sure if the associativity is correct
|
2013-12-16 09:03:46 +01:00
|
|
|
|
2013-12-14 12:05:02 +01:00
|
|
|
> ,("select a from t cross join u cross join v",
|
2013-12-14 13:10:46 +01:00
|
|
|
> ms [TRJoin
|
|
|
|
> (TRJoin (TRSimple "t")
|
|
|
|
> JCross (TRSimple "u") Nothing)
|
|
|
|
> JCross (TRSimple "v") Nothing])
|
2013-12-13 13:08:33 +01:00
|
|
|
> ]
|
|
|
|
> where
|
2013-12-13 16:00:22 +01:00
|
|
|
> ms f = makeSelect {qeSelectList = [(Nothing,Iden "a")]
|
2013-12-13 13:08:33 +01:00
|
|
|
> ,qeFrom = f}
|
|
|
|
|
|
|
|
> whereClause :: TestItem
|
|
|
|
> whereClause = Group "whereClause" $ map (uncurry TestQueryExpr)
|
|
|
|
> [("select a from t where a = 5"
|
2013-12-13 16:00:22 +01:00
|
|
|
> ,makeSelect {qeSelectList = [(Nothing,Iden "a")]
|
2013-12-14 13:10:46 +01:00
|
|
|
> ,qeFrom = [TRSimple "t"]
|
2013-12-14 12:33:15 +01:00
|
|
|
> ,qeWhere = Just $ BinOp (Iden "a") "=" (NumLit "5")})
|
2013-12-13 13:08:33 +01:00
|
|
|
> ]
|
|
|
|
|
|
|
|
> groupByClause :: TestItem
|
|
|
|
> groupByClause = Group "groupByClause" $ map (uncurry TestQueryExpr)
|
|
|
|
> [("select a,sum(b) from t group by a"
|
2013-12-13 16:00:22 +01:00
|
|
|
> ,makeSelect {qeSelectList = [(Nothing, Iden "a")
|
|
|
|
> ,(Nothing, App "sum" [Iden "b"])]
|
2013-12-14 13:10:46 +01:00
|
|
|
> ,qeFrom = [TRSimple "t"]
|
2013-12-13 16:00:22 +01:00
|
|
|
> ,qeGroupBy = [Iden "a"]
|
2013-12-13 13:08:33 +01:00
|
|
|
> })
|
2013-12-16 09:03:46 +01:00
|
|
|
|
2013-12-13 13:08:33 +01:00
|
|
|
> ,("select a,b,sum(c) from t group by a,b"
|
2013-12-13 16:00:22 +01:00
|
|
|
> ,makeSelect {qeSelectList = [(Nothing, Iden "a")
|
|
|
|
> ,(Nothing, Iden "b")
|
|
|
|
> ,(Nothing, App "sum" [Iden "c"])]
|
2013-12-14 13:10:46 +01:00
|
|
|
> ,qeFrom = [TRSimple "t"]
|
2013-12-13 16:00:22 +01:00
|
|
|
> ,qeGroupBy = [Iden "a",Iden "b"]
|
2013-12-13 13:08:33 +01:00
|
|
|
> })
|
|
|
|
> ]
|
|
|
|
|
|
|
|
> having :: TestItem
|
|
|
|
> having = Group "having" $ map (uncurry TestQueryExpr)
|
|
|
|
> [("select a,sum(b) from t group by a having sum(b) > 5"
|
2013-12-13 16:00:22 +01:00
|
|
|
> ,makeSelect {qeSelectList = [(Nothing, Iden "a")
|
|
|
|
> ,(Nothing, App "sum" [Iden "b"])]
|
2013-12-14 13:10:46 +01:00
|
|
|
> ,qeFrom = [TRSimple "t"]
|
2013-12-13 16:00:22 +01:00
|
|
|
> ,qeGroupBy = [Iden "a"]
|
2013-12-14 12:33:15 +01:00
|
|
|
> ,qeHaving = Just $ BinOp (App "sum" [Iden "b"])
|
|
|
|
> ">" (NumLit "5")
|
2013-12-13 13:08:33 +01:00
|
|
|
> })
|
|
|
|
> ]
|
|
|
|
|
|
|
|
> orderBy :: TestItem
|
|
|
|
> orderBy = Group "orderBy" $ map (uncurry TestQueryExpr)
|
|
|
|
> [("select a from t order by a"
|
2013-12-13 16:08:10 +01:00
|
|
|
> ,ms [(Iden "a", Asc)])
|
2013-12-16 09:03:46 +01:00
|
|
|
|
2013-12-13 13:08:33 +01:00
|
|
|
> ,("select a from t order by a, b"
|
2013-12-13 16:08:10 +01:00
|
|
|
> ,ms [(Iden "a", Asc), (Iden "b", Asc)])
|
2013-12-16 09:03:46 +01:00
|
|
|
|
2013-12-13 16:08:10 +01:00
|
|
|
> ,("select a from t order by a asc"
|
|
|
|
> ,ms [(Iden "a", Asc)])
|
2013-12-16 09:03:46 +01:00
|
|
|
|
2013-12-13 16:08:10 +01:00
|
|
|
> ,("select a from t order by a desc, b desc"
|
|
|
|
> ,ms [(Iden "a", Desc), (Iden "b", Desc)])
|
2013-12-13 13:08:33 +01:00
|
|
|
> ]
|
|
|
|
> where
|
2013-12-13 16:00:22 +01:00
|
|
|
> ms o = makeSelect {qeSelectList = [(Nothing,Iden "a")]
|
2013-12-14 13:10:46 +01:00
|
|
|
> ,qeFrom = [TRSimple "t"]
|
2013-12-13 13:08:33 +01:00
|
|
|
> ,qeOrderBy = o}
|
|
|
|
|
2013-12-13 16:27:02 +01:00
|
|
|
> limit :: TestItem
|
|
|
|
> limit = Group "limit" $ map (uncurry TestQueryExpr)
|
|
|
|
> [("select a from t limit 10"
|
|
|
|
> ,ms (Just $ NumLit "10") Nothing)
|
2013-12-16 09:03:46 +01:00
|
|
|
|
2013-12-13 16:27:02 +01:00
|
|
|
> ,("select a from t limit 10 offset 10"
|
|
|
|
> ,ms (Just $ NumLit "10") (Just $ NumLit "10"))
|
|
|
|
> ]
|
|
|
|
> where
|
|
|
|
> ms l o = makeSelect
|
|
|
|
> {qeSelectList = [(Nothing,Iden "a")]
|
2013-12-14 13:10:46 +01:00
|
|
|
> ,qeFrom = [TRSimple "t"]
|
2013-12-13 16:27:02 +01:00
|
|
|
> ,qeLimit = l
|
|
|
|
> ,qeOffset = o}
|
|
|
|
|
2013-12-13 17:50:41 +01:00
|
|
|
> combos :: TestItem
|
|
|
|
> combos = Group "combos" $ map (uncurry TestQueryExpr)
|
2013-12-13 22:41:12 +01:00
|
|
|
> [("select a from t union select b from u"
|
2013-12-13 22:49:22 +01:00
|
|
|
> ,CombineQueryExpr ms1 Union All Respectively ms2)
|
2013-12-16 09:03:46 +01:00
|
|
|
|
2013-12-13 17:50:41 +01:00
|
|
|
> ,("select a from t intersect select b from u"
|
2013-12-13 22:49:22 +01:00
|
|
|
> ,CombineQueryExpr ms1 Intersect All Respectively ms2)
|
2013-12-16 09:03:46 +01:00
|
|
|
|
2013-12-13 22:49:22 +01:00
|
|
|
> ,("select a from t except all select b from u"
|
|
|
|
> ,CombineQueryExpr ms1 Except All Respectively ms2)
|
2013-12-16 09:03:46 +01:00
|
|
|
|
2013-12-13 22:49:22 +01:00
|
|
|
> ,("select a from t union distinct corresponding \
|
|
|
|
> \select b from u"
|
|
|
|
> ,CombineQueryExpr ms1 Union Distinct Corresponding ms2)
|
2013-12-16 09:03:46 +01:00
|
|
|
|
2013-12-14 10:41:58 +01:00
|
|
|
> ,("select a from t union select a from t union select a from t"
|
2013-12-16 09:03:46 +01:00
|
|
|
> -- is this the correct associativity?
|
2013-12-14 10:41:58 +01:00
|
|
|
> ,CombineQueryExpr ms1 Union All Respectively
|
|
|
|
> (CombineQueryExpr ms1 Union All Respectively ms1))
|
2013-12-13 17:50:41 +01:00
|
|
|
> ]
|
2013-12-13 22:41:12 +01:00
|
|
|
> where
|
|
|
|
> ms1 = makeSelect
|
|
|
|
> {qeSelectList = [(Nothing,Iden "a")]
|
2013-12-14 13:10:46 +01:00
|
|
|
> ,qeFrom = [TRSimple "t"]}
|
2013-12-13 22:41:12 +01:00
|
|
|
> ms2 = makeSelect
|
|
|
|
> {qeSelectList = [(Nothing,Iden "b")]
|
2013-12-14 13:10:46 +01:00
|
|
|
> ,qeFrom = [TRSimple "u"]}
|
2013-12-13 17:50:41 +01:00
|
|
|
|
2013-12-13 23:58:12 +01:00
|
|
|
|
|
|
|
> withQueries :: TestItem
|
|
|
|
> withQueries = Group "with queries" $ map (uncurry TestQueryExpr)
|
|
|
|
> [("with u as (select a from t) select a from u"
|
|
|
|
> ,With [("u", ms1)] ms2)
|
2013-12-16 09:03:46 +01:00
|
|
|
|
2013-12-13 23:58:12 +01:00
|
|
|
> ,("with x as (select a from t),\n\
|
|
|
|
> \ u as (select a from x)\n\
|
|
|
|
> \select a from u"
|
|
|
|
> ,With [("x", ms1), ("u",ms3)] ms2)
|
|
|
|
> ]
|
|
|
|
> where
|
|
|
|
> ms c t = makeSelect
|
|
|
|
> {qeSelectList = [(Nothing,Iden c)]
|
2013-12-14 13:10:46 +01:00
|
|
|
> ,qeFrom = [TRSimple t]}
|
2013-12-13 23:58:12 +01:00
|
|
|
> ms1 = ms "a" "t"
|
|
|
|
> ms2 = ms "a" "u"
|
|
|
|
> ms3 = ms "a" "x"
|
|
|
|
|
|
|
|
|
2013-12-13 13:08:33 +01:00
|
|
|
> fullQueries :: TestItem
|
|
|
|
> fullQueries = Group "queries" $ map (uncurry TestQueryExpr)
|
2013-12-13 13:21:25 +01:00
|
|
|
> [("select count(*) from t"
|
|
|
|
> ,makeSelect
|
|
|
|
> {qeSelectList = [(Nothing, App "count" [Star])]
|
2013-12-14 13:10:46 +01:00
|
|
|
> ,qeFrom = [TRSimple "t"]
|
2013-12-13 13:21:25 +01:00
|
|
|
> }
|
|
|
|
> )
|
2013-12-16 09:03:46 +01:00
|
|
|
|
2013-12-13 13:21:25 +01:00
|
|
|
> ,("select a, sum(c+d) as s\n\
|
2013-12-13 13:08:33 +01:00
|
|
|
> \ from t,u\n\
|
|
|
|
> \ where a > 5\n\
|
|
|
|
> \ group by a\n\
|
|
|
|
> \ having count(1) > 5\n\
|
|
|
|
> \ order by s"
|
|
|
|
> ,makeSelect
|
2013-12-13 16:00:22 +01:00
|
|
|
> {qeSelectList = [(Nothing, Iden "a")
|
2013-12-14 12:33:15 +01:00
|
|
|
> ,(Just "s"
|
|
|
|
> ,App "sum" [BinOp (Iden "c")
|
|
|
|
> "+" (Iden "d")])]
|
2013-12-14 13:10:46 +01:00
|
|
|
> ,qeFrom = [TRSimple "t", TRSimple "u"]
|
2013-12-14 12:33:15 +01:00
|
|
|
> ,qeWhere = Just $ BinOp (Iden "a") ">" (NumLit "5")
|
2013-12-13 16:00:22 +01:00
|
|
|
> ,qeGroupBy = [Iden "a"]
|
2013-12-14 12:33:15 +01:00
|
|
|
> ,qeHaving = Just $ BinOp (App "count" [NumLit "1"])
|
|
|
|
> ">" (NumLit "5")
|
2013-12-13 16:08:10 +01:00
|
|
|
> ,qeOrderBy = [(Iden "s", Asc)]
|
2013-12-13 13:08:33 +01:00
|
|
|
> }
|
|
|
|
> )
|
|
|
|
> ]
|
2013-12-13 11:39:26 +01:00
|
|
|
|
2013-12-14 10:59:29 +01:00
|
|
|
> queryExprsParserTests :: TestItem
|
|
|
|
> queryExprsParserTests = Group "query exprs" $ map (uncurry TestQueryExprs)
|
|
|
|
> [("select 1",[ms])
|
|
|
|
> ,("select 1;",[ms])
|
|
|
|
> ,("select 1;select 1",[ms,ms])
|
|
|
|
> ,(" select 1;select 1; ",[ms,ms])
|
|
|
|
> ]
|
|
|
|
> where
|
|
|
|
> ms = makeSelect {qeSelectList = [(Nothing,NumLit "1")]}
|
|
|
|
|
2013-12-13 17:50:41 +01:00
|
|
|
> tpchTests :: TestItem
|
|
|
|
> tpchTests =
|
|
|
|
> Group "parse tpch"
|
2013-12-13 23:34:05 +01:00
|
|
|
> $ map (ParseQueryExpr . snd) tpchQueries
|
2013-12-13 17:50:41 +01:00
|
|
|
|
2013-12-13 11:39:26 +01:00
|
|
|
> testData :: TestItem
|
|
|
|
> testData =
|
|
|
|
> Group "parserTest"
|
|
|
|
> [scalarExprParserTests
|
2013-12-13 17:50:41 +01:00
|
|
|
> ,queryExprParserTests
|
2013-12-14 10:59:29 +01:00
|
|
|
> ,queryExprsParserTests
|
2013-12-13 23:07:45 +01:00
|
|
|
> ,tpchTests
|
2013-12-13 19:24:20 +01:00
|
|
|
> ]
|
2013-12-13 13:08:33 +01:00
|
|
|
|
2013-12-14 19:42:01 +01:00
|
|
|
> tests :: Test.Framework.Test
|
|
|
|
> tests = itemToTest testData
|
2013-12-13 13:08:33 +01:00
|
|
|
|
2013-12-14 19:42:01 +01:00
|
|
|
> --runTests :: IO ()
|
|
|
|
> --runTests = void $ H.runTestTT $ itemToTest testData
|
2013-12-13 13:08:33 +01:00
|
|
|
|
2013-12-14 19:42:01 +01:00
|
|
|
> itemToTest :: TestItem -> Test.Framework.Test
|
2013-12-13 13:08:33 +01:00
|
|
|
> itemToTest (Group nm ts) =
|
2013-12-14 19:42:01 +01:00
|
|
|
> testGroup nm $ map itemToTest ts
|
2013-12-13 13:08:33 +01:00
|
|
|
> itemToTest (TestScalarExpr str expected) =
|
2013-12-13 14:05:32 +01:00
|
|
|
> toTest parseScalarExpr prettyScalarExpr str expected
|
2013-12-13 13:08:33 +01:00
|
|
|
> itemToTest (TestQueryExpr str expected) =
|
2013-12-13 14:05:32 +01:00
|
|
|
> toTest parseQueryExpr prettyQueryExpr str expected
|
2013-12-14 10:59:29 +01:00
|
|
|
> itemToTest (TestQueryExprs str expected) =
|
|
|
|
> toTest parseQueryExprs prettyQueryExprs str expected
|
2013-12-13 17:50:41 +01:00
|
|
|
> itemToTest (ParseQueryExpr str) =
|
|
|
|
> toPTest parseQueryExpr prettyQueryExpr str
|
2013-12-13 13:08:33 +01:00
|
|
|
|
2013-12-13 18:21:44 +01:00
|
|
|
> toTest :: (Eq a, Show a) =>
|
|
|
|
> (String -> Maybe (Int,Int) -> String -> Either ParseError a)
|
2013-12-13 14:05:32 +01:00
|
|
|
> -> (a -> String)
|
|
|
|
> -> String
|
|
|
|
> -> a
|
2013-12-14 19:42:01 +01:00
|
|
|
> -> Test.Framework.Test
|
|
|
|
> toTest parser pp str expected = testCase str $ do
|
2013-12-13 13:08:33 +01:00
|
|
|
> let egot = parser "" Nothing str
|
|
|
|
> case egot of
|
2013-12-13 18:21:44 +01:00
|
|
|
> Left e -> H.assertFailure $ peFormattedError e
|
2013-12-13 14:05:32 +01:00
|
|
|
> Right got -> do
|
|
|
|
> H.assertEqual "" expected got
|
|
|
|
> let str' = pp got
|
|
|
|
> let egot' = parser "" Nothing str'
|
|
|
|
> case egot' of
|
2013-12-16 09:03:46 +01:00
|
|
|
> Left e' -> H.assertFailure $ "pp roundtrip "
|
|
|
|
> ++ peFormattedError e'
|
2013-12-13 14:05:32 +01:00
|
|
|
> Right got' -> H.assertEqual "pp roundtrip" expected got'
|
2013-12-13 17:50:41 +01:00
|
|
|
|
2013-12-13 18:21:44 +01:00
|
|
|
> toPTest :: (Eq a, Show a) =>
|
|
|
|
> (String -> Maybe (Int,Int) -> String -> Either ParseError a)
|
2013-12-13 17:50:41 +01:00
|
|
|
> -> (a -> String)
|
|
|
|
> -> String
|
2013-12-14 19:42:01 +01:00
|
|
|
> -> Test.Framework.Test
|
|
|
|
> toPTest parser pp str = testCase str $ do
|
2013-12-13 17:50:41 +01:00
|
|
|
> let egot = parser "" Nothing str
|
|
|
|
> case egot of
|
2013-12-13 18:21:44 +01:00
|
|
|
> Left e -> H.assertFailure $ peFormattedError e
|
2013-12-13 17:50:41 +01:00
|
|
|
> Right got -> do
|
|
|
|
> let str' = pp got
|
|
|
|
> let egot' = parser "" Nothing str'
|
|
|
|
> case egot' of
|
2013-12-16 09:03:46 +01:00
|
|
|
> Left e' -> H.assertFailure $ "pp roundtrip "
|
|
|
|
> ++ peFormattedError e'
|
2013-12-13 18:21:44 +01:00
|
|
|
> Right _got' -> return ()
|