diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,11 @@
 # Changelog for persistent
 
+## 2.12.1.0
+
+*  [#1226](https://github.com/yesodweb/persistent/pull/1226)
+    * Expose the `filterClause` and `filterClauseWithValues` functions to support
+      the `upsertWhere` functionality in `persistent-postgresql`.
+
 ## 2.12.0.2
 
 * [#1123](https://github.com/yesodweb/persistent/pull/1223)
@@ -22,10 +28,10 @@
   * Added `makeCompatibleInstances` and `makeCompatibleKeyInstances`, TemplateHaskell invocations for auto-generating standalone derivations using `Compatible` and `DerivingVia`.
 * [#1207](https://github.com/yesodweb/persistent/pull/1207)
     * @codygman discovered a bug in [issue #1199](https://github.com/yesodweb/persistent/issues/1199) where postgres connections were being returned to the `Pool SqlBackend` in an inconsistent state.
-      @parsonsmatt debugged the issue and determined that it had something to do with asynchronous exceptions. 
+      @parsonsmatt debugged the issue and determined that it had something to do with asynchronous exceptions.
       Declaring it to be "out of his pay grade," he ripped the `poolToAcquire` function out and replaced it with `Data.Pool.withResource`, which doesn't exhibit the bug.
       Fortunately, this doesn't affect the public API, and can be a mere bug release.
-    * Removed the functions `unsafeAcquireSqlConnFromPool`, `acquireASqlConnFromPool`, and `acquireSqlConnFromPoolWithIsolation`. 
+    * Removed the functions `unsafeAcquireSqlConnFromPool`, `acquireASqlConnFromPool`, and `acquireSqlConnFromPoolWithIsolation`.
       For a replacement, see `runSqlPoolNoTransaction` and `runSqlPoolWithHooks`.
 * Renaming values in persistent-template [#1203](https://github.com/yesodweb/persistent/pull/1203)
 * [#1214](https://github.com/yesodweb/persistent/pull/1214):
diff --git a/Database/Persist/Sql.hs b/Database/Persist/Sql.hs
--- a/Database/Persist/Sql.hs
+++ b/Database/Persist/Sql.hs
@@ -12,6 +12,9 @@
     , rawSql
     , deleteWhereCount
     , updateWhereCount
+    , filterClause
+    , filterClauseWithVals
+    , FilterTablePrefix (..)
     , transactionSave
     , transactionSaveWithIsolation
     , transactionUndo
@@ -27,13 +30,13 @@
 import Control.Monad.Trans.Reader (ReaderT, ask)
 
 import Database.Persist
-import Database.Persist.Sql.Types
-import Database.Persist.Sql.Types.Internal (IsolationLevel (..))
 import Database.Persist.Sql.Class
-import Database.Persist.Sql.Run hiding (rawAcquireSqlConn, rawRunSqlPool)
-import Database.Persist.Sql.Raw
-import Database.Persist.Sql.Migration
 import Database.Persist.Sql.Internal
+import Database.Persist.Sql.Migration
+import Database.Persist.Sql.Raw
+import Database.Persist.Sql.Run hiding (rawAcquireSqlConn, rawRunSqlPool)
+import Database.Persist.Sql.Types
+import Database.Persist.Sql.Types.Internal (IsolationLevel(..))
 
 import Database.Persist.Sql.Orphan.PersistQuery
 import Database.Persist.Sql.Orphan.PersistStore
diff --git a/Database/Persist/Sql/Orphan/PersistQuery.hs b/Database/Persist/Sql/Orphan/PersistQuery.hs
--- a/Database/Persist/Sql/Orphan/PersistQuery.hs
+++ b/Database/Persist/Sql/Orphan/PersistQuery.hs
@@ -6,6 +6,10 @@
 module Database.Persist.Sql.Orphan.PersistQuery
     ( deleteWhereCount
     , updateWhereCount
+    , filterClause
+    , filterClauseHelper
+    , filterClauseWithVals
+    , FilterTablePrefix (..)
     , decorateSQLWithLimitOffset
     ) where
 
@@ -36,7 +40,7 @@
         conn <- ask
         let wher = if null filts
                     then ""
-                    else filterClause False conn filts
+                    else filterClause Nothing conn filts
         let sql = mconcat
                 [ "SELECT COUNT(*) FROM "
                 , connEscapeTableName conn t
@@ -59,7 +63,7 @@
         conn <- ask
         let wher = if null filts
                     then ""
-                    else filterClause False conn filts
+                    else filterClause Nothing conn filts
         let sql = mconcat
                 [ "SELECT EXISTS(SELECT 1 FROM "
                 , connEscapeTableName conn t
@@ -93,7 +97,7 @@
         t = entityDef $ dummyFromFilts filts
         wher conn = if null filts
                     then ""
-                    else filterClause False conn filts
+                    else filterClause Nothing conn filts
         ord conn =
             case map (orderClause False conn) orders of
                 [] -> ""
@@ -119,7 +123,7 @@
 
         wher conn = if null filts
                     then ""
-                    else filterClause False conn filts
+                    else filterClause Nothing conn filts
         sql conn = connLimitOffset conn (limit,offset) (not (null orders)) $ mconcat
             [ "SELECT "
             , cols conn
@@ -183,7 +187,7 @@
     let t = entityDef $ dummyFromFilts filts
     let wher = if null filts
                 then ""
-                else filterClause False conn filts
+                else filterClause Nothing conn filts
         sql = mconcat
             [ "DELETE FROM "
             , connEscapeTableName conn t
@@ -203,7 +207,7 @@
     conn <- ask
     let wher = if null filts
                 then ""
-                else filterClause False conn filts
+                else filterClause Nothing conn filts
     let sql = mconcat
             [ "UPDATE "
             , connEscapeTableName conn t
@@ -217,26 +221,42 @@
   where
     t = entityDef $ dummyFromFilts filts
 
-fieldName ::  forall record typ. (PersistEntity record, PersistEntityBackend record ~ SqlBackend) => EntityField record typ -> FieldNameDB
+fieldName ::  forall record typ. (PersistEntity record) => EntityField record typ -> FieldNameDB
 fieldName f = fieldDB $ persistFieldDef f
 
 dummyFromFilts :: [Filter v] -> Maybe v
 dummyFromFilts _ = Nothing
 
-getFiltsValues :: forall val. (PersistEntity val, PersistEntityBackend val ~ SqlBackend)
+getFiltsValues :: forall val. (PersistEntity val)
                => SqlBackend -> [Filter val] -> [PersistValue]
-getFiltsValues conn = snd . filterClauseHelper False False conn OrNullNo
+getFiltsValues conn = snd . filterClauseHelper Nothing False conn OrNullNo
 
 data OrNull = OrNullYes | OrNullNo
 
-filterClauseHelper :: (PersistEntity val, PersistEntityBackend val ~ SqlBackend)
-             => Bool -- ^ include table name?
-             -> Bool -- ^ include WHERE?
+-- | Used when determining how to prefix a column name in a @WHERE@ clause.
+--
+-- @since 2.12.1.0
+data FilterTablePrefix
+    = PrefixTableName
+    -- ^ Prefix the column with the table name. This is useful if the column
+    -- name might be ambiguous.
+    --
+    -- @since 2.12.1.0
+    | PrefixExcluded
+    -- ^ Prefix the column name with the @EXCLUDED@ keyword. This is used with
+    -- the Postgresql backend when doing @ON CONFLICT DO UPDATE@ clauses - see
+    -- the documentation on @upsertWhere@ and @upsertManyWhere@.
+    --
+    -- @since 2.12.1.0
+
+filterClauseHelper :: (PersistEntity val)
+             => Maybe FilterTablePrefix -- ^ include table name or PostgresSQL EXCLUDED
+             -> Bool -- ^ include WHERE
              -> SqlBackend
              -> OrNull
              -> [Filter val]
              -> (Text, [PersistValue])
-filterClauseHelper includeTable includeWhere conn orNull filters =
+filterClauseHelper tablePrefix includeWhere conn orNull filters =
     (if not (T.null sql) && includeWhere
         then " WHERE " <> sql
         else sql, vals)
@@ -356,7 +376,9 @@
 
         orNullSuffix =
             case orNull of
-                OrNullYes -> mconcat [" OR ", name, " IS NULL"]
+                OrNullYes -> mconcat [" OR "
+                                      , name
+                                      , " IS NULL"]
                 OrNullNo -> ""
 
         isNull = PersistNull `elem` allVals
@@ -364,10 +386,10 @@
         allVals = filterValueToPersistValues value
         tn = connEscapeTableName conn $ entityDef $ dummyFromFilts [Filter field value pfilter]
         name =
-            (if includeTable
-                then ((tn <> ".") <>)
-                else id)
-            $ connEscapeFieldName conn (fieldName field)
+          case tablePrefix of
+            Just PrefixTableName -> ((tn <> ".") <>) $ connEscapeFieldName conn (fieldName field)
+            Just PrefixExcluded -> (("EXCLUDED.") <>) $ connEscapeFieldName conn (fieldName field)
+            _ -> id $ connEscapeFieldName conn (fieldName field)
         qmarks = case value of
                     FilterValue{} -> "(?)"
                     UnsafeValue{} -> "(?)"
@@ -387,14 +409,30 @@
         showSqlFilter NotIn = " NOT IN "
         showSqlFilter (BackendSpecificFilter s) = s
 
-filterClause :: (PersistEntity val, PersistEntityBackend val ~ SqlBackend)
-             => Bool -- ^ include table name?
+-- |  Render a @['Filter' record]@ into a 'Text' value suitable for inclusion
+-- into a SQL query.
+--
+-- @since 2.12.1.0
+filterClause :: (PersistEntity val)
+             => Maybe FilterTablePrefix -- ^ include table name or EXCLUDED
              -> SqlBackend
              -> [Filter val]
              -> Text
 filterClause b c = fst . filterClauseHelper b True c OrNullNo
 
-orderClause :: (PersistEntity val, PersistEntityBackend val ~ SqlBackend)
+-- |  Render a @['Filter' record]@ into a 'Text' value suitable for inclusion
+-- into a SQL query, as well as the @['PersistValue']@ to properly fill in the
+-- @?@ place holders.
+--
+-- @since 2.12.1.0
+filterClauseWithVals :: (PersistEntity val)
+             => Maybe FilterTablePrefix -- ^ include table name or EXCLUDED
+             -> SqlBackend
+             -> [Filter val]
+             -> (Text, [PersistValue])
+filterClauseWithVals b c  = filterClauseHelper b True c OrNullNo
+
+orderClause :: (PersistEntity val)
             => Bool -- ^ include the table name
             -> SqlBackend
             -> SelectOpt val
@@ -410,7 +448,7 @@
 
     tn = connEscapeTableName conn (entityDef $ dummyFromOrder o)
 
-    name :: (PersistEntityBackend record ~ SqlBackend, PersistEntity record)
+    name :: (PersistEntity record)
          => EntityField record typ -> Text
     name x =
         (if includeTable
diff --git a/Database/Persist/Sql/Util.hs b/Database/Persist/Sql/Util.hs
--- a/Database/Persist/Sql/Util.hs
+++ b/Database/Persist/Sql/Util.hs
@@ -207,6 +207,7 @@
 mkUpdateText :: PersistEntity record => SqlBackend -> Update record -> Text
 mkUpdateText conn = mkUpdateText' (connEscapeFieldName conn) id
 
+-- TODO: incorporate the table names into a sum type
 mkUpdateText' :: PersistEntity record => (FieldNameDB -> Text) -> (Text -> Text) -> Update record -> Text
 mkUpdateText' escapeName refColumn x =
   case updateUpdate x of
@@ -223,7 +224,7 @@
 parenWrapped :: Text -> Text
 parenWrapped t = T.concat ["(", t, ")"]
 
--- | Make a list 'PersistValue' suitable for detabase inserts. Pairs nicely
+-- | Make a list 'PersistValue' suitable for database inserts. Pairs nicely
 -- with the function 'mkInsertPlaceholders'.
 --
 -- Does not include generated columns.
diff --git a/persistent.cabal b/persistent.cabal
--- a/persistent.cabal
+++ b/persistent.cabal
@@ -1,5 +1,5 @@
 name:            persistent
-version:         2.12.0.2
+version:         2.12.1.0
 license:         MIT
 license-file:    LICENSE
 author:          Michael Snoyman <michael@snoyman.com>
