diff --git a/relational-query.cabal b/relational-query.cabal
--- a/relational-query.cabal
+++ b/relational-query.cabal
@@ -1,5 +1,5 @@
 name:                relational-query
-version:             0.4.0.0
+version:             0.4.0.1
 synopsis:            Typeful, Modular, Relational, algebraic query engine
 description:         This package contiains typeful relation structure and
                      relational-algebraic query building DSL which can
diff --git a/src/Database/Relational/Query/Monad/Aggregate.hs b/src/Database/Relational/Query/Monad/Aggregate.hs
--- a/src/Database/Relational/Query/Monad/Aggregate.hs
+++ b/src/Database/Relational/Query/Monad/Aggregate.hs
@@ -27,16 +27,16 @@
   ) where
 
 import Data.Functor.Identity (Identity (runIdentity))
+import Data.Monoid ((<>))
 
-import Database.Relational.Query.Internal.SQL (showStringSQL)
 import Database.Relational.Query.Context (Flat, Aggregated, OverWindow)
 import Database.Relational.Query.Projection (Projection)
 import qualified Database.Relational.Query.Projection as Projection
 import Database.Relational.Query.Component
-  (AggregateColumnRef, Duplication, QueryRestriction, OrderingTerms, AggregateElem, composeOver)
+  (AggregateColumnRef, Duplication, QueryRestriction, OrderingTerms, AggregateElem, composeOver, showsColumnSQL)
 import Database.Relational.Query.Sub (SubQuery, aggregatedSubQuery, JoinProduct)
 import qualified Database.Relational.Query.Sub as SubQuery
-import Database.Relational.Query.Projectable (PlaceHolders, SqlProjectable, unsafeProjectSql, unsafeShowSql)
+import Database.Relational.Query.Projectable (PlaceHolders, SqlProjectable)
 
 import Database.Relational.Query.Monad.Class (MonadRestrict(..), MonadQualify(..), MonadPartition (..))
 import Database.Relational.Query.Monad.Trans.Join (join')
@@ -104,5 +104,8 @@
      => Projection OverWindow a
      -> Window c ()
      -> Projection c a
-wp `over` win = unsafeProjectSql $ unwords [unsafeShowSql wp, showStringSQL (composeOver pt ot)]  where
-  (((), ot), pt) = extractWindow win
+wp `over` win =
+  Projection.unsafeFromSqlTerms
+  [ showsColumnSQL c <> composeOver pt ot
+  | c <- Projection.columns wp
+  ]  where (((), ot), pt) = extractWindow win
diff --git a/src/Database/Relational/Query/Projectable.hs b/src/Database/Relational/Query/Projectable.hs
--- a/src/Database/Relational/Query/Projectable.hs
+++ b/src/Database/Relational/Query/Projectable.hs
@@ -188,7 +188,7 @@
 -- | Unsafely make projection unary operator from SQL keyword.
 unsafeUniOp :: (ProjectableShowSql p0, SqlProjectable p1)
              => (Keyword -> Keyword) -> p0 a -> p1 b
-unsafeUniOp u = unsafeProjectSql . SQL.strUniOp u . unsafeShowSql
+unsafeUniOp u = unsafeProjectSql' . u . unsafeShowSql'
 
 unsafeFlatUniOp :: (SqlProjectable p, ProjectableShowSql p)
                => Keyword -> p a -> p b
diff --git a/test/Lex.hs b/test/Lex.hs
--- a/test/Lex.hs
+++ b/test/Lex.hs
@@ -3,18 +3,40 @@
 import Control.Applicative
   ((<$>), (<*>), pure, (*>), (<*), (<|>), empty, many, some)
 import Control.Monad (void)
-import Control.Monad.Trans.State (StateT, runStateT, get, put)
+import Control.Monad.Trans.State (StateT (..), evalStateT, get, put)
 import Control.Monad.Trans.Class (lift)
 import Data.Maybe (listToMaybe, fromMaybe)
 import Data.Map (Map)
 import qualified Data.Map as Map
-import Text.ParserCombinators.ReadP (ReadP, readP_to_S)
-import qualified Text.ParserCombinators.ReadP as ReadP
 
 import Distribution.TestSuite (Test)
 import Distribution.TestSuite.Compat (prop')
 
 
+type P = StateT String Maybe
+
+satisfy' :: (Char -> Bool) -> P Char
+satisfy' p = do
+  s <- get
+  case s of
+    c:cs -> if p c
+            then  put cs *> pure c
+            else  empty
+    []   ->       empty
+
+char' :: Char -> P Char
+char' x = satisfy' (== x)
+
+look' :: P String
+look' =  get
+
+eof' :: P ()
+eof' =  do
+  s <- get
+  case s of
+    []   -> pure ()
+    _:_  -> empty
+
 type Var = Int
 
 data Token
@@ -37,13 +59,16 @@
   , varMap   ::  Map VarName Var
   } deriving Eq
 
-type Parser = StateT QState ReadP
+type Parser = StateT QState P
 
+run' :: Parser a -> String -> Maybe (a, String)
+run' p = runStateT (evalStateT p (QState { nextVar = 0, varMap = Map.empty }))
+
 char :: Char -> Parser Char
-char =  lift . ReadP.char
+char =  lift . char'
 
 satisfy :: (Char -> Bool) -> Parser Char
-satisfy =  lift . ReadP.satisfy
+satisfy =  lift . satisfy'
 
 quote :: Parser Char
 quote =  char '\''
@@ -58,7 +83,7 @@
 symbol =  Symbol <$> symbol'
 
 opCharset :: [Char]
-opCharset =  "=<>+-*|"
+opCharset =  "=<>+-*/|"
 
 op :: Parser Token
 op =  Op <$> some (satisfy (`elem` opCharset))
@@ -101,7 +126,7 @@
 spaces =  many space *> pure ()
 
 peekChar :: Parser (Maybe Char)
-peekChar =  listToMaybe <$> lift ReadP.look
+peekChar =  listToMaybe <$> lift look'
 
 peekSatisfy :: (Char -> Bool) -> Parser Char
 peekSatisfy pre = do
@@ -130,7 +155,7 @@
 placeholder =  char '?' *> pure PlaceHolder
 
 eof :: Parser ()
-eof =  lift ReadP.eof
+eof =  lift eof'
 
 token :: Parser Token
 token =
@@ -147,12 +172,6 @@
 tokens :: Parser [Token]
 tokens =  (many $ token <* spaces) <* eof
 
-run' :: Parser a -> String -> Maybe (a, String)
-run' p =
-  (result <$>) . listToMaybe .
-  readP_to_S (runStateT p (QState { nextVar = 0, varMap = Map.empty }))  where
-    result ((a, _s), in') = (a, in')
-
 run :: String -> Maybe [Token]
 run =  (fst <$>) . run' tokens
 
@@ -165,7 +184,7 @@
 
 eqProp' :: String -> (a -> String) -> a -> String -> Test
 eqProp' name t x est = prop' name (Just em) (t x `eq` est)
-  where em = unlines [show . run $ t x, " -- NOT EQUALS! --", show $ run est]
+  where em = unlines [show $ run $ t x, " -- compares --", show $ run est]
 
 eqProp :: Show a => String -> a -> String -> Test
 eqProp name = eqProp' name show
diff --git a/test/SQLs.hs b/test/SQLs.hs
--- a/test/SQLs.hs
+++ b/test/SQLs.hs
@@ -3,21 +3,39 @@
 import Distribution.TestSuite (Test)
 import Distribution.TestSuite.Compat (TestList, testList)
 
+import Control.Applicative ((<$>), (<*>))
+
 import Lex (eqProp)
 import Model
 
-import Data.Int (Int32)
+import Data.Int (Int32, Int64)
 import Database.Relational.Query
 
-base :: [Test]
-base =
+
+numBin :: (Projection Flat Int32 -> Projection Flat Int32 -> Projection Flat r) -> Relation () r
+numBin op = relation $ do
+  return $ value 5 `op` value 3
+
+_p_numBin :: (Projection Flat Int32 -> Projection Flat Int32 -> Projection Flat r) -> IO ()
+_p_numBin = print . numBin
+
+bin :: [Test]
+bin =
+  [ eqProp "plus"  (numBin (.+.)) "SELECT ALL (5 + 3) AS f0"
+  , eqProp "minus" (numBin (.-.)) "SELECT ALL (5 - 3) AS f0"
+  , eqProp "mult"  (numBin (.*.)) "SELECT ALL (5 * 3) AS f0"
+  , eqProp "div"   (numBin (./.)) "SELECT ALL (5 / 3) AS f0"
+  ]
+
+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_base :: IO ()
-_p_base =  mapM_ print [show setA, show setB, show setC]
+_p_tables :: IO ()
+_p_tables =  mapM_ print [show setA, show setB, show setC]
 
 cross :: Relation () (SetA, SetB)
 cross =  setA `inner` setB `on'` []
@@ -37,15 +55,25 @@
 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)"
+    "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)"
+    "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)"
+    "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)"
+    "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)"
+    "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 ()
@@ -73,12 +101,23 @@
   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)"
+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)"
-          ]
+  , 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]
@@ -102,15 +141,105 @@
   return $ fromMaybe (value 1) (a ?! intA0') >< b
 
 maybes :: [Test]
-maybes =  [ 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)"
-          ]
+maybes =
+  [ 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)"
+  ]
 
 _p_maybes :: IO ()
 _p_maybes =  mapM_ print [show justX, show maybeX]
 
+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]
+
+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'
 
@@ -132,19 +261,27 @@
 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"
-        ]
+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'
 
+insertQueryX :: InsertQuery ()
+insertQueryX =  derivedInsertQuery setAFromB setA
+
 updateKeyX :: KeyUpdate Int32 SetA
 updateKeyX =  primaryUpdate tableOfSetA
 
@@ -160,16 +297,21 @@
   return unitPlaceHolder
 
 effs :: [Test]
-effs =  [ eqProp "insert" insertX
-          "INSERT INTO TEST.set_a (int_a0, str_a1, str_a2) VALUES (?, ?, ?)"
-        , 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')"
-        ]
+effs =
+  [ eqProp "insert" insertX
+    "INSERT INTO TEST.set_a (int_a0, str_a1, str_a2) 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')"
+  ]
 
 tests :: TestList
 tests =
-  testList $ concat [base, directJoins, join3s, maybes, exps, effs]
+  testList
+  $ concat [bin, tables, directJoins, join3s, maybes,
+            groups, partitions, exps, effs]
