diff --git a/Database/Groundhog/Core.hs b/Database/Groundhog/Core.hs
--- a/Database/Groundhog/Core.hs
+++ b/Database/Groundhog/Core.hs
@@ -1,4 +1,4 @@
-{-# LANGUAGE GADTs, TypeFamilies, ExistentialQuantification, MultiParamTypeClasses, FunctionalDependencies, FlexibleContexts, FlexibleInstances, GeneralizedNewtypeDeriving, EmptyDataDecls #-}
+{-# LANGUAGE GADTs, TypeFamilies, ExistentialQuantification, MultiParamTypeClasses, FunctionalDependencies, FlexibleContexts, FlexibleInstances, GeneralizedNewtypeDeriving, EmptyDataDecls, ConstraintKinds #-}
 -- | This module defines the functions and datatypes used throughout the framework.
 -- Most of them are for the internal use
 module Database.Groundhog.Core
@@ -90,6 +90,7 @@
 import Data.Map (Map)
 import Data.Time (Day, TimeOfDay, UTCTime)
 import Data.Time.LocalTime (ZonedTime, zonedTimeToUTC, zonedTimeToLocalTime, zonedTimeZone)
+import GHC.Exts (Constraint)
 
 -- | Only instances of this class can be persisted in a database
 class (PersistField v, PurePersistField (AutoKey v)) => PersistEntity v where
@@ -146,27 +147,29 @@
 
 data ExprRelation = Eq | Ne | Gt | Lt | Ge | Le deriving Show
 
-data Update db r = forall f a . Assignable f db r a => Update f (UntypedExpr db r)
+data Update db r = forall f a . (Assignable f a, ProjectionDb f db, ProjectionRestriction f r) => Update f (UntypedExpr db r)
 
 -- | Defines sort order of a result-set
-data Order db r = forall a f . (FieldLike f db r a) => Asc  f
-                | forall a f . (FieldLike f db r a) => Desc f
+data Order db r = forall a f . (Projection f a, ProjectionDb f db, ProjectionRestriction f r) => Asc  f
+                | forall a f . (Projection f a, ProjectionDb f db, ProjectionRestriction f r) => Desc f
 
 -- | It is used to map field to column names. It can be either a column name for a regular field of non-embedded type or a list of this field and the outer fields in reverse order. Eg, fieldChain $ SomeField ~> Tuple2_0Selector may result in [(\"val0\", DbString), (\"some\", DbEmbedded False [dbType \"\", dbType True])].
 type FieldChain = ((String, DbType), [(String, EmbeddedDef)])
 
 -- | Any data that can be fetched from a database
-class PersistField a => Projection p db r a | p -> db r a where
+class PersistField a => Projection p a | p -> a where
+  type ProjectionDb p db :: Constraint
+  type ProjectionRestriction p r :: Constraint
   -- | It returns multiple expressions that can be transformed into values which can be selected. Difflist is used for concatenation efficiency.
-  projectionExprs :: p -> [UntypedExpr db r] -> [UntypedExpr db r]
+  projectionExprs :: (ProjectionDb p db, ProjectionRestriction p r) => p -> [UntypedExpr db r] -> [UntypedExpr db r]
   -- | It is like 'fromPersistValues'. However, we cannot use it for projections in all cases. For the 'PersistEntity' instances 'fromPersistValues' expects entity id instead of the entity values.
   projectionResult :: PersistBackend m => p -> [PersistValue] -> m (a, [PersistValue])
 
 -- | This subset of Projection instances is for things that behave like fields. Namely, they can occur in condition expressions (for example, Field and SubField) and on the left side of update statements. For example \"lower(field)\" is a valid Projection, but not Field like because it cannot be on the left side. Datatypes that index PostgreSQL arrays \"arr[5]\" or access composites \"(comp).subfield\" are valid instances of Assignable.
-class Projection f db r a => Assignable f db r a | f -> r a
+class Projection f a => Assignable f a | f -> a
 
 -- | This subset of Assignable is for plain database fields.
-class Assignable f db r a => FieldLike f db r a | f -> r a where
+class Assignable f a => FieldLike f a | f -> a where
   fieldChain :: f -> FieldChain
 
 class PersistField v => Embedded v where
@@ -175,7 +178,7 @@
 
 infixl 5 ~>
 -- | Accesses fields of the embedded datatypes. For example, @SomeField ==. (\"abc\", \"def\") ||. SomeField ~> Tuple2_0Selector ==. \"def\"@
-(~>) :: (EntityConstr v c, FieldLike f db (RestrictionHolder v c) a, Embedded a) => f -> Selector a a' -> SubField v c a'
+(~>) :: (EntityConstr v c, FieldLike f a, ProjectionRestriction f (RestrictionHolder v c), Embedded a) => f -> Selector a a' -> SubField v c a'
 field ~> sel = case fieldChain field of
   ((name, typ), prefix) -> case typ of
     DbEmbedded emb@(EmbeddedDef _ ts) _ -> SubField (ts !! selectorNum sel, (name, emb):prefix)
@@ -298,7 +301,7 @@
   -- | Count total number of records with all constructors. The entity parameter is used only for type inference
   countAll      :: PersistEntity v => v -> m Int
   -- | Fetch projection of some fields. Example: @project (SecondField, ThirdField) $ (FirstField ==. \"abc\" &&. SecondField >. \"def\") \`orderBy\` [Asc ThirdField] \`offsetBy\` 100@
-  project       :: (PersistEntity v, EntityConstr v c, Projection p (PhantomDb m) (RestrictionHolder v c) a, HasSelectOptions opts (PhantomDb m) (RestrictionHolder v c))
+  project       :: (PersistEntity v, EntityConstr v c, Projection p a, ProjectionDb p (PhantomDb m), ProjectionRestriction p (RestrictionHolder v c), HasSelectOptions opts (PhantomDb m) (RestrictionHolder v c))
                 => p
                 -> opts
                 -> m [a]
diff --git a/Database/Groundhog/Expression.hs b/Database/Groundhog/Expression.hs
--- a/Database/Groundhog/Expression.hs
+++ b/Database/Groundhog/Expression.hs
@@ -1,4 +1,4 @@
-{-# LANGUAGE MultiParamTypeClasses, TypeFamilies, FlexibleContexts, FlexibleInstances, FunctionalDependencies, UndecidableInstances, OverlappingInstances, EmptyDataDecls #-}
+{-# LANGUAGE MultiParamTypeClasses, TypeFamilies, FlexibleContexts, FlexibleInstances, FunctionalDependencies, UndecidableInstances, OverlappingInstances, EmptyDataDecls, ConstraintKinds #-}
 
 -- | This module provides mechanism for flexible and typesafe usage of plain data values and fields.
 -- The expressions can used in conditions and right part of Update statement.
@@ -31,7 +31,7 @@
   toExpr :: a -> UntypedExpr db r
 
 -- | This helper class can make type signatures more concise
-class (Expression db r a, PersistField a') => ExpressionOf db r a a'
+class (Expression db r a, PersistField a') => ExpressionOf db r a a' | a -> a'
 
 instance (Expression db r a, Normalize HTrue a (flag, a'), PersistField a') => ExpressionOf db r a a'
 
@@ -83,11 +83,11 @@
 class NormalizeValue t r | t -> r
 -- Normalize @Key v u@ to @v@ only if this key is used for storing @v@.
 instance (TypeEq (DefaultKey v) (Key v u) isDef,
-         NormalizeKey isDef (Key v u) k,
+         NormalizeKey isDef v u k,
          r ~ (Not isDef, Maybe k))
          => NormalizeValue (Maybe (Key v u)) r
 instance (TypeEq (DefaultKey v) (Key v u) isDef,
-         NormalizeKey isDef (Key v u) k,
+         NormalizeKey isDef v u k,
          r ~ (Not isDef, k))
          => NormalizeValue (Key v u) r
 instance r ~ (HTrue, a) => NormalizeValue a r
@@ -96,9 +96,9 @@
 instance b ~ HFalse => TypeEq x y b
 instance TypeEq x x HTrue
 
-class NormalizeKey isDef key r | isDef key -> r, r -> key
-instance r ~ v => NormalizeKey HTrue (Key v u) r
-instance r ~ a => NormalizeKey HFalse a r
+class NormalizeKey isDef v u k | isDef v u -> k, k -> v
+instance k ~ v => NormalizeKey HTrue v u k
+instance k ~ Key v u => NormalizeKey HFalse v u k
 
 type family Not bool
 type instance Not HTrue  = HFalse
@@ -107,7 +107,9 @@
 -- | Update field
 infixr 3 =.
 (=.) ::
-  ( FieldLike f db r a'
+  ( Assignable f a'
+  , ProjectionDb f db
+  , ProjectionRestriction f r
   , Expression db r b
   , Unifiable f b)
   => f -> b -> Update db r
@@ -147,9 +149,10 @@
 
 -- | This function more limited than (==.), but has better type inference.
 -- If you want to compare your value to Nothing with @(==.)@ operator, you have to write the types explicitly @myExpr ==. (Nothing :: Maybe Int)@.
-isFieldNothing :: (Expression db r f, FieldLike f db r (Maybe a), PrimitivePersistField (Maybe a), Unifiable f (Maybe a)) => f -> Cond db r
+-- TODO: restrict db r
+isFieldNothing :: (Expression db r f, Projection f (Maybe a), PrimitivePersistField (Maybe a), Unifiable f (Maybe a)) => f -> Cond db r
 isFieldNothing a = a `eq` Nothing where
-  eq :: (Expression db r f, Expression db r a, FieldLike f db r a, Unifiable f a) => f -> a -> Cond db r
+  eq :: (Expression db r f, Expression db r a, Projection f a, Unifiable f a) => f -> a -> Cond db r
   eq = (==.)
 
 -- | Converts value to 'Expr'. It can help to pass values of different types into functions which expect arguments of the same type, like (+).
diff --git a/Database/Groundhog/Generic/PersistBackendHelpers.hs b/Database/Groundhog/Generic/PersistBackendHelpers.hs
--- a/Database/Groundhog/Generic/PersistBackendHelpers.hs
+++ b/Database/Groundhog/Generic/PersistBackendHelpers.hs
@@ -1,4 +1,4 @@
-{-# LANGUAGE ScopedTypeVariables, FlexibleContexts, OverloadedStrings, RecordWildCards, Rank2Types, TypeFamilies #-}
+{-# LANGUAGE ScopedTypeVariables, FlexibleContexts, OverloadedStrings, RecordWildCards, Rank2Types, TypeFamilies, ConstraintKinds #-}
 
 -- | This helper module contains generic versions of PersistBackend functions
 module Database.Groundhog.Generic.PersistBackendHelpers
@@ -61,7 +61,7 @@
         Just x' -> fail $ "Unexpected number of columns returned: " ++ show x'
         Nothing -> return Nothing
 
-select :: forall m db r v c opts . (SqlDb db, QueryRaw db ~ Snippet db, db ~ PhantomDb m, r ~ RestrictionHolder v c, PersistBackend m, PersistEntity v, EntityConstr v c, HasSelectOptions opts db r)
+select :: forall m db r v c opts . (SqlDb db, db ~ PhantomDb m, r ~ RestrictionHolder v c, PersistBackend m, PersistEntity v, EntityConstr v c, HasSelectOptions opts db r)
        => RenderConfig -> (forall a . Utf8 -> [PersistValue] -> (RowPopper m -> m a) -> m a) -> Utf8 -> opts -> m [v]
 select conf@RenderConfig{..} queryFunc noLimit options = doSelectQuery where
   SelectOptions cond limit offset ords = getSelectOptions options
@@ -69,17 +69,16 @@
   e = entityDef (undefined :: v)
   proxy = undefined :: proxy (PhantomDb m)
   orders = renderOrders conf ords
-  (lim, limps) = case (limit, offset) of
-        (Nothing, Nothing) -> ("", [])
-        (Nothing, o) -> (" " <> noLimit <> " OFFSET ?", [toPrimitivePersistValue proxy o])
-        (l, Nothing) -> (" LIMIT ?", [toPrimitivePersistValue proxy l])
-        (l, o) -> (" LIMIT ? OFFSET ?", [toPrimitivePersistValue proxy l, toPrimitivePersistValue proxy o])
+  lim = case (limit, offset) of
+          (Nothing, Nothing) -> mempty
+          (Nothing, o) -> RenderS (" " <> noLimit <> " OFFSET ?") (toPurePersistValues proxy o)
+          (l, Nothing) -> RenderS " LIMIT ?" (toPurePersistValues proxy l)
+          (l, o) -> RenderS " LIMIT ? OFFSET ?" (toPurePersistValues proxy (l, o))
   cond' = renderCond conf cond
-  fields = renderFields esc (constrParams constr)
-  query = "SELECT " <> fields <> " FROM " <> tableName esc e constr <> whereClause <> orders <> lim
-  whereClause = maybe "" (\c -> " WHERE " <> getQuery c) cond'
-  doSelectQuery = queryFunc query binds $ mapAllRows $ liftM fst . fromEntityPersistValues . (toPrimitivePersistValue proxy cNum:)
-  binds = maybe id getValues cond' $ limps
+  fields = RenderS (renderFields esc (constrParams constr)) id
+  RenderS query binds = "SELECT " <> fields <> " FROM " <> RenderS (tableName esc e constr) id <> whereClause <> orders <> lim
+  whereClause = maybe "" (" WHERE " <>) cond'
+  doSelectQuery = queryFunc query (binds []) $ mapAllRows $ liftM fst . fromEntityPersistValues . (toPrimitivePersistValue proxy cNum:)
   cNum = entityConstrNum (undefined :: proxy v) (undefined :: c a)
   constr = constructors e !! cNum
 
@@ -118,28 +117,27 @@
     Just xs -> liftM (Just . fst) $ fromEntityPersistValues $ PersistInt64 0:xs
     Nothing -> return Nothing
 
-project :: forall m db r v c p opts a'. (SqlDb db, QueryRaw db ~ Snippet db, db ~ PhantomDb m, r ~ RestrictionHolder v c, PersistBackend m, PersistEntity v, EntityConstr v c, Projection p db r a', HasSelectOptions opts db r)
+project :: forall m db r v c p opts a'. (SqlDb db, db ~ PhantomDb m, r ~ RestrictionHolder v c, PersistBackend m, PersistEntity v, EntityConstr v c, Projection p a', ProjectionDb p db, ProjectionRestriction p r, HasSelectOptions opts db r)
         => RenderConfig -> (forall a . Utf8 -> [PersistValue] -> (RowPopper m -> m a) -> m a) -> Utf8 -> p -> opts -> m [a']
 project conf@RenderConfig{..} queryFunc noLimit p options = doSelectQuery where
   SelectOptions cond limit offset ords = getSelectOptions options
   e = entityDef (undefined :: v)
   proxy = undefined :: proxy (PhantomDb m)
   orders = renderOrders conf ords
-  (lim, limps) = case (limit, offset) of
-        (Nothing, Nothing) -> ("", [])
-        (Nothing, o) -> (" " <> noLimit <> " OFFSET ?", [toPrimitivePersistValue proxy o])
-        (l, Nothing) -> (" LIMIT ?", [toPrimitivePersistValue proxy l])
-        (l, o) -> (" LIMIT ? OFFSET ?", [toPrimitivePersistValue proxy l, toPrimitivePersistValue proxy o])
+  lim = case (limit, offset) of
+          (Nothing, Nothing) -> mempty
+          (Nothing, o) -> RenderS (" " <> noLimit <> " OFFSET ?") (toPurePersistValues proxy o)
+          (l, Nothing) -> RenderS " LIMIT ?" (toPurePersistValues proxy l)
+          (l, o) -> RenderS " LIMIT ? OFFSET ?" (toPurePersistValues proxy (l, o))
   cond' = renderCond conf cond
   chains = projectionExprs p []
-  RenderS fields fieldVals = commasJoin $ concatMap (renderExprExtended conf 0) chains
-  query = "SELECT " <> fields <> " FROM " <> tableName esc e constr <> whereClause <> orders <> lim
-  whereClause = maybe "" (\c -> " WHERE " <> getQuery c) cond'
-  doSelectQuery = queryFunc query binds $ mapAllRows $ liftM fst . projectionResult p
-  binds = fieldVals . maybe id getValues cond' $ limps
+  fields = commasJoin $ concatMap (renderExprExtended conf 0) chains
+  RenderS query binds = "SELECT " <> fields <> " FROM " <> RenderS (tableName esc e constr) id <> whereClause <> orders <> lim
+  whereClause = maybe "" (" WHERE " <>) cond'
+  doSelectQuery = queryFunc query (binds []) $ mapAllRows $ liftM fst . projectionResult p
   constr = constructors e !! entityConstrNum (undefined :: proxy v) (undefined :: c a)
 
-count :: forall m db r v c . (SqlDb db, QueryRaw db ~ Snippet db, db ~ PhantomDb m, r ~ RestrictionHolder v c, PersistBackend m, PersistEntity v, EntityConstr v c)
+count :: forall m db r v c . (SqlDb db, db ~ PhantomDb m, r ~ RestrictionHolder v c, PersistBackend m, PersistEntity v, EntityConstr v c)
       => RenderConfig -> (forall a . Utf8 -> [PersistValue] -> (RowPopper m -> m a) -> m a) -> Cond db r -> m Int
 count conf@RenderConfig{..} queryFunc cond = do
   let e = entityDef (undefined :: v)
@@ -211,7 +209,7 @@
       updateQuery = "UPDATE " <> tableName esc e constr <> " SET " <> upds <> " WHERE " <> cond
   execFunc updateQuery (updsVals . condVals $ [])
 
-update :: forall m db r v c . (SqlDb db, QueryRaw db ~ Snippet db, db ~ PhantomDb m, r ~ RestrictionHolder v c, PersistBackend m, PersistEntity v, EntityConstr v c)
+update :: forall m db r v c . (SqlDb db, db ~ PhantomDb m, r ~ RestrictionHolder v c, PersistBackend m, PersistEntity v, EntityConstr v c)
        => RenderConfig -> (Utf8 -> [PersistValue] -> m ()) -> [Update db r] -> Cond db r -> m ()
 update conf@RenderConfig{..} execFunc upds cond = do
   let e = entityDef (undefined :: v)
@@ -224,7 +222,7 @@
       execFunc query (getValues upds' <> maybe mempty getValues cond' $ [])
     Nothing -> return ()
 
-delete :: forall m db r v c . (SqlDb db, QueryRaw db ~ Snippet db, db ~ PhantomDb m, r ~ RestrictionHolder v c, PersistBackend m, PersistEntity v, EntityConstr v c)
+delete :: forall m db r v c . (SqlDb db, db ~ PhantomDb m, r ~ RestrictionHolder v c, PersistBackend m, PersistEntity v, EntityConstr v c)
        => RenderConfig -> (Utf8 -> [PersistValue] -> m ()) -> Cond db r -> m ()
 delete conf@RenderConfig{..} execFunc cond = execFunc query (maybe [] (($ []) . getValues) cond') where
   e = entityDef (undefined :: v)
diff --git a/Database/Groundhog/Generic/Sql.hs b/Database/Groundhog/Generic/Sql.hs
--- a/Database/Groundhog/Generic/Sql.hs
+++ b/Database/Groundhog/Generic/Sql.hs
@@ -74,9 +74,8 @@
     esc  :: Utf8 -> Utf8
 }
 
--- Alas , GHC before 7.2 does not support superclass equality constraints (QueryRaw db ~ Snippet db).
 -- | This class distinguishes databases which support SQL-specific expressions. It contains ad hoc members for features whose syntax differs across the databases.
-class DbDescriptor db => SqlDb db where
+class (DbDescriptor db, QueryRaw db ~ Snippet db) => SqlDb db where
   append :: (ExpressionOf db r a String, ExpressionOf db r b String) => a -> b -> Expr db r String
   signum' :: (ExpressionOf db r x a, Num a) => x -> Expr db r a
   quotRem' :: (ExpressionOf db r x a, ExpressionOf db r y a, Integral a) => x -> y -> (Expr db r a, Expr db r a)
@@ -91,7 +90,7 @@
   logBase' :: (ExpressionOf db r b a, ExpressionOf db r x a, Floating a) => b -> x -> Expr db r a
 
 -- | If we reuse complex expression several times, prerendering it saves time. `RenderConfig` can be obtained with `mkExprWithConf`
-prerenderExpr :: (SqlDb db, QueryRaw db ~ Snippet db) => RenderConfig -> Expr db r a -> Expr db r a
+prerenderExpr :: SqlDb db => RenderConfig -> Expr db r a -> Expr db r a
 prerenderExpr conf (Expr e) = Expr $ ExprRaw $ Snippet $ \_ _ -> prerendered where
   -- Priority of outer operation is not known. Assuming that it is high ensures that parentheses won't be missing.
   prerendered = renderExprExtended conf maxBound e
@@ -102,14 +101,14 @@
 --        x' = prerenderExpr conf x
 --     in x' + x' * x'@
 -- @
-mkExprWithConf :: (SqlDb db, QueryRaw db ~ Snippet db, PersistField a) => (RenderConfig -> Int -> Expr db r a) -> Expr db r a
+mkExprWithConf :: (SqlDb db, PersistField a) => (RenderConfig -> Int -> Expr db r a) -> Expr db r a
 mkExprWithConf f = expr where
   expr = mkExpr $ Snippet $ \conf p -> [renderExprPriority conf p $ toExpr $ (f conf p) `asTypeOf` expr]
 
-renderExpr :: (SqlDb db, QueryRaw db ~ Snippet db) => RenderConfig -> UntypedExpr db r -> RenderS db r
+renderExpr :: SqlDb db => RenderConfig -> UntypedExpr db r -> RenderS db r
 renderExpr conf expr = renderExprPriority conf 0 expr
 
-renderExprPriority :: (SqlDb db, QueryRaw db ~ Snippet db) => RenderConfig -> Int -> UntypedExpr db r -> RenderS db r
+renderExprPriority :: SqlDb db => RenderConfig -> Int -> UntypedExpr db r -> RenderS db r
 renderExprPriority conf p expr = (case expr of
   ExprRaw (Snippet f) -> let vals = f conf p in ensureOne vals id
   ExprField f -> let fs = renderChain conf f []
@@ -125,7 +124,7 @@
       [x] -> f x
       xs' -> error $ "renderExprPriority: expected one column field, found " ++ show (length xs')
 
-renderExprExtended :: (SqlDb db, QueryRaw db ~ Snippet db) => RenderConfig -> Int -> UntypedExpr db r -> [RenderS db r]
+renderExprExtended :: SqlDb db => RenderConfig -> Int -> UntypedExpr db r -> [RenderS db r]
 renderExprExtended conf p expr = (case expr of
   ExprRaw (Snippet f) -> f conf p
   ExprField f -> map (flip RenderS id) $ renderChain conf f []
@@ -156,14 +155,14 @@
 parens :: Int -> Int -> RenderS db r -> RenderS db r
 parens p1 p2 expr = if p1 < p2 then fromChar '(' <> expr <> fromChar ')' else expr
 
-operator :: (SqlDb db, QueryRaw db ~ Snippet db, Expression db r a, Expression db r b) => Int -> String -> a -> b -> Snippet db r
+operator :: (SqlDb db, Expression db r a, Expression db r b) => Int -> String -> a -> b -> Snippet db r
 operator pr op = \a b -> Snippet $ \conf p ->
   [parens pr p $ renderExprPriority conf pr (toExpr a) <> fromString op <> renderExprPriority conf pr (toExpr b)]
 
-function :: (SqlDb db, QueryRaw db ~ Snippet db) => String -> [UntypedExpr db r] -> Snippet db r
+function :: SqlDb db => String -> [UntypedExpr db r] -> Snippet db r
 function func args = Snippet $ \conf _ -> [fromString func <> fromChar '(' <> commasJoin (map (renderExpr conf) args) <> fromChar ')']
 
-mkExpr :: (SqlDb db, QueryRaw db ~ Snippet db) => Snippet db r -> Expr db r a
+mkExpr :: SqlDb db => Snippet db r -> Expr db r a
 mkExpr = Expr . ExprRaw
 
 #if !MIN_VERSION_base(4, 5, 0)
@@ -174,14 +173,14 @@
 
 {-# INLINABLE renderCond #-}
 -- | Renders conditions for SQL backend. Returns Nothing if the fields don't have any columns.
-renderCond :: (SqlDb db, QueryRaw db ~ Snippet db)
+renderCond :: SqlDb db
   => RenderConfig
   -> Cond db r -> Maybe (RenderS db r)
 renderCond conf cond = renderCondPriority conf 0 cond where
 
 {-# INLINABLE renderCondPriority #-}
 -- | Renders conditions for SQL backend. Returns Nothing if the fields don't have any columns.
-renderCondPriority :: (SqlDb db, QueryRaw db ~ Snippet db)
+renderCondPriority :: SqlDb db
   => RenderConfig
   -> Int -> Cond db r -> Maybe (RenderS db r)
 renderCondPriority conf@RenderConfig{..} priority cond = go cond priority where
@@ -249,12 +248,13 @@
 defaultShowPrim (PersistCustom _ _) = error "Unexpected PersistCustom"
 
 {-# INLINABLE renderOrders #-}
-renderOrders :: RenderConfig -> [Order db r] -> Utf8
+renderOrders :: SqlDb db => RenderConfig -> [Order db r] -> RenderS db r
 renderOrders _ [] = mempty
 renderOrders conf xs = if null orders then mempty else " ORDER BY " <> commasJoin orders where
-  orders = foldr go [] xs
-  go (Asc a) acc = renderChain conf (fieldChain a) acc
-  go (Desc a) acc = renderChain conf' (fieldChain a) acc where
+  orders = concatMap go xs
+  rend conf' a = map (commasJoin . renderExprExtended conf' 0) $ projectionExprs a []
+  go (Asc a) = rend conf a
+  go (Desc a) = rend conf' a where
      conf' = conf { esc = \f -> esc conf f <> " DESC" }
 
 {-# INLINABLE renderFields #-}
@@ -294,7 +294,7 @@
   go (f:fs) = a <> f <> go fs
 
 {-# INLINABLE renderUpdates #-}
-renderUpdates :: (SqlDb db, QueryRaw db ~ Snippet db) => RenderConfig -> [Update db r] -> Maybe (RenderS db r)
+renderUpdates :: SqlDb db => RenderConfig -> [Update db r] -> Maybe (RenderS db r)
 renderUpdates conf upds = (case mapMaybe go upds of
   [] -> Nothing
   xs -> Just $ commasJoin xs) where
diff --git a/Database/Groundhog/Generic/Sql/Functions.hs b/Database/Groundhog/Generic/Sql/Functions.hs
--- a/Database/Groundhog/Generic/Sql/Functions.hs
+++ b/Database/Groundhog/Generic/Sql/Functions.hs
@@ -23,36 +23,36 @@
 import Database.Groundhog.Expression
 import Database.Groundhog.Generic.Sql
 
-in_ :: (SqlDb db, QueryRaw db ~ Snippet db, Expression db r a, Expression db r b, PrimitivePersistField b, Unifiable a b) =>
+in_ :: (SqlDb db, Expression db r a, Expression db r b, PrimitivePersistField b, Unifiable a b) =>
     a -> [b] -> Cond db r
 in_ _ [] = CondEmpty
 in_ a bs = CondRaw $ Snippet $ \conf p -> [parens 45 p $ renderExpr conf (toExpr a) <> " IN (" <> commasJoin (map (renderExpr conf . toExpr) bs) <> ")"]
 
-notIn_ :: (SqlDb db, QueryRaw db ~ Snippet db, Expression db r a, Expression db r b, PrimitivePersistField b, Unifiable a b) =>
+notIn_ :: (SqlDb db, Expression db r a, Expression db r b, PrimitivePersistField b, Unifiable a b) =>
        a -> [b] -> Cond db r
 notIn_ _ [] = CondEmpty
 notIn_ a bs = CondRaw $ Snippet $ \conf p -> [parens 45 p $ renderExpr conf (toExpr a) <> " NOT IN (" <> commasJoin (map (renderExpr conf . toExpr) bs) <> ")"]
 
-like :: (SqlDb db, QueryRaw db ~ Snippet db, ExpressionOf db r a a', IsString a') => a -> String -> Cond db r
+like :: (SqlDb db, ExpressionOf db r a a', IsString a') => a -> String -> Cond db r
 like a b = CondRaw $ operator 40 " LIKE " a b
 
-notLike :: (SqlDb db, QueryRaw db ~ Snippet db, ExpressionOf db r a a', IsString a') => a -> String -> Cond db r
+notLike :: (SqlDb db, ExpressionOf db r a a', IsString a') => a -> String -> Cond db r
 notLike a b = CondRaw $ operator 40 " NOT LIKE " a b
 
-lower :: (SqlDb db, QueryRaw db ~ Snippet db, ExpressionOf db r a a', IsString a') => a -> Expr db r a'
+lower :: (SqlDb db, ExpressionOf db r a a', IsString a') => a -> Expr db r a'
 lower a = mkExpr $ function "lower" [toExpr a]
 
-upper :: (SqlDb db, QueryRaw db ~ Snippet db, ExpressionOf db r a a', IsString a') => a -> Expr db r a'
+upper :: (SqlDb db, ExpressionOf db r a a', IsString a') => a -> Expr db r a'
 upper a = mkExpr $ function "upper" [toExpr a]
 
-cot :: (FloatingSqlDb db, QueryRaw db ~ Snippet db, ExpressionOf db r a a', Floating a') => a -> Expr db r a'
+cot :: (FloatingSqlDb db, ExpressionOf db r a a', Floating a') => a -> Expr db r a'
 cot a = mkExpr $ function "cot" [toExpr a]
 
-radians, degrees :: (FloatingSqlDb db, QueryRaw db ~ Snippet db, ExpressionOf db r a a', Floating a') => a -> Expr db r a'
+radians, degrees :: (FloatingSqlDb db, ExpressionOf db r a a', Floating a') => a -> Expr db r a'
 radians x = mkExpr $ function "radians" [toExpr x]
 degrees x = mkExpr $ function "degrees" [toExpr x]
 
-instance (SqlDb db, QueryRaw db ~ Snippet db, PersistField a, Num a) => Num (Expr db r a) where
+instance (SqlDb db, PersistField a, Num a) => Num (Expr db r a) where
   a + b = mkExpr $ operator 60 "+" a b
   a - b = mkExpr $ operator 60 "-" a b
   a * b = mkExpr $ operator 70 "*" a b
@@ -60,11 +60,11 @@
   abs a = mkExpr $ function "abs" [toExpr a]
   fromInteger a = Expr $ toExpr (fromIntegral a :: Int64)
 
-instance (SqlDb db, QueryRaw db ~ Snippet db, PersistField a, Fractional a) => Fractional (Expr db r a) where
+instance (SqlDb db, PersistField a, Fractional a) => Fractional (Expr db r a) where
   a / b = mkExpr $ operator 70 "/" a b
   fromRational a = Expr $ toExpr (fromRational a :: Double)
 
-instance (FloatingSqlDb db, QueryRaw db ~ Snippet db, PersistField a, Floating a) => Floating (Expr db r a) where
+instance (FloatingSqlDb db, PersistField a, Floating a) => Floating (Expr db r a) where
   pi = mkExpr $ function "pi" []
   exp x = mkExpr $ function "exp" [toExpr x]
   sqrt x = mkExpr $ function "sqrt" [toExpr x]
@@ -84,20 +84,20 @@
   atanh x = log ((1 + x) / (1 - x)) / 2
   acosh x = log $ x + sqrt (x * x - 1)
 
-instance (SqlDb db, QueryRaw db ~ Snippet db, PersistField a, Ord a) => Ord (Expr db r a) where
+instance (SqlDb db, PersistField a, Ord a) => Ord (Expr db r a) where
   compare = error "compare: instance Ord (Expr db r a) does not have implementation"
   (<=) = error "(<=): instance Ord (Expr db r a) does not have implementation"
   max a b = mkExpr $ function "max" [toExpr a, toExpr b]
   min a b = mkExpr $ function "min" [toExpr a, toExpr b]
 
-instance (SqlDb db, QueryRaw db ~ Snippet db, PersistField a, Real a) => Real (Expr db r a) where
+instance (SqlDb db, PersistField a, Real a) => Real (Expr db r a) where
   toRational = error "toRational: instance Real (Expr db r a) is made only for Integral superclass constraint"
 
-instance (SqlDb db, QueryRaw db ~ Snippet db, PersistField a, Enum a) => Enum (Expr db r a) where
+instance (SqlDb db, PersistField a, Enum a) => Enum (Expr db r a) where
   toEnum = error "toEnum: instance Enum (Expr db r a) is made only for Integral superclass constraint"
   fromEnum = error "fromEnum: instance Enum (Expr db r a) is made only for Integral superclass constraint"
 
-instance (SqlDb db, QueryRaw db ~ Snippet db, PurePersistField a, Integral a) => Integral (Expr db r a) where
+instance (SqlDb db, PurePersistField a, Integral a) => Integral (Expr db r a) where
   quotRem x y = quotRem' x y
   divMod x y = (div', mod') where
     div' = mkExprWithConf $ \conf _ -> let
@@ -115,7 +115,7 @@
     zero = 0 `asTypeOf` ((undefined :: Expr db r a -> a) x)
   toInteger = error "toInteger: instance Integral (Expr db r a) does not have implementation"
 
-case_ :: (SqlDb db, QueryRaw db ~ Snippet db, ExpressionOf db r a a', ExpressionOf db r b a')
+case_ :: (SqlDb db, ExpressionOf db r a a', ExpressionOf db r b a')
       => [(Cond db r, a)] -- ^ Conditions
       -> b          -- ^ It is returned when none of conditions is true
       -> Expr db r a'
diff --git a/Database/Groundhog/Instances.hs b/Database/Groundhog/Instances.hs
--- a/Database/Groundhog/Instances.hs
+++ b/Database/Groundhog/Instances.hs
@@ -1,4 +1,4 @@
-{-# LANGUAGE TypeFamilies, GADTs, TypeSynonymInstances, OverlappingInstances, MultiParamTypeClasses, FlexibleInstances, UndecidableInstances #-}
+{-# LANGUAGE TypeFamilies, GADTs, TypeSynonymInstances, OverlappingInstances, MultiParamTypeClasses, FlexibleInstances, UndecidableInstances, CPP, ConstraintKinds #-}
 {-# OPTIONS_GHC -fno-warn-orphans #-}
 module Database.Groundhog.Instances (Selector(..)) where
 
@@ -8,7 +8,11 @@
 import qualified Data.Text as T
 import qualified Data.Text.Encoding as T
 import qualified Data.Text.Encoding.Error as T
+#if MIN_VERSION_base(4, 7, 0)
+import Data.Bits (finiteBitSize)
+#else
 import Data.Bits (bitSize)
+#endif
 import Data.ByteString.Char8 (ByteString, unpack)
 import Data.Int (Int8, Int16, Int32, Int64)
 import Data.Time (Day, TimeOfDay, UTCTime)
@@ -267,8 +271,12 @@
   persistName _ = "Int"
   toPersistValues = primToPersistValue
   fromPersistValues = primFromPersistValue
-  dbType a = DbTypePrimitive (if bitSize a == 32 then DbInt32 else DbInt64) False Nothing Nothing
+  dbType a = DbTypePrimitive (if finiteBitSize a == 32 then DbInt32 else DbInt64) False Nothing Nothing where
+#if !MIN_VERSION_base(4, 7, 0)
+    finiteBitSize = bitSize
+#endif
 
+
 instance PersistField Int8 where
   persistName _ = "Int8"
   toPersistValues = primToPersistValue
@@ -446,27 +454,39 @@
   fromPersistValues = primFromPersistValue
   dbType a = dbType ((undefined :: KeyForBackend db v -> v) a)
 
-instance (EntityConstr v c, PersistField a) => Projection (Field v c a) db (RestrictionHolder v c) a where
+instance (EntityConstr v c, PersistField a) => Projection (Field v c a) a where
+  type ProjectionDb (Field v c a) db = ()
+  type ProjectionRestriction (Field v c a) r = r ~ RestrictionHolder v c
   projectionExprs f = (ExprField (fieldChain f):)
   projectionResult _ = fromPersistValues
 
-instance (EntityConstr v c, PersistField a) => Projection (SubField v c a) db (RestrictionHolder v c) a where
+instance (EntityConstr v c, PersistField a) => Projection (SubField v c a) a where
+  type ProjectionDb (SubField v c a) db = ()
+  type ProjectionRestriction (SubField v c a) r = r ~ RestrictionHolder v c
   projectionExprs f = (ExprField (fieldChain f):)
   projectionResult _ = fromPersistValues
 
-instance PersistField a => Projection (Expr db r a) db r a where
+instance PersistField a => Projection (Expr db r a) a where
+  type ProjectionDb (Expr db r a) db' = db ~ db'
+  type ProjectionRestriction (Expr db r a) r' = r ~ r'
   projectionExprs (Expr e) = (e:)
   projectionResult _ = fromPersistValues
 
-instance a ~ Bool => Projection (Cond db r) db r a where
+instance a ~ Bool => Projection (Cond db r) a where
+  type ProjectionDb (Cond db r) db' = db ~ db'
+  type ProjectionRestriction (Cond db r) r' = r ~ r'
   projectionExprs cond = (ExprCond cond:)
   projectionResult _ = fromPersistValues
 
-instance (EntityConstr v c, a ~ AutoKey v) => Projection (AutoKeyField v c) db (RestrictionHolder v c) a where
+instance (EntityConstr v c, a ~ AutoKey v) => Projection (AutoKeyField v c) a where
+  type ProjectionDb (AutoKeyField v c) db = ()
+  type ProjectionRestriction (AutoKeyField v c) r = r ~ RestrictionHolder v c
   projectionExprs f = (ExprField (fieldChain f):)
   projectionResult _ = fromPersistValues
 
-instance EntityConstr v c => Projection (c (ConstructorMarker v)) db (RestrictionHolder v c) v where
+instance EntityConstr v c => Projection (c (ConstructorMarker v)) v where
+  type ProjectionDb (c (ConstructorMarker v)) db = ()
+  type ProjectionRestriction (c (ConstructorMarker v)) r = r ~ RestrictionHolder v c
   projectionExprs c = ((map ExprField chains)++) where
     chains = map (\f -> (f, [])) $ constrParams constr
     e = entityDef ((undefined :: c (ConstructorMarker v) -> v) c)
@@ -475,22 +495,28 @@
   projectionResult c xs = toSinglePersistValue cNum >>= \cNum' -> fromEntityPersistValues (cNum':xs) where
     cNum = entityConstrNum ((undefined :: c (ConstructorMarker v) -> proxy v) c) c
 
-instance (PersistEntity v, IsUniqueKey k, k ~ Key v (Unique u), r ~ RestrictionHolder v c)
-      => Projection (u (UniqueMarker v)) db r k where
+instance (PersistEntity v, IsUniqueKey k, k ~ Key v (Unique u))
+      => Projection (u (UniqueMarker v)) k where
+  type ProjectionDb (u (UniqueMarker v)) db = ()
+  type ProjectionRestriction (u (UniqueMarker v)) (RestrictionHolder v' c) = v ~ v'
   projectionExprs u = ((map ExprField chains)++) where
     UniqueDef _ _ uFields = constrUniques constr !! uniqueNum ((undefined :: u (UniqueMarker v) -> Key v (Unique u)) u)
     chains = map (\f -> (f, [])) uFields
     constr = head $ constructors (entityDef ((undefined :: u (UniqueMarker v) -> v) u))
   projectionResult _ = fromPersistValues
 
-instance (Projection a1 db r a1', Projection a2 db r a2') => Projection (a1, a2) db r (a1', a2') where
+instance (Projection a1 a1', Projection a2 a2') => Projection (a1, a2) (a1', a2') where
+  type ProjectionDb (a1, a2) db = (ProjectionDb a1 db, ProjectionDb a2 db)
+  type ProjectionRestriction (a1, a2) r = (ProjectionRestriction a1 r, ProjectionRestriction a2 r)
   projectionExprs (a1, a2) = projectionExprs a1 . projectionExprs a2
   projectionResult (a', b') xs = do
     (a, rest0) <- projectionResult a' xs
     (b, rest1) <- projectionResult b' rest0
     return ((a, b), rest1)
 
-instance (Projection a1 db r a1', Projection a2 db r a2', Projection a3 db r a3') => Projection (a1, a2, a3) db r (a1', a2', a3') where
+instance (Projection a1 a1', Projection a2 a2', Projection a3 a3') => Projection (a1, a2, a3) (a1', a2', a3') where
+  type ProjectionDb (a1, a2, a3) db = (ProjectionDb (a1, a2) db, ProjectionDb a3 db)
+  type ProjectionRestriction (a1, a2, a3) r = (ProjectionRestriction (a1, a2) r, ProjectionRestriction a3 r)
   projectionExprs (a1, a2, a3) = projectionExprs a1 . projectionExprs a2 . projectionExprs a3
   projectionResult (a', b', c') xs = do
     (a, rest0) <- projectionResult a' xs
@@ -498,7 +524,9 @@
     (c, rest2) <- projectionResult c' rest1
     return ((a, b, c), rest2)
 
-instance (Projection a1 db r a1', Projection a2 db r a2', Projection a3 db r a3', Projection a4 db r a4') => Projection (a1, a2, a3, a4) db r (a1', a2', a3', a4') where
+instance (Projection a1 a1', Projection a2 a2', Projection a3 a3', Projection a4 a4') => Projection (a1, a2, a3, a4) (a1', a2', a3', a4') where
+  type ProjectionDb (a1, a2, a3, a4) db = (ProjectionDb (a1, a2, a3) db, ProjectionDb a4 db)
+  type ProjectionRestriction (a1, a2, a3, a4) r = (ProjectionRestriction (a1, a2, a3) r, ProjectionRestriction a4 r)
   projectionExprs (a1, a2, a3, a4) = projectionExprs a1 . projectionExprs a2 . projectionExprs a3 . projectionExprs a4
   projectionResult (a', b', c', d') xs = do
     (a, rest0) <- projectionResult a' xs
@@ -507,7 +535,9 @@
     (d, rest3) <- projectionResult d' rest2
     return ((a, b, c, d), rest3)
 
-instance (Projection a1 db r a1', Projection a2 db r a2', Projection a3 db r a3', Projection a4 db r a4', Projection a5 db r a5') => Projection (a1, a2, a3, a4, a5) db r (a1', a2', a3', a4', a5') where
+instance (Projection a1 a1', Projection a2 a2', Projection a3 a3', Projection a4 a4', Projection a5 a5') => Projection (a1, a2, a3, a4, a5) (a1', a2', a3', a4', a5') where
+  type ProjectionDb (a1, a2, a3, a4, a5) db = (ProjectionDb (a1, a2, a3, a4) db, ProjectionDb a5 db)
+  type ProjectionRestriction (a1, a2, a3, a4, a5) r = (ProjectionRestriction (a1, a2, a3, a4) r, ProjectionRestriction a5 r)
   projectionExprs (a1, a2, a3, a4, a5) = projectionExprs a1 . projectionExprs a2 . projectionExprs a3 . projectionExprs a4 . projectionExprs a5
   projectionResult (a', b', c', d', e') xs = do
     (a, rest0) <- projectionResult a' xs
@@ -517,12 +547,12 @@
     (e, rest4) <- projectionResult e' rest3
     return ((a, b, c, d, e), rest4)
 
-instance (EntityConstr v c, Projection (AutoKeyField v c) db r a') => Assignable (AutoKeyField v c) db r a'
-instance (EntityConstr v c, Projection (SubField v c a) db r a') => Assignable (SubField v c a) db r a'
-instance (EntityConstr v c, Projection (Field v c a) db r a') => Assignable (Field v c a) db r a'
-instance (PersistEntity v, IsUniqueKey (Key v (Unique u)), Projection (u (UniqueMarker v)) db r a') => Assignable (u (UniqueMarker v)) db r a'
+instance (EntityConstr v c, a ~ AutoKey v) => Assignable (AutoKeyField v c) a
+instance (EntityConstr v c, PersistField a) => Assignable (SubField v c a) a
+instance (EntityConstr v c, PersistField a) => Assignable (Field v c a) a
+instance (PersistEntity v, IsUniqueKey k, k ~ Key v (Unique u)) => Assignable (u (UniqueMarker v)) k
 
-instance (EntityConstr v c, a ~ AutoKey v) => FieldLike (AutoKeyField v c) db (RestrictionHolder v c) a where
+instance (EntityConstr v c, a ~ AutoKey v) => FieldLike (AutoKeyField v c) a where
   fieldChain a = chain where
     chain = ((name, dbType k), [])
     -- if it is Nothing, the name would not be used because the type will be () with no columns
@@ -532,14 +562,14 @@
     e = entityDef ((undefined :: AutoKeyField v c -> v) a)
     cNum = entityConstrNum ((undefined :: AutoKeyField v c -> proxy v) a) ((undefined :: AutoKeyField v c -> c (ConstructorMarker v)) a)
 
-instance (EntityConstr v c, PersistField a) => FieldLike (SubField v c a) db (RestrictionHolder v c) a where
+instance (EntityConstr v c, PersistField a) => FieldLike (SubField v c a) a where
   fieldChain (SubField a) = a
 
-instance (EntityConstr v c, PersistField a) => FieldLike (Field v c a) db (RestrictionHolder v c) a where
+instance (EntityConstr v c, PersistField a) => FieldLike (Field v c a) a where
   fieldChain = entityFieldChain
 
-instance (PersistEntity v, IsUniqueKey k, k ~ Key v (Unique u), r ~ RestrictionHolder v c)
-      => FieldLike (u (UniqueMarker v)) db r k where
+instance (PersistEntity v, IsUniqueKey k, k ~ Key v (Unique u))
+      => FieldLike (u (UniqueMarker v)) k where
   fieldChain u = chain where
     UniqueDef _ _ uFields = constrUniques constr !! uniqueNum ((undefined :: u (UniqueMarker v) -> Key v (Unique u)) u)
     chain = (("will_be_ignored", DbEmbedded (EmbeddedDef True uFields) Nothing), [])
diff --git a/changelog b/changelog
--- a/changelog
+++ b/changelog
@@ -1,6 +1,11 @@
+0.5.0
+* Reimplemented projections with constraint kinds
+* Moved QueryRaw constraint into class SqlDb simplifying SQL function signatures
+* Compatibility with GHC 7.8
+
 0.4.2.2
 * Create missing schemas (or databases in MySQL terminology) during migration
-* Replace datatype Proxy with type variable
+* Replaced datatype Proxy with type variable
 
 0.4.2
 * Cond can be used as expression
diff --git a/groundhog.cabal b/groundhog.cabal
--- a/groundhog.cabal
+++ b/groundhog.cabal
@@ -1,5 +1,5 @@
 name:            groundhog
-version:         0.4.2.2
+version:         0.5.0
 license:         BSD3
 license-file:    LICENSE
 author:          Boris Lykah <lykahb@gmail.com>
