import Test.QuickCheck.Simple (Test, defaultMain) import qualified Test.QuickCheck.Simple as QSimple import Control.Applicative ((<$>), (<*>)) import Lex (eqProp, eqProp') import Model import Data.Int (Int32, Int64) import Database.Relational.Query tables :: [Test] tables = [ eqProp "setA" setA "SELECT int_a0, str_a1, str_a2 FROM TEST.set_a" , eqProp "setB" setB "SELECT int_b0, may_str_b1, str_b2 FROM TEST.set_b" , eqProp "setC" setC "SELECT int_c0, str_c1, int_c2, may_str_c3 FROM TEST.set_c" ] _p_tables :: IO () _p_tables = mapM_ print [show setA, show setB, show setC] -- Monadic Operators tests queryX :: Relation () SetA queryX = relation $ do a <- query setA return a queryMaybeX :: Relation () (Maybe SetA) queryMaybeX = relation $ do a <- queryMaybe setA return a onX :: Relation () (Maybe SetA, SetB) onX = relation $ do a <- queryMaybe setA b <- query setB on $ a ?! intA0' .=. just (b ! intB0') return $ (,) |$| a |*| b wheresX :: Relation () (SetA, SetB) wheresX = relation $ do a <- query setA b <- query setB wheres $ b ! intB0' .>=. value 3 return $ (,) |$| a |*| b groupByX :: Relation () (Int32, Integer) groupByX = aggregateRelation $ do a <- query setA ga0 <- groupBy $ a ! intA0' return $ (,) |$| ga0 |*| count (a ! intA0') havingX :: Relation () Int havingX = aggregateRelation $ do a <- query setA let c = count (a ! intA0') having $ c .>. value 1 return c distinctX :: Relation () Int32 distinctX = relation $ do distinct a <- query setA return $ a ! intA0' all'X :: Relation () Int32 all'X = relation $ do all' a <- query setA return $ a ! intA0' assignX :: Update () assignX = derivedUpdate $ \_proj -> do intA0' <-# value (0 :: Int32) return unitPlaceHolder registerX :: Insert (String, Maybe String) registerX = derivedInsertValue $ do intC0' <-# value 1 (ph1, ()) <- placeholder (\ph' -> strC1' <-# ph') intC2' <-# value 2 (ph2, ()) <- placeholder (\ph' -> mayStrC3' <-# ph') return $ ph1 >< ph2 eqChunkedInsert :: String -> Insert a -> String -> String -> Test eqChunkedInsert name ins prefix row = maybe (name, success) (\(sql, n) -> let estimate = unwords $ prefix : replicate (n - 1) (row ++ ",") ++ [row] in eqProp' name id sql estimate) $ chunkedInsert ins where success = QSimple.Bool Nothing True monadic :: [Test] monadic = [ eqProp "query" queryX "SELECT ALL T0.int_a0 AS f0, T0.str_a1 AS f1, T0.str_a2 AS f2 FROM TEST.set_a T0" , eqProp "queryMaybe" queryMaybeX "SELECT ALL T0.int_a0 AS f0, T0.str_a1 AS f1, T0.str_a2 AS f2 FROM TEST.set_a T0" , eqProp "on" onX "SELECT ALL T0.int_a0 AS f0, T0.str_a1 AS f1, T0.str_a2 AS f2, \ \ T1.int_b0 AS f3, T1.may_str_b1 AS f4, T1.str_b2 AS f5 \ \ FROM TEST.set_a T0 RIGHT JOIN TEST.set_b T1 ON (T0.int_a0 = T1.int_b0)" , eqProp "wheres" wheresX "SELECT ALL T0.int_a0 AS f0, T0.str_a1 AS f1, T0.str_a2 AS f2, \ \ T1.int_b0 AS f3, T1.may_str_b1 AS f4, T1.str_b2 AS f5 \ \ FROM TEST.set_a T0 INNER JOIN TEST.set_b T1 ON (0=0) \ \ WHERE (T1.int_b0 >= 3)" , eqProp "groupBy" groupByX "SELECT ALL T0.int_a0 AS f0, COUNT(T0.int_a0) AS f1 \ \ FROM TEST.set_a T0 GROUP BY T0.int_a0" , eqProp "having" havingX "SELECT ALL COUNT(T0.int_a0) AS f0 FROM TEST.set_a T0 HAVING (COUNT(T0.int_a0) > 1)" , eqProp "distinct" distinctX "SELECT DISTINCT T0.int_a0 AS f0 FROM TEST.set_a T0" , eqProp "all'" all'X "SELECT ALL T0.int_a0 AS f0 FROM TEST.set_a T0" , eqProp "update" assignX "UPDATE TEST.set_a SET int_a0 = 0" , eqProp "insert" registerX "INSERT INTO TEST.set_c (int_c0, str_c1, int_c2, may_str_c3) VALUES (1, ?, 2, ?)" , eqChunkedInsert "insert chunked" registerX "INSERT INTO TEST.set_c (int_c0, str_c1, int_c2, may_str_c3) VALUES" "(1, ?, 2, ?)" ] _p_monadic :: IO () _p_monadic = mapM_ putStrLn [ show queryX, show queryMaybeX, show onX, show wheresX , show groupByX, show havingX, show distinctX, show all'X , show assignX ] -- Direct Join Operators cross :: Relation () (SetA, SetB) cross = setA `inner` setB `on'` [] innerX :: Relation () (SetA, SetB) innerX = setA `inner` setB `on'` [ \a b -> a ! intA0' .=. b ! intB0' ] leftX :: Relation () (SetA, Maybe SetB) leftX = setA `left` setB `on'` [ \a b -> just (a ! strA1') .=. b ?!? mayStrB1' ] rightX :: Relation () (Maybe SetA, SetB) rightX = setA `right` setB `on'` [ \a b -> a ?! intA0' .=. just (b ! intB0') ] fullX :: Relation () (Maybe SetA, Maybe SetB) fullX = setA `full` setB `on'` [ \a b -> a ?! intA0' .=. b ?! intB0' ] directJoins :: [Test] directJoins = [ eqProp "cross" cross "SELECT ALL T0.int_a0 AS f0, T0.str_a1 AS f1, T0.str_a2 AS f2, \ \ T1.int_b0 AS f3, T1.may_str_b1 AS f4, T1.str_b2 AS f5 \ \ FROM TEST.set_a T0 INNER JOIN TEST.set_b T1 ON (0=0)" , eqProp "inner" innerX "SELECT ALL T0.int_a0 AS f0, T0.str_a1 AS f1, T0.str_a2 AS f2, \ \ T1.int_b0 AS f3, T1.may_str_b1 AS f4, T1.str_b2 AS f5 \ \ FROM TEST.set_a T0 INNER JOIN TEST.set_b T1 ON (T0.int_a0 = T1.int_b0)" , eqProp "left" leftX "SELECT ALL T0.int_a0 AS f0, T0.str_a1 AS f1, T0.str_a2 AS f2, \ \ T1.int_b0 AS f3, T1.may_str_b1 AS f4, T1.str_b2 AS f5 \ \ FROM TEST.set_a T0 LEFT JOIN TEST.set_b T1 ON (T0.str_a1 = T1.may_str_b1)" , eqProp "right" rightX "SELECT ALL T0.int_a0 AS f0, T0.str_a1 AS f1, T0.str_a2 AS f2, \ \ T1.int_b0 AS f3, T1.may_str_b1 AS f4, T1.str_b2 AS f5 \ \ FROM TEST.set_a T0 RIGHT JOIN TEST.set_b T1 ON (T0.int_a0 = T1.int_b0)" , eqProp "full" fullX "SELECT ALL T0.int_a0 AS f0, T0.str_a1 AS f1, T0.str_a2 AS f2, \ \ T1.int_b0 AS f3, T1.may_str_b1 AS f4, T1.str_b2 AS f5 \ \ FROM TEST.set_a T0 FULL JOIN TEST.set_b T1 ON (T0.int_a0 = T1.int_b0)" ] _p_directJoins :: IO () _p_directJoins = mapM_ print [show cross, show innerX, show leftX, show rightX, show fullX] j3left :: Relation () Abc j3left = relation $ do a <- query setA b <- queryMaybe setB on $ just (a ! strA2') .=. b ?! strB2' c <- queryMaybe setC on $ b ?! intB0' .=. c ?! intC0' return $ Abc |$| a |*| b |*| c j3right :: Relation () Abc j3right = relation $ do a <- query setA bc <- query $ setB `full` setC `on'` [ \b c -> b ?! intB0' .=. c ?! intC0' ] let b = bc ! fst' c = bc ! snd' on $ just (a ! strA2') .=. b ?! strB2' return $ Abc |$| a |*| b |*| c join3s :: [Test] join3s = [ eqProp "join-3 left" j3left "SELECT ALL T0.int_a0 AS f0, T0.str_a1 AS f1, T0.str_a2 AS f2, \ \ T1.int_b0 AS f3, T1.may_str_b1 AS f4, T1.str_b2 AS f5, \ \ T2.int_c0 AS f6, T2.str_c1 AS f7, T2.int_c2 AS f8, T2.may_str_c3 AS f9 \ \ FROM (TEST.set_a T0 LEFT JOIN TEST.set_b T1 ON (T0.str_a2 = T1.str_b2)) \ \ LEFT JOIN TEST.set_c T2 ON (T1.int_b0 = T2.int_c0)" , eqProp "join-3 right" j3right "SELECT ALL T0.int_a0 AS f0, T0.str_a1 AS f1, T0.str_a2 AS f2, \ \ T3.f0 AS f3, T3.f1 AS f4, T3.f2 AS f5, T3.f3 AS f6, T3.f4 AS f7, T3.f5 AS f8, T3.f6 AS f9 \ \ FROM TEST.set_a T0 \ \ INNER JOIN (SELECT ALL T1.int_b0 AS f0, T1.may_str_b1 AS f1, T1.str_b2 AS f2, \ \ T2.int_c0 AS f3, T2.str_c1 AS f4, T2.int_c2 AS f5, T2.may_str_c3 AS f6 \ \ FROM TEST.set_b T1 FULL JOIN TEST.set_c T2 ON (T1.int_b0 = T2.int_c0)) T3 \ \ ON (T0.str_a2 = T3.f2)" ] _p_j3s :: IO () _p_j3s = mapM_ print [show j3left, show j3right] -- Index of Nested Projections nestedPiRec :: Relation () SetA nestedPiRec = relation $ do ar <- query . relation $ do a <- query setA return $ value "Hello" >< a return $ ar ! snd' nestedPiCol :: Relation () String nestedPiCol = relation $ do ar <- query . relation $ do a <- query setA return $ a >< value "Hello" return $ ar ! snd' nestedPi :: Relation () String nestedPi = relation $ do ar <- query . relation $ do a <- query setA return $ (value "Hello" >< a) >< value "World" return $ ar ! snd' nested :: [Test] nested = [ eqProp "nested pi record" nestedPiRec "SELECT ALL T1.f1 AS f0, T1.f2 AS f1, T1.f3 AS f2 \ \ FROM (SELECT ALL 'Hello' AS f0, \ \ T0.int_a0 AS f1, T0.str_a1 AS f2, T0.str_a2 AS f3 \ \ FROM TEST.set_a T0) T1" , eqProp "nested pi column" nestedPiCol "SELECT ALL T1.f3 AS f0 \ \ FROM (SELECT ALL T0.int_a0 AS f0, T0.str_a1 AS f1, T0.str_a2 AS f2, \ \ 'Hello' AS f3 \ \ FROM TEST.set_a T0) T1" , eqProp "nested pi both" nestedPi "SELECT ALL T1.f4 AS f0 \ \ FROM (SELECT ALL 'Hello' AS f0, \ \ T0.int_a0 AS f1, T0.str_a1 AS f2, T0.str_a2 AS f3, \ \ 'World' AS f4 \ \ FROM TEST.set_a T0) T1" ] _p_nested :: IO () _p_nested = mapM_ print [show nestedPiRec, show nestedPiCol, show nestedPi] -- Projection Operators bin53 :: (Projection Flat Int32 -> Projection Flat Int32 -> Projection Flat r) -> Relation () r bin53 op = relation $ do return $ value 5 `op` value 3 strIn :: Relation () (Maybe Bool) strIn = relation $ return $ value "foo" `in'` values ["foo", "bar"] boolTF :: (Projection Flat (Maybe Bool) -> Projection Flat (Maybe Bool) -> Projection Flat r) -> Relation () r boolTF op = relation $ do return $ valueTrue `op` valueFalse strConcat :: Relation () String strConcat = relation $ do return $ value "Hello, " .||. value "World!" strLike :: Relation () (Maybe Bool) strLike = relation $ do return $ value "Hoge" `like` "H%" _p_bin53 :: (Projection Flat Int32 -> Projection Flat Int32 -> Projection Flat r) -> IO () _p_bin53 = print . bin53 bin :: [Test] bin = [ eqProp "equal" (bin53 (.=.)) "SELECT ALL (5 = 3) AS f0" , eqProp "lt" (bin53 (.<.)) "SELECT ALL (5 < 3) AS f0" , eqProp "le" (bin53 (.<=.)) "SELECT ALL (5 <= 3) AS f0" , eqProp "gt" (bin53 (.>.)) "SELECT ALL (5 > 3) AS f0" , eqProp "ge" (bin53 (.>=.)) "SELECT ALL (5 >= 3) AS f0" , eqProp "ne" (bin53 (.<>.)) "SELECT ALL (5 <> 3) AS f0" , eqProp "and" (boolTF and') "SELECT ALL ((0=0) AND (0=1)) AS f0" , eqProp "or" (boolTF or') "SELECT ALL ((0=0) OR (0=1)) AS f0" , eqProp "in" strIn "SELECT ALL ('foo' IN ('foo', 'bar')) AS f0" , eqProp "string concat" strConcat "SELECT ALL ('Hello, ' || 'World!') AS f0" , eqProp "like" strLike "SELECT ALL ('Hoge' LIKE 'H%') AS f0" , eqProp "plus" (bin53 (.+.)) "SELECT ALL (5 + 3) AS f0" , eqProp "minus" (bin53 (.-.)) "SELECT ALL (5 - 3) AS f0" , eqProp "mult" (bin53 (.*.)) "SELECT ALL (5 * 3) AS f0" , eqProp "div" (bin53 (./.)) "SELECT ALL (5 / 3) AS f0" ] caseSearchX :: Relation () String caseSearchX = relation $ do return $ caseSearch [ (value 2 .=. value (1 :: Int32) , value "foo") , (value 5 .=. value 3 .+. value (2 :: Int32) , value "bar") , (value "a" .=. value "b" , value "baz") ] (value "other") caseX :: Relation () String caseX = relation $ do return $ case' (value (5 :: Int32)) [ (value 1 , value "foo") , (value 3 .+. value 2 , value "bar") , (value 10 , value "baz") ] (value "other") caseRecordX :: Relation () Int32 caseRecordX = relation $ do return $ case' (value (5 :: Int32)) [ (value 1 , (,) |$| value 1 |*| value "foo") , (value 3 .+. value 2 , (,) |$| value 2 |*| value "bar") , (value 10 , (,) |$| value 3 |*| value "baz") ] ((,) |$| value (0 :: Int32) |*| value "other") ! fst' .*. value 10 caseRecordMaybeX :: Relation () (Maybe (Int32, String)) caseRecordMaybeX = relation $ do return $ caseMaybe (value (5 :: Int32)) [ (value (1 :: Int32) , just $ (,) |$| value (1 :: Int32) |*| value "foo") , (value 3 .+. value 2 , just $ (,) |$| value 2 |*| value "bar") ] cases :: [Test] cases = [ eqProp "caseSearch" caseSearchX "SELECT ALL CASE WHEN (2 = 1) THEN 'foo' WHEN (5 = (3 + 2)) THEN 'bar' WHEN ('a' = 'b') THEN 'baz' ELSE 'other' END AS f0" , eqProp "case" caseX "SELECT ALL CASE 5 WHEN 1 THEN 'foo' WHEN (3 + 2) THEN 'bar' WHEN 10 THEN 'baz' ELSE 'other' END AS f0" , eqProp "caseRecord" caseRecordX "SELECT ALL (CASE 5 WHEN 1 THEN 1 WHEN (3 + 2) THEN 2 WHEN 10 THEN 3 ELSE 0 END * 10) AS f0" , eqProp "caseRecordMaybe" caseRecordMaybeX "SELECT ALL CASE 5 WHEN 1 THEN 1 WHEN (3 + 2) THEN 2 ELSE NULL END AS f0, \ \ CASE 5 WHEN 1 THEN 'foo' WHEN (3 + 2) THEN 'bar' ELSE NULL END AS f1" ] _p_cases :: IO () _p_cases = mapM_ print [show caseSearchX, show caseX] nothingX :: Relation () (SetA, Maybe SetB) nothingX = relation $ do a <- query setA b <- queryMaybe setB wheres $ isNothing b `or'` a ! intA0' .=. value 1 return $ a >< b justX :: Relation () (SetA, Maybe SetB) justX = relation $ do a <- query setA b <- queryMaybe setB wheres $ isJust b `or'` a ! intA0' .=. value 1 return $ a >< b maybeX :: Relation () (Int32, SetB) maybeX = relation $ do a <- queryMaybe setA b <- query setB wheres $ a ?! strA2' .=. b ! mayStrB1' return $ fromMaybe (value 1) (a ?! intA0') >< b notX :: Relation () (Maybe Bool) notX = relation $ return $ not' valueFalse existsX :: Relation () (Maybe Bool) existsX = relation $ return . exists =<< queryList setA uni :: [Test] uni = [ eqProp "isNothing" nothingX "SELECT ALL T0.int_a0 AS f0, T0.str_a1 AS f1, T0.str_a2 AS f2, \ \ T1.int_b0 AS f3, T1.may_str_b1 AS f4, T1.str_b2 AS f5 \ \ FROM TEST.set_a T0 LEFT JOIN TEST.set_b T1 ON (0=0) \ \ WHERE ((T1.int_b0 IS NULL) OR (T0.int_a0 = 1))" , eqProp "isJust" justX "SELECT ALL T0.int_a0 AS f0, T0.str_a1 AS f1, T0.str_a2 AS f2, \ \ T1.int_b0 AS f3, T1.may_str_b1 AS f4, T1.str_b2 AS f5 \ \ FROM TEST.set_a T0 LEFT JOIN TEST.set_b T1 ON (0=0) \ \ WHERE ((NOT (T1.int_b0 IS NULL)) OR (T0.int_a0 = 1))" , eqProp "fromMaybe" maybeX "SELECT ALL CASE WHEN (T0.int_a0 IS NULL) THEN 1 ELSE T0.int_a0 END AS f0, \ \ T1.int_b0 AS f1, T1.may_str_b1 AS f2, T1.str_b2 AS f3 \ \ FROM TEST.set_a T0 RIGHT JOIN TEST.set_b T1 ON (0=0) WHERE (T0.str_a2 = T1.may_str_b1)" , eqProp "not" notX "SELECT ALL (NOT (0=1)) AS f0" , eqProp "exists" existsX "SELECT ALL (EXISTS (SELECT int_a0, str_a1, str_a2 FROM TEST.set_a)) AS f0" ] _p_uni :: IO () _p_uni = mapM_ print [show nothingX, show justX, show maybeX, show notX, show existsX] groupX :: Relation () (String, Int64) groupX = aggregateRelation $ do c <- query setC gc1 <- groupBy $ c ! strC1' return $ gc1 >< count (c ! intC0') cubeX :: Relation () ((Maybe String, Maybe (Int64, Maybe String)), Maybe Int32) cubeX = aggregateRelation $ do c <- query setC gCube <- groupBy' . cube $ do (><) <$> bkey (c ! strC1') <*> bkey (c ! intC2' >< c ! mayStrC3') return $ gCube >< sum' (c ! intC0') groupingSetsX :: Relation () (((Maybe String, Maybe (Maybe String)), Maybe Int64), Maybe Int64) groupingSetsX = aggregateRelation $ do c <- query setC gs <- groupBy' . groupingSets $ do s1 <- set $ do gRollup <- key' . rollup $ do (><) <$> bkey (c ! strC1') <*> bkey (c ! mayStrC3') gc2 <- key $ c ! intC2' return $ gRollup >< gc2 s2 <- set . key $ c ! intC2' return $ s1 >< s2 return gs groups :: [Test] groups = [ eqProp "group" groupX "SELECT ALL T0.str_c1 AS f0, COUNT(T0.int_c0) AS f1 \ \ FROM TEST.set_c T0 GROUP BY T0.str_c1" , eqProp "cube" cubeX "SELECT ALL T0.str_c1 AS f0, T0.int_c2 AS f1, T0.may_str_c3 AS f2, SUM(T0.int_c0) AS f3 \ \ FROM TEST.set_c T0 GROUP BY CUBE ((T0.str_c1), (T0.int_c2, T0.may_str_c3))" , eqProp "groupingSets" groupingSetsX "SELECT ALL T0.str_c1 AS f0, T0.may_str_c3 AS f1, T0.int_c2 AS f2, T0.int_c2 AS f3 \ \ FROM TEST.set_c T0 GROUP BY \ \ GROUPING SETS ((ROLLUP ((T0.str_c1), (T0.may_str_c3)), T0.int_c2), (T0.int_c2))" ] _p_groups :: IO () _p_groups = mapM_ print [show groupX, show cubeX, show groupingSetsX] ordFlatX :: Relation () (SetA, Maybe SetB) ordFlatX = relation $ do a <- query setA b <- queryMaybe setB on $ just (a ! strA2') .=. b ?! strB2' orderBy (a ! strA1') Asc orderBy' (b ?! mayStrB1') Desc NullsLast return $ (,) |$| a |*| b ordFlatY :: Relation () (SetA, Maybe SetB) ordFlatY = relation $ do a <- query setA b <- queryMaybe setB on $ just (a ! strA2') .=. b ?! strB2' orderBy (a ! strA1') Asc orderBy' b Desc NullsLast return $ (,) |$| a |*| b ordAggX :: Relation () (String, Int64) ordAggX = aggregateRelation $ do c <- query setC gc1 <- groupBy $ c ! strC1' orderBy' (sum' $ c ! intC0') Asc NullsFirst return $ gc1 >< count (c ! intC0') _p_orders :: IO () _p_orders = mapM_ print [show ordFlatX, show ordAggX] orders :: [Test] orders = [ eqProp "order-by - flat" ordFlatX "SELECT ALL T0.int_a0 AS f0, T0.str_a1 AS f1, T0.str_a2 AS f2, \ \ T1.int_b0 AS f3, T1.may_str_b1 AS f4, T1.str_b2 AS f5 \ \ FROM TEST.set_a T0 LEFT JOIN TEST.set_b T1 ON (T0.str_a2 = T1.str_b2) \ \ ORDER BY T0.str_a1 ASC, T1.may_str_b1 DESC NULLS LAST" , eqProp "order-by - flag 2" ordFlatY "SELECT ALL T0.int_a0 AS f0, T0.str_a1 AS f1, T0.str_a2 AS f2, \ \ T1.int_b0 AS f3, T1.may_str_b1 AS f4, T1.str_b2 AS f5 \ \ FROM TEST.set_a T0 LEFT JOIN TEST.set_b T1 ON (T0.str_a2 = T1.str_b2) \ \ ORDER BY T0.str_a1 ASC, T1.int_b0 DESC NULLS LAST, \ \ T1.may_str_b1 DESC NULLS LAST, T1.str_b2 DESC NULLS LAST" , eqProp "order-by - aggregated" ordAggX "SELECT ALL T0.str_c1 AS f0, COUNT(T0.int_c0) AS f1 \ \ FROM TEST.set_c T0 GROUP BY T0.str_c1 ORDER BY SUM(T0.int_c0) ASC NULLS FIRST" ] partitionX :: Relation () (String, Int64) partitionX = relation $ do c <- query setC return $ (c ! strC1') >< rank `over` do partitionBy $ c ! strC1' orderBy (c ! intC2') Asc partitionY :: Relation () (String, (Int64, Maybe Int32)) partitionY = relation $ do c <- query setC return $ (c ! strC1') >< (rank >< sum' (c ! intC0'))`over` do partitionBy $ c ! strC1' orderBy (c ! intC2') Asc partitions :: [Test] partitions = [ eqProp "partition 0" partitionX "SELECT ALL T0.str_c1 AS f0, \ \ RANK() OVER (PARTITION BY T0.str_c1 ORDER BY T0.int_c2 ASC) AS f1 \ \ FROM TEST.set_c T0" , eqProp "partition 1" partitionY "SELECT ALL T0.str_c1 AS f0, \ \ RANK() OVER (PARTITION BY T0.str_c1 ORDER BY T0.int_c2 ASC) AS f1, \ \ SUM(T0.int_c0) OVER (PARTITION BY T0.str_c1 ORDER BY T0.int_c2 ASC) AS f2 \ \ FROM TEST.set_c T0" ] _p_partitions :: IO () _p_partitions = mapM_ print [show partitionX, show partitionY] setAFromB :: Pi SetB SetA setAFromB = SetA |$| intB0' |*| strB2' |*| strB2' aFromB :: Relation () SetA aFromB = relation $ do x <- query setB return $ x ! setAFromB unionX :: Relation () SetA unionX = setA `union` aFromB unionAllX :: Relation () SetA unionAllX = setA `unionAll` aFromB exceptX :: Relation () SetA exceptX = setA `except` aFromB intersectX :: Relation () SetA intersectX = setA `intersect` aFromB exps :: [Test] exps = [ eqProp "union" unionX "SELECT int_a0 AS f0, str_a1 AS f1, str_a2 AS f2 FROM TEST.set_a UNION \ \SELECT ALL T0.int_b0 AS f0, T0.str_b2 AS f1, T0.str_b2 AS f2 FROM TEST.set_b T0" , eqProp "unionAll" unionAllX "SELECT int_a0 AS f0, str_a1 AS f1, str_a2 AS f2 FROM TEST.set_a UNION ALL \ \SELECT ALL T0.int_b0 AS f0, T0.str_b2 AS f1, T0.str_b2 AS f2 FROM TEST.set_b T0" , eqProp "except" exceptX "SELECT int_a0 AS f0, str_a1 AS f1, str_a2 AS f2 FROM TEST.set_a EXCEPT \ \SELECT ALL T0.int_b0 AS f0, T0.str_b2 AS f1, T0.str_b2 AS f2 FROM TEST.set_b T0" , eqProp "intersect" intersectX "SELECT int_a0 AS f0, str_a1 AS f1, str_a2 AS f2 FROM TEST.set_a INTERSECT \ \SELECT ALL T0.int_b0 AS f0, T0.str_b2 AS f1, T0.str_b2 AS f2 FROM TEST.set_b T0" ] insertX :: Insert SetA insertX = derivedInsert id' insertI :: Insert SetI insertI = derivedInsert id' insertQueryX :: InsertQuery () insertQueryX = derivedInsertQuery setAFromB setA updateKeyX :: KeyUpdate Int32 SetA updateKeyX = primaryUpdate tableOfSetA updateX :: Update () updateX = derivedUpdate $ \proj -> do strA2' <-# value "X" wheres $ proj ! strA1' .=. value "A" return unitPlaceHolder deleteX :: Delete () deleteX = derivedDelete $ \proj -> do wheres $ proj ! strA1' .=. value "A" return unitPlaceHolder effs :: [Test] effs = [ eqProp "insert" insertX "INSERT INTO TEST.set_a (int_a0, str_a1, str_a2) VALUES (?, ?, ?)" , eqChunkedInsert "insert chunked" insertX "INSERT INTO TEST.set_a (int_a0, str_a1, str_a2) VALUES" "(?, ?, ?)" , eqProp "insert1" insertI "INSERT INTO TEST.set_i (int_i0) VALUES (?)" , eqChunkedInsert "insert1 chunked" insertI "INSERT INTO TEST.set_i (int_i0) VALUES" "(?)" , eqProp "insertQuery" insertQueryX "INSERT INTO TEST.set_b (int_b0, str_b2, str_b2) SELECT int_a0, str_a1, str_a2 FROM TEST.set_a" , eqProp "updateKey" updateKeyX "UPDATE TEST.set_a SET str_a1 = ?, str_a2 = ? WHERE int_a0 = ?" , eqProp "update" updateX "UPDATE TEST.set_a SET str_a2 = 'X' WHERE (str_a1 = 'A')" , eqProp "delete" deleteX "DELETE FROM TEST.set_a WHERE (str_a1 = 'A')" ] updateExistsX :: Update () updateExistsX = derivedUpdate $ \proj -> do strA2' <-# value "X" wheres . exists =<< (queryList . relation $ do b <- query setB wheres $ b ! intB0' .=. proj ! intA0' return b) return unitPlaceHolder updateScalarX :: Update () updateScalarX = derivedUpdate $ \proj -> do strA2' <-# value "X" sb <- queryScalar . unsafeUnique . relation $ do b <- query setB wheres $ b ! intB0' .=. value 0 return $ b ! intB0' wheres $ just (proj ! intA0') .=. sb return unitPlaceHolder deleteExistsX :: Delete () deleteExistsX = derivedDelete $ \proj -> do wheres . exists =<< (queryList . relation $ do b <- query setB wheres $ b ! intB0' .=. proj ! intA0' return b) return unitPlaceHolder deleteScalarX :: Delete () deleteScalarX = derivedDelete $ \proj -> do sb <- queryScalar . unsafeUnique . relation $ do b <- query setB wheres $ b ! intB0' .=. value 0 return $ b ! intB0' wheres $ just (proj ! intA0') .=. sb return unitPlaceHolder correlated :: [Test] correlated = [ eqProp "update-exists" updateExistsX "UPDATE TEST.set_a SET str_a2 = 'X' \ \ WHERE (EXISTS (SELECT ALL T0.int_b0 AS f0, T0.may_str_b1 AS f1, T0.str_b2 AS f2 \ \ FROM TEST.set_b T0 \ \ WHERE (T0.int_b0 = int_a0)))" , eqProp "update-scalar" updateScalarX "UPDATE TEST.set_a SET str_a2 = 'X' \ \ WHERE (int_a0 = (SELECT ALL T0.int_b0 AS f0 \ \ FROM TEST.set_b T0 \ \ WHERE (T0.int_b0 = 0)))" , eqProp "delete-exists" deleteExistsX "DELETE FROM TEST.set_a \ \ WHERE (EXISTS (SELECT ALL T0.int_b0 AS f0, T0.may_str_b1 AS f1, T0.str_b2 AS f2 \ \ FROM TEST.set_b T0 \ \ WHERE (T0.int_b0 = int_a0)))" , eqProp "delete-scalar" deleteScalarX "DELETE FROM TEST.set_a \ \ WHERE (int_a0 = (SELECT ALL T0.int_b0 AS f0 \ \ FROM TEST.set_b T0 \ \ WHERE (T0.int_b0 = 0)))" ] tests :: [Test] tests = concat [ tables, monadic, directJoins, join3s, nested, bin, cases, uni , groups, orders, partitions, exps, effs, correlated] main :: IO () main = defaultMain tests