From 57cecef6abf7e9f7162696ec3b8847809a85e9b9 Mon Sep 17 00:00:00 2001
From: Peter Geoghegan <pg@heroku.com>
Date: Fri, 26 Sep 2014 20:59:04 -0700
Subject: [PATCH 8/8] User-visible documentation for INSERT ... ON CONFLICT
 {UPDATE | IGNORE}

INSERT ... ON CONFLICT {UPDATE | IGNORE} is documented as a new clause
of the INSERT command.  Some potentially surprising interactions with
triggers are noted -- BEFORE INSERT per-row triggers must fire without
the INSERT path necessarily being taken, for example.

All the existing features that INSERT ... ON CONFLICT {UPDATE | IGNORE}
interacts with have these interactions noted.  This includes
postgres_fdw, updatable views, table inheritance, RLS and partial unique
indexes.

Finally, a user-level description of the new "MVCC violation" that the
ON CONFLICT UPDATE variant sometimes requires has been added to "Chapter
13 - Concurrency Control", beside existing commentary on READ COMMITTED
mode's special handling of concurrent updates.  The new "MVCC violation"
introduced seems somewhat distinct from the existing one (i.e.  READ
COMMITTED's handling of when an UPDATE affects a concurrently
updated/deleted tuple, which internally uses a mechanism called
EvalPlanQual()), because in READ COMMITTED mode it is no longer
necessary for any row version to be conventionally visible to the
command's MVCC snapshot for an UPDATE of the row to occur (or for the
row to be locked, should the UPDATE's WHERE clause not be satisfied).
---
 doc/src/sgml/ddl.sgml                 |  23 +++
 doc/src/sgml/fdwhandler.sgml          |   8 +
 doc/src/sgml/keywords.sgml            |   7 +
 doc/src/sgml/mvcc.sgml                |  24 +++
 doc/src/sgml/plpgsql.sgml             |  14 +-
 doc/src/sgml/postgres-fdw.sgml        |   8 +
 doc/src/sgml/protocol.sgml            |  13 +-
 doc/src/sgml/ref/alter_policy.sgml    |   7 +-
 doc/src/sgml/ref/create_policy.sgml   |  50 +++--
 doc/src/sgml/ref/create_rule.sgml     |   6 +-
 doc/src/sgml/ref/create_table.sgml    |   5 +-
 doc/src/sgml/ref/create_trigger.sgml  |   5 +-
 doc/src/sgml/ref/create_view.sgml     |  33 ++-
 doc/src/sgml/ref/insert.sgml          | 373 ++++++++++++++++++++++++++++++++--
 doc/src/sgml/ref/set_constraints.sgml |   6 +-
 doc/src/sgml/trigger.sgml             |  49 ++++-
 16 files changed, 573 insertions(+), 58 deletions(-)

diff --git a/doc/src/sgml/ddl.sgml b/doc/src/sgml/ddl.sgml
index 570a003..7b43a10 100644
--- a/doc/src/sgml/ddl.sgml
+++ b/doc/src/sgml/ddl.sgml
@@ -2428,9 +2428,27 @@ VALUES ('Albany', NULL, NULL, 'NY');
   </para>
 
   <para>
+   There is limited inheritance support for <command>INSERT</command>
+   commands with <literal>ON CONFLICT</> clauses.  Tables with
+   children are not generally accepted as targets.  One notable
+   exception is that such tables are accepted as targets for
+   <command>INSERT</command> commands with <literal>ON CONFLICT
+   IGNORE</> clauses, provided a unique index inference clause was
+   omitted (which implies that there is no concern about
+   <emphasis>which</> unique index any would-be conflict might arise
+   from).  However, tables that happen to be inheritance children are
+   accepted as targets for all variants of <command>INSERT</command>
+   with <literal>ON CONFLICT</>.
+  </para>
+
+  <para>
    All check constraints and not-null constraints on a parent table are
    automatically inherited by its children.  Other types of constraints
    (unique, primary key, and foreign key constraints) are not inherited.
+   Therefore, <command>INSERT</command> with <literal>ON CONFLICT</>
+   unique index inference considers only unique constraints/indexes
+   directly associated with the child
+   table.
   </para>
 
   <para>
@@ -2515,6 +2533,11 @@ VALUES ('Albany', NULL, NULL, 'NY');
    not <literal>INSERT</literal> or <literal>ALTER TABLE ...
    RENAME</literal>) typically default to including child tables and
    support the <literal>ONLY</literal> notation to exclude them.
+   <literal>INSERT</literal> with an <literal>ON CONFLICT
+   UPDATE</literal> clause does not support the
+   <literal>ONLY</literal> notation, and so in effect tables with
+   inheritance children are not supported for the <literal>ON
+   CONFLICT</literal> variant.
    Commands that do database maintenance and tuning
    (e.g., <literal>REINDEX</literal>, <literal>VACUUM</literal>)
    typically only work on individual, physical tables and do not
diff --git a/doc/src/sgml/fdwhandler.sgml b/doc/src/sgml/fdwhandler.sgml
index c1daa4b..0c3dcb5 100644
--- a/doc/src/sgml/fdwhandler.sgml
+++ b/doc/src/sgml/fdwhandler.sgml
@@ -1014,6 +1014,14 @@ GetForeignServerByName(const char *name, bool missing_ok);
      source provides.
     </para>
 
+    <para>
+     <command>INSERT</> with an <literal>ON CONFLICT</> clause is not supported
+     with a unique index inference specification (this implies that <literal>ON
+     CONFLICT UPDATE</> is never supported, since the specification is
+     mandatory there).  When planning an <command>INSERT</>,
+     <function>PlanForeignModify</> should reject these cases.
+    </para>
+
   </sect1>
 
  </chapter>
diff --git a/doc/src/sgml/keywords.sgml b/doc/src/sgml/keywords.sgml
index b0dfd5f..ea58211 100644
--- a/doc/src/sgml/keywords.sgml
+++ b/doc/src/sgml/keywords.sgml
@@ -854,6 +854,13 @@
     <entry></entry>
    </row>
    <row>
+    <entry><token>CONFLICT</token></entry>
+    <entry>non-reserved</entry>
+    <entry></entry>
+    <entry></entry>
+    <entry></entry>
+   </row>
+   <row>
     <entry><token>CONNECT</token></entry>
     <entry></entry>
     <entry>reserved</entry>
diff --git a/doc/src/sgml/mvcc.sgml b/doc/src/sgml/mvcc.sgml
index a0d6867..5e310d7 100644
--- a/doc/src/sgml/mvcc.sgml
+++ b/doc/src/sgml/mvcc.sgml
@@ -326,6 +326,30 @@
    </para>
 
    <para>
+    <command>INSERT</command> with an <literal>ON CONFLICT UPDATE</> clause is
+    another special case.  In Read Committed mode, the implementation will
+    either insert or update each row proposed for insertion, with either one of
+    those two outcomes guaranteed.  This is a useful guarantee for many
+    use-cases, but it implies that further liberties must be taken with
+    snapshot isolation.  Should a conflict originate in another transaction
+    whose effects are not visible to the <command>INSERT</command>, the
+    <command>UPDATE</command> may affect that row, even though it may be the
+    case that <emphasis>no</> version of that row is conventionally visible to
+    the command.  In the same vein, if the secondary search condition of the
+    command (an explicit <literal>WHERE</> clause) is supplied, it is only
+    evaluated on the most recent row version, which is not necessarily the
+    version conventionally visible to the command (if indeed there is a row
+    version conventionally visible to the command at all).
+   </para>
+
+   <para>
+    <command>INSERT</command> with an <literal>ON CONFLICT IGNORE</> clause may
+    have insertion not proceed for a row due to the outcome of another
+    transaction whose effects are not visible to the <command>INSERT</command>
+    snapshot.  Again, this is only the case in Read Committed mode.
+   </para>
+
+   <para>
     Because of the above rule, it is possible for an updating command to see an
     inconsistent snapshot: it can see the effects of concurrent updating
     commands on the same rows it is trying to update, but it
diff --git a/doc/src/sgml/plpgsql.sgml b/doc/src/sgml/plpgsql.sgml
index 69a0885..59a5945 100644
--- a/doc/src/sgml/plpgsql.sgml
+++ b/doc/src/sgml/plpgsql.sgml
@@ -2607,7 +2607,11 @@ END;
     <para>
 
     This example uses exception handling to perform either
-    <command>UPDATE</> or <command>INSERT</>, as appropriate:
+    <command>UPDATE</> or <command>INSERT</>, as appropriate.  It is
+    recommended that applications use <command>INSERT</> with
+    <literal>ON CONFLICT UPDATE</> rather than actually emulating this
+    pattern.  This example serves only to illustrate use of
+    <application>PL/pgSQL</application> control flow structures:
 
 <programlisting>
 CREATE TABLE db (a INT PRIMARY KEY, b TEXT);
@@ -3771,9 +3775,11 @@ RAISE unique_violation USING MESSAGE = 'Duplicate user ID: ' || user_id;
     <command>INSERT</> and <command>UPDATE</> operations, the return value
     should be <varname>NEW</>, which the trigger function may modify to
     support <command>INSERT RETURNING</> and <command>UPDATE RETURNING</>
-    (this will also affect the row value passed to any subsequent triggers).
-    For <command>DELETE</> operations, the return value should be
-    <varname>OLD</>.
+    (this will also affect the row value passed to any subsequent triggers,
+    or passed to a special <varname>EXCLUDED</> alias reference within
+    an <command>INSERT</> statement with an <literal>ON CONFLICT UPDATE</>
+    clause).  For <command>DELETE</> operations, the return
+    value should be <varname>OLD</>.
    </para>
 
    <para>
diff --git a/doc/src/sgml/postgres-fdw.sgml b/doc/src/sgml/postgres-fdw.sgml
index 43adb61..fa39661 100644
--- a/doc/src/sgml/postgres-fdw.sgml
+++ b/doc/src/sgml/postgres-fdw.sgml
@@ -69,6 +69,14 @@
  </para>
 
  <para>
+  Note that <filename>postgres_fdw</> currently lacks support for
+  <command>INSERT</command> statements with an <literal>ON CONFLICT
+  UPDATE</> clause.  However, the <literal>ON CONFLICT IGNORE</>
+  clause is supported, provided a unique index inference specification
+  is omitted.
+ </para>
+
+ <para>
   It is generally recommended that the columns of a foreign table be declared
   with exactly the same data types, and collations if applicable, as the
   referenced columns of the remote table.  Although <filename>postgres_fdw</>
diff --git a/doc/src/sgml/protocol.sgml b/doc/src/sgml/protocol.sgml
index efe75ea..a198182 100644
--- a/doc/src/sgml/protocol.sgml
+++ b/doc/src/sgml/protocol.sgml
@@ -2998,9 +2998,16 @@ CommandComplete (B)
         <literal>INSERT <replaceable>oid</replaceable>
         <replaceable>rows</replaceable></literal>, where
         <replaceable>rows</replaceable> is the number of rows
-        inserted. <replaceable>oid</replaceable> is the object ID
-        of the inserted row if <replaceable>rows</replaceable> is 1
-        and the target table has OIDs;
+        inserted. However, if and only if <literal>ON CONFLICT
+        UPDATE</> is specified, then the tag is <literal>UPSERT
+        <replaceable>oid</replaceable>
+        <replaceable>rows</replaceable></literal>, where
+        <replaceable>rows</replaceable> is the number of rows inserted
+        <emphasis>or updated</emphasis>.
+        <replaceable>oid</replaceable> is the object ID of the
+        inserted row if <replaceable>rows</replaceable> is 1 and the
+        target table has OIDs, and (for the <literal>UPSERT</literal>
+        tag), the row was actually inserted rather than updated;
         otherwise <replaceable>oid</replaceable> is 0.
        </para>
 
diff --git a/doc/src/sgml/ref/alter_policy.sgml b/doc/src/sgml/ref/alter_policy.sgml
index 796035e..86bda92 100644
--- a/doc/src/sgml/ref/alter_policy.sgml
+++ b/doc/src/sgml/ref/alter_policy.sgml
@@ -93,8 +93,11 @@ ALTER POLICY <replaceable class="parameter">name</replaceable> ON <replaceable c
       The USING expression for the policy.  This expression will be added as a
       security-barrier qualification to queries which use the table
       automatically.  If multiple policies are being applied for a given
-      table then they are all combined and added using OR.  The USING
-      expression applies to records which are being retrieved from the table.
+      table then they are all combined and added using OR (except as noted in
+      the <xref linkend="sql-createpolicy"> documentation for
+      <command>INSERT</command> with <literal> ON CONFLICT UPDATE</literal>).
+      The USING expression applies to records which are being retrieved from the
+      table.
      </para>
     </listitem>
    </varlistentry>
diff --git a/doc/src/sgml/ref/create_policy.sgml b/doc/src/sgml/ref/create_policy.sgml
index 8ef8556..fcfcb02 100644
--- a/doc/src/sgml/ref/create_policy.sgml
+++ b/doc/src/sgml/ref/create_policy.sgml
@@ -63,7 +63,8 @@ CREATE POLICY <replaceable class="parameter">name</replaceable> ON <replaceable
    Policies can be applied for specific commands or for specific roles.  The
    default for newly created policies is that they apply for all commands and
    roles, unless otherwise specified.  If multiple policies apply to a given
-   query, they will be combined using OR.
+   query, they will be combined using OR (except as noted for
+   <command>INSERT</command> with <literal> ON CONFLICT UPDATE</literal>).
   </para>
 
   <para>
@@ -237,6 +238,19 @@ CREATE POLICY <replaceable class="parameter">name</replaceable> ON <replaceable
          as it only ever applies in cases where records are being added to the
          relation.
        </para>
+       <para>
+         Note that <literal>INSERT</literal> with <literal>ON CONFLICT
+         UPDATE</literal> requires that an <literal>INSERT</literal> policy WITH
+         CHECK expression also passes for both any existing tuple in the target
+         table that necessitates that the <literal>UPDATE</literal> path be
+         taken, and the final tuple added back into the relation.
+         <literal>INSERT</literal> policies are separately combined using
+         <literal>OR</literal>, and this distinct set of policy expressions must
+         always pass, regardless of whether any or all <literal>UPDATE</literal>
+         policies also pass (in the same tuple check).  However, successfully
+         inserted tuples are not subject to <literal>UPDATE</literal> policy
+         enforcement.
+       </para>
       </listitem>
      </varlistentry>
 
@@ -245,18 +259,28 @@ CREATE POLICY <replaceable class="parameter">name</replaceable> ON <replaceable
       <listitem>
        <para>
          Using <literal>UPDATE</literal> for a policy means that it will apply
-         to <literal>UPDATE</literal> commands.  As <literal>UPDATE</literal>
-         involves pulling an existing record and then making changes to some
-         portion (but possibly not all) of the record, the
-         <literal>UPDATE</literal> policy accepts both a USING expression and
-         a WITH CHECK expression.  The USING expression will be used to
-         determine which records the <literal>UPDATE</literal> command will
-         see to operate against, while the <literal>WITH CHECK</literal>
-         expression defines what rows are allowed to be added back into the
-         relation (similar to the <literal>INSERT</literal> policy).
-         Any rows whose resulting values do not pass the
-         <literal>WITH CHECK</literal> expression will cause an ERROR and the
-         entire command will be aborted.
+         to <literal>UPDATE</literal> commands (or auxiliary <literal>ON
+         CONFLICT UPDATE</literal> clauses of <literal>INSERT</literal>
+         commands).  As <literal>UPDATE</literal> involves pulling an existing
+         record and then making changes to some portion (but possibly not all)
+         of the record, the <literal>UPDATE</literal> policy accepts both a
+         USING expression and a WITH CHECK expression.  The USING expression
+         will be used to determine which records the <literal>UPDATE</literal>
+         command will see to operate against, while the <literal>WITH
+         CHECK</literal> expression defines what rows are allowed to be added
+         back into the relation (similar to the <literal>INSERT</literal>
+         policy).  Any rows whose resulting values do not pass the <literal>WITH
+         CHECK</literal> expression will cause an ERROR and the entire command
+         will be aborted.
+       </para>
+       <para>
+         Note that <literal>INSERT</literal> with <literal>ON CONFLICT
+         UPDATE</literal> requires that an <literal>UPDATE</literal> policy
+         USING expression always be treated as a WITH CHECK
+         expression.  This <literal>UPDATE</literal> policy must
+         always pass, regardless of whether any
+         <literal>INSERT</literal> policy also passes in the same
+         tuple check.
        </para>
       </listitem>
      </varlistentry>
diff --git a/doc/src/sgml/ref/create_rule.sgml b/doc/src/sgml/ref/create_rule.sgml
index 677766a..9b5c740 100644
--- a/doc/src/sgml/ref/create_rule.sgml
+++ b/doc/src/sgml/ref/create_rule.sgml
@@ -136,7 +136,11 @@ CREATE [ OR REPLACE ] RULE <replaceable class="parameter">name</replaceable> AS
      <para>
       The event is one of <literal>SELECT</literal>,
       <literal>INSERT</literal>, <literal>UPDATE</literal>, or
-      <literal>DELETE</literal>.
+      <literal>DELETE</literal>.  Note that an
+      <command>INSERT</command> containing an <literal>ON
+      CONFLICT</literal> clause is unsupported.  Consider using an
+      updatable view instead, which have limited support for
+      <literal>ON CONFLICT IGNORE</literal> only.
      </para>
     </listitem>
    </varlistentry>
diff --git a/doc/src/sgml/ref/create_table.sgml b/doc/src/sgml/ref/create_table.sgml
index 299cce8..a9c1124 100644
--- a/doc/src/sgml/ref/create_table.sgml
+++ b/doc/src/sgml/ref/create_table.sgml
@@ -708,7 +708,10 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXI
       <literal>EXCLUDE</>, and
       <literal>REFERENCES</> (foreign key) constraints accept this
       clause.  <literal>NOT NULL</> and <literal>CHECK</> constraints are not
-      deferrable.
+      deferrable.  Note that constraints that were created with this
+      clause cannot be used as arbiters of whether or not to take the
+      alternative path with an <command>INSERT</command> statement
+      that includes an <literal>ON CONFLICT UPDATE</> clause.
      </para>
     </listitem>
    </varlistentry>
diff --git a/doc/src/sgml/ref/create_trigger.sgml b/doc/src/sgml/ref/create_trigger.sgml
index 29b815c..26a0986 100644
--- a/doc/src/sgml/ref/create_trigger.sgml
+++ b/doc/src/sgml/ref/create_trigger.sgml
@@ -76,7 +76,10 @@ CREATE [ CONSTRAINT ] TRIGGER <replaceable class="PARAMETER">name</replaceable>
    executes once for any given operation, regardless of how many rows
    it modifies (in particular, an operation that modifies zero rows
    will still result in the execution of any applicable <literal>FOR
-   EACH STATEMENT</literal> triggers).
+   EACH STATEMENT</literal> triggers).  Note that since
+   <command>INSERT</command> with an <literal>ON CONFLICT UPDATE</>
+   clause is considered an <command>INSERT</command> statement, no
+   <command>UPDATE</command> statement level trigger will be fired.
   </para>
 
   <para>
diff --git a/doc/src/sgml/ref/create_view.sgml b/doc/src/sgml/ref/create_view.sgml
index 5dadab1..599c1cb 100644
--- a/doc/src/sgml/ref/create_view.sgml
+++ b/doc/src/sgml/ref/create_view.sgml
@@ -286,8 +286,9 @@ CREATE VIEW vista AS SELECT text 'Hello World' AS hello;
    <para>
     Simple views are automatically updatable: the system will allow
     <command>INSERT</>, <command>UPDATE</> and <command>DELETE</> statements
-    to be used on the view in the same way as on a regular table.  A view is
-    automatically updatable if it satisfies all of the following conditions:
+    to be used on the view in the same way as on a regular table (aside from
+    the limitations on ON CONFLICT noted below).  A view is automatically
+    updatable if it satisfies all of the following conditions:
 
     <itemizedlist>
      <listitem>
@@ -383,6 +384,34 @@ CREATE VIEW vista AS SELECT text 'Hello World' AS hello;
     not need any permissions on the underlying base relations (see
     <xref linkend="rules-privileges">).
    </para>
+   <para>
+    <command>INSERT</command> with an <literal>ON CONFLICT</> clause
+    is only supported on updatable views under specific circumstances.
+    If a set of columns/expressions has been provided with which to
+    infer a unique index to consider as the arbiter of whether the
+    statement ultimately takes an alternative path - if a would-be
+    duplicate violation in some particular unique index is tacitly
+    taken as provoking an alternative <command>UPDATE</command> or
+    <literal>IGNORE</> path - then updatable views are not supported.
+    Since this specification is already mandatory for
+    <command>INSERT</command> with <literal>ON CONFLICT UPDATE</>,
+    this implies that only the <literal>ON CONFLICT IGNORE</> variant
+    is supported, and only when there is no such specification.  For
+    example:
+   </para>
+   <para>
+<programlisting>
+-- Unsupported:
+INSERT INTO my_updatable_view(key, val) VALUES(1, 'foo') ON CONFLICT (key)
+  UPDATE SET val = EXCLUDED.val;
+INSERT INTO my_updatable_view(key, val) VALUES(1, 'bar') ON CONFLICT (key)
+  IGNORE;
+
+-- Supported (note the omission of "key" column):
+INSERT INTO my_updatable_view(key, val) VALUES(1, 'baz') ON CONFLICT
+  IGNORE;
+</programlisting>
+   </para>
   </refsect2>
  </refsect1>
 
diff --git a/doc/src/sgml/ref/insert.sgml b/doc/src/sgml/ref/insert.sgml
index a3cccb9..40b7566 100644
--- a/doc/src/sgml/ref/insert.sgml
+++ b/doc/src/sgml/ref/insert.sgml
@@ -24,6 +24,14 @@ PostgreSQL documentation
 [ WITH [ RECURSIVE ] <replaceable class="parameter">with_query</replaceable> [, ...] ]
 INSERT INTO <replaceable class="PARAMETER">table_name</replaceable> [ ( <replaceable class="PARAMETER">column_name</replaceable> [, ...] ) ]
     { DEFAULT VALUES | VALUES ( { <replaceable class="PARAMETER">expression</replaceable> | DEFAULT } [, ...] ) [, ...] | <replaceable class="PARAMETER">query</replaceable> }
+    [ ON CONFLICT [ ( { <replaceable class="parameter">column_name_index</replaceable> | ( <replaceable class="parameter">expression_index</replaceable> ) } [, ...] [ WHERE <replaceable class="PARAMETER">index_condition</replaceable> ] ) ]
+      { IGNORE | UPDATE
+        SET { <replaceable class="PARAMETER">column_name</replaceable> = { <replaceable class="PARAMETER">expression</replaceable> | DEFAULT } |
+              ( <replaceable class="PARAMETER">column_name</replaceable> [, ...] ) = ( { <replaceable class="PARAMETER">expression</replaceable> | DEFAULT } [, ...] )
+            } [, ...]
+        [ WHERE <replaceable class="PARAMETER">condition</replaceable> ]
+      }
+    ]
     [ RETURNING * | <replaceable class="parameter">output_expression</replaceable> [ [ AS ] <replaceable class="parameter">output_name</replaceable> ] [, ...] ]
 </synopsis>
  </refsynopsisdiv>
@@ -32,9 +40,15 @@ INSERT INTO <replaceable class="PARAMETER">table_name</replaceable> [ ( <replace
   <title>Description</title>
 
   <para>
-   <command>INSERT</command> inserts new rows into a table.
-   One can insert one or more rows specified by value expressions,
-   or zero or more rows resulting from a query.
+   <command>INSERT</command> inserts new rows into a table.  One can
+   insert one or more rows specified by value expressions, or zero or
+   more rows resulting from a query.  An alternative path
+   (<literal>IGNORE</literal> or <literal>UPDATE</literal>) can
+   optionally be specified, to be taken in the event of detecting that
+   proceeding with insertion would result in a conflict (i.e. a
+   conflicting tuple already exists).  The alternative path is
+   considered individually for each row proposed for insertion, and is
+   taken (or not taken) once per row.
   </para>
 
   <para>
@@ -59,25 +73,214 @@ INSERT INTO <replaceable class="PARAMETER">table_name</replaceable> [ ( <replace
   </para>
 
   <para>
+   The optional <literal>ON CONFLICT</> clause specifies a path to
+   take as an alternative to raising a conflict related error.
+   <literal>ON CONFLICT IGNORE</> simply avoids inserting any
+   individual row when it is determined that a conflict related error
+   would otherwise need to be raised.  <literal>ON CONFLICT UPDATE</>
+   has the system take an <command>UPDATE</command> path in respect of
+   such rows instead.  <literal>ON CONFLICT UPDATE</> guarantees an
+   atomic <command>INSERT</command> or <command>UPDATE</command>
+   outcome - provided there is no incidental error, one of those two
+   outcomes is guaranteed, even under high concurrency.
+  </para>
+
+  <para>
+   <literal>ON CONFLICT UPDATE</> optionally accepts a
+   <literal>WHERE</> clause <replaceable>condition</>.  When provided,
+   the statement only proceeds with updating if the
+   <replaceable>condition</> is satisfied.  Otherwise, unlike a
+   conventional <command>UPDATE</command>, the row is still locked for
+   update.  Note that the <replaceable>condition</> is evaluated last,
+   after a conflict has been identified as a candidate to update.
+  </para>
+
+  <para>
+   <literal>ON CONFLICT UPDATE</> is effectively an auxiliary query of
+   its parent <command>INSERT</command>.  Two aliases are visible to
+   the auxiliary query only - <varname>TARGET</> and
+   <varname>EXCLUDED</>.  The first alias is just a standard alias for
+   the target relation in the context of the auxiliary query, while
+   the second alias refers to rows originally proposed for insertion.
+   Both aliases can be used in the auxiliary query targetlist and
+   <literal>WHERE</> clause.  This allows expressions (in particular,
+   assignments) to reference rows originally proposed for insertion.
+   Note that the effects of all per-row <literal>BEFORE INSERT</>
+   triggers are carried forward.  This is particularly useful for
+   multi-insert <literal>ON CONFLICT UPDATE</> statements;  when
+   inserting or updating multiple rows, constants or parameter values
+   need only appear once.
+  </para>
+
+  <para>
+   There are several restrictions on the <literal>ON CONFLICT
+   UPDATE</> clause that do not apply to <command>UPDATE</command>
+   statements.  Subqueries may not appear in either the
+   <command>UPDATE</command> targetlist, nor its <literal>WHERE</>
+   clause (although simple multi-assignment expressions are
+   supported).  <literal>WHERE CURRENT OF</> cannot be used.  In
+   general, only columns in the target table, and excluded values
+   originally proposed for insertion may be referenced.  Operators and
+   functions may be used freely, though.
+  </para>
+
+  <para>
+   <command>INSERT</command> with an <literal>ON CONFLICT UPDATE</>
+   clause is a <quote>deterministic</quote> statement.  This means
+   that the command will not be allowed to affect any single existing
+   row more than once; a cardinality violation error will be raised
+   when this situation arises.  Rows proposed for insertion should not
+   duplicate each other in terms of attributes constrained by the
+   conflict-arbitrating unique index.  Note that the ordinary rules
+   for unique indexes with regard to null apply analogously to whether
+   or not an arbitrating unique index indicates if the alternative
+   path should be taken.  This means that when a null value appears in
+   any uniquely constrained tuple's attribute in an
+   <command>INSERT</command> statement with <literal>ON CONFLICT
+   UPDATE</literal>, rows proposed for insertion will never take the
+   alternative path (provided that a <literal>BEFORE ROW
+   INSERT</literal> trigger does not make null values non-null before
+   insertion);  the statement will always insert, assuming there is no
+   unrelated error.  Note that merely locking a row (by having it not
+   satisfy the <literal>WHERE</> clause <replaceable>condition</>)
+   does not count towards whether or not the row has been affected
+   multiple times (and whether or not a cardinality violation error is
+   raised).  However, the implementation checks for cardinality
+   violations after locking the row, and before updating (or
+   considering updating), so a cardinality violation may be raised
+   despite the fact that the row would not otherwise have gone on to
+   be updated if and only if the existing row was updated by the
+   <literal>ON CONFLICT UPDATE</literal> command at least once
+   already.
+  </para>
+
+  <para>
+   <literal>ON CONFLICT UPDATE</> requires a <emphasis>unique index
+   inference</emphasis> specification, which consists of one or more
+   <replaceable class="PARAMETER">column_name_index</replaceable>
+   columns and/or <replaceable
+   class="PARAMETER">expression_index</replaceable> expressions on
+   columns, appearing between parenthesis.  These are used to infer a
+   single unique index to limit pre-checking for conflicts to (if no
+   appropriate index is available, an error is raised).  A subset of
+   the table to limit the check for conflicts to can optionally also
+   be specified using <replaceable
+   class="PARAMETER">index_condition</replaceable>.  Note that any
+   available unique index must only cover at least that subset in
+   order to be arbitrate taking the alternative path;  it need not
+   match exactly, and so a non-partial unique index that otherwise
+   matches is applicable.  <literal>ON CONFLICT IGNORE</> makes an
+   inference specification optional;  omitting the specification
+   indicates a total indifference to where any conflict could occur,
+   which isn't always appropriate.  At times, it may be desirable for
+   <literal>ON CONFLICT IGNORE</> to <emphasis>not</emphasis> suppress
+   a conflict related error associated with an index where that isn't
+   explicitly anticipated.  Note that <literal>ON CONFLICT UPDATE</>
+   assignment may result in a uniqueness violation, just as with a
+   conventional <command>UPDATE</command>.
+  </para>
+
+  <para>
+   Columns and/or expressions appearing in a unique index inference
+   specification must match all the columns/expressions of some
+   existing unique index on <replaceable
+   class="PARAMETER">table_name</replaceable> - there can be no
+   columns/expressions from the unique index that do not appear in the
+   inference specification, nor can there be any columns/expressions
+   appearing in the inference specification that do not appear in the
+   unique index definition.  However, the order of the
+   columns/expressions in the index definition, or whether or not the
+   index definition specified <literal>NULLS FIRST</> or
+   <literal>NULLS LAST</>, or the internal sort order of each column
+   (whether <literal>DESC</> or <literal>ASC</> were specified) are
+   all irrelevant.  Deferred unique constraints are not supported as
+   arbiters of whether an alternative <literal>ON CONFLICT</> path
+   should be taken.
+  </para>
+
+  <para>
+   The definition of a conflict for the purposes of <literal>ON
+   CONFLICT</> is somewhat subtle, although the exact definition is
+   seldom of great interest.  A conflict is either a unique violation
+   from a unique constraint (or unique index), or an exclusion
+   violation from an exclusion constraint.  Only unique indexes can be
+   inferred with a unique index inference specification, which is
+   required for the <command>UPDATE</command> variant, so in effect
+   only unique constraints (and unique indexes) are supported by the
+   <command>UPDATE</command> variant.  In contrast to the rules around
+   certain other SQL clauses, like the <literal>DISTINCT</literal>
+   clause, the definition of a duplicate (a conflict) is based on
+   whatever unique indexes happen to be defined on columns on the
+   table.  This means that if a user-defined type has multiple sort
+   orders, and the "equals" operator of any of those available sort
+   orders happens to be inconsistent (which goes against an unenforced
+   convention of <productname>PostgreSQL</productname>), the exact
+   behavior depends on the choice of operator class when the unique
+   index was created initially, and not any other consideration such
+   as the default operator class for the type of each indexed column.
+   If there are multiple unique indexes available that seem like
+   equally suitable candidates, but with inconsistent definitions of
+   "equals", then the system chooses whatever it estimates to be the
+   cheapest one to use as an arbiter of taking the alternative
+   <command>UPDATE</command>/<literal>IGNORE</literal> path.
+  </para>
+
+  <para>
+   The optional <replaceable
+   class="PARAMETER">index_condition</replaceable> can be used to
+   allow the inference specification to infer that a partial unique
+   index can be used.  Any unique index that otherwise satisfies the
+   inference specification, while also covering at least all the rows
+   in the table covered by <replaceable
+   class="PARAMETER">index_condition</replaceable> may be used.  It is
+   recommended that the partial index predicate of the unique index
+   intended to be used as the arbiter of taking the alternative path
+   be matched exactly, but this is not required.  Note that an error
+   will be raised if an arbiter unique index is chosen that does not
+   cover the tuple or tuples ultimately proposed for insertion.
+   However, an overly specific <replaceable
+   class="PARAMETER">index_condition</replaceable> does not imply that
+   arbitrating conflicts will be limited to the subset of rows covered
+   by the inferred unique index corresponding to <replaceable
+   class="PARAMETER">index_condition</replaceable>.
+  </para>
+
+  <para>
    The optional <literal>RETURNING</> clause causes <command>INSERT</>
-   to compute and return value(s) based on each row actually inserted.
+   to compute and return value(s) based on each row actually inserted
+   (or updated, if an <literal>ON CONFLICT UPDATE</> clause was used).
    This is primarily useful for obtaining values that were supplied by
    defaults, such as a serial sequence number.  However, any expression
    using the table's columns is allowed.  The syntax of the
    <literal>RETURNING</> list is identical to that of the output list
-   of <command>SELECT</>.
+   of <command>SELECT</>.  Only rows that were successfully inserted
+   or updated will be returned.  If a row was locked but not updated
+   because an <literal>ON CONFLICT UPDATE</> <literal>WHERE</> clause
+   did not pass, the row will not be returned.  Since
+   <literal>RETURNING</> is not part of the <command>UPDATE</>
+   auxiliary query, the special <literal>ON CONFLICT UPDATE</> aliases
+   (<varname>TARGET</> and <varname>EXCLUDED</>) may not be
+   referenced;  only the row as it exists after updating (or
+   inserting) is returned.
   </para>
 
   <para>
    You must have <literal>INSERT</literal> privilege on a table in
-   order to insert into it.  If a column list is specified, you only
-   need <literal>INSERT</literal> privilege on the listed columns.
-   Use of the <literal>RETURNING</> clause requires <literal>SELECT</>
-   privilege on all columns mentioned in <literal>RETURNING</>.
-   If you use the <replaceable
-   class="PARAMETER">query</replaceable> clause to insert rows from a
-   query, you of course need to have <literal>SELECT</literal> privilege on
-   any table or column used in the query.
+   order to insert into it, as well as <literal>UPDATE
+   privilege</literal> if and only if <literal>ON CONFLICT UPDATE</>
+   is specified.  If a column list is specified, you only need
+   <literal>INSERT</literal> privilege on the listed columns.
+   Similarly, when <literal>ON CONFLICT UPDATE</> is specified, you
+   only need <literal>UPDATE</> privilege on the column(s) that are
+   listed to be updated, as well as SELECT privilege on any column
+   whose values are read in the <literal>ON CONFLICT UPDATE</>
+   expressions or <replaceable>condition</>.  Use of the
+   <literal>RETURNING</> clause requires <literal>SELECT</> privilege
+   on all columns mentioned in <literal>RETURNING</>.  If you use the
+   <replaceable class="PARAMETER">query</replaceable> clause to insert
+   rows from a query, you of course need to have
+   <literal>SELECT</literal> privilege on any table or column used in
+   the query.
   </para>
  </refsect1>
 
@@ -121,7 +324,54 @@ INSERT INTO <replaceable class="PARAMETER">table_name</replaceable> [ ( <replace
       The name of a column in the table named by <replaceable class="PARAMETER">table_name</replaceable>.
       The column name can be qualified with a subfield name or array
       subscript, if needed.  (Inserting into only some fields of a
-      composite column leaves the other fields null.)
+      composite column leaves the other fields null.)  When
+      referencing a column with <literal>ON CONFLICT UPDATE</>, do not
+      include the table's name in the specification of a target
+      column.  For example, <literal>INSERT ... ON CONFLICT UPDATE tab
+      SET TARGET.col = 1</> is invalid.
+     </para>
+    </listitem>
+   </varlistentry>
+
+   <varlistentry>
+    <term><replaceable class="PARAMETER">column_name_index</replaceable></term>
+    <listitem>
+     <para>
+      The name of a <replaceable
+      class="PARAMETER">table_name</replaceable> column (with several
+      columns potentially named).  These are used to infer a
+      particular unique index defined on <replaceable
+      class="PARAMETER">table_name</replaceable>.  This requires
+      <literal>ON CONFLICT UPDATE</> and <literal>ON CONFLICT
+      IGNORE</> to assume that all expected sources of uniqueness
+      violations originate within the columns/rows constrained by the
+      unique index.  When this is omitted, (which is forbidden with
+      the <literal>ON CONFLICT UPDATE</> variant), the system checks
+      for sources of uniqueness violations ahead of time in all unique
+      indexes.  Otherwise, only a single specified unique index is
+      checked ahead of time, and uniqueness violation errors can
+      appear for conflicts originating in any other unique index.  If
+      a unique index cannot be inferred, an error is raised.
+     </para>
+    </listitem>
+   </varlistentry>
+
+   <varlistentry>
+    <term><replaceable class="PARAMETER">expression_index</replaceable></term>
+    <listitem>
+     <para>
+      Equivalent to <replaceable
+      class="PARAMETER">column_name_index</replaceable>, but used to
+      infer a particular expressional index instead.
+     </para>
+    </listitem>
+   </varlistentry>
+
+   <varlistentry>
+    <term><replaceable class="PARAMETER">index_condition</replaceable></term>
+    <listitem>
+     <para>
+      Used to allow inference of partial unique indexes.
      </para>
     </listitem>
    </varlistentry>
@@ -167,12 +417,25 @@ INSERT INTO <replaceable class="PARAMETER">table_name</replaceable> [ ( <replace
    </varlistentry>
 
    <varlistentry>
+    <term><replaceable class="PARAMETER">condition</replaceable></term>
+    <listitem>
+     <para>
+      An expression that returns a value of type <type>boolean</type>.
+      Only rows for which this expression returns <literal>true</>
+      will be updated, although all rows will be locked when the
+      <literal>ON CONFLICT UPDATE</> path is taken.
+     </para>
+    </listitem>
+   </varlistentry>
+   <varlistentry>
+
     <term><replaceable class="PARAMETER">output_expression</replaceable></term>
     <listitem>
      <para>
       An expression to be computed and returned by the <command>INSERT</>
-      command after each row is inserted.  The expression can use any
-      column names of the table named by <replaceable class="PARAMETER">table_name</replaceable>.
+      command after each row is inserted (not updated). The
+      expression can use any column names of the table named by
+      <replaceable class="PARAMETER">table_name</replaceable>.
       Write <literal>*</> to return all columns of the inserted row(s).
      </para>
     </listitem>
@@ -198,20 +461,29 @@ INSERT INTO <replaceable class="PARAMETER">table_name</replaceable> [ ( <replace
 <screen>
 INSERT <replaceable>oid</replaceable> <replaceable class="parameter">count</replaceable>
 </screen>
+   However, in the event of an <literal>ON CONFLICT UPDATE</> clause
+   (but <emphasis>not</emphasis> in the event of an <literal>ON
+   CONFLICT IGNORE</> clause), the command tag reports the number of
+   rows inserted or updated together, of the form
+<screen>
+UPSERT <replaceable>oid</replaceable> <replaceable class="parameter">count</replaceable>
+</screen>
    The <replaceable class="parameter">count</replaceable> is the number
    of rows inserted.  If <replaceable class="parameter">count</replaceable>
    is exactly one, and the target table has OIDs, then
    <replaceable class="parameter">oid</replaceable> is the
-   <acronym>OID</acronym> assigned to the inserted row.  Otherwise
-   <replaceable class="parameter">oid</replaceable> is zero.
+   <acronym>OID</acronym>
+   assigned to the inserted row (but not if there is only a single
+   updated row).  Otherwise <replaceable
+   class="parameter">oid</replaceable> is zero..
   </para>
 
   <para>
    If the <command>INSERT</> command contains a <literal>RETURNING</>
    clause, the result will be similar to that of a <command>SELECT</>
    statement containing the columns and values defined in the
-   <literal>RETURNING</> list, computed over the row(s) inserted by the
-   command.
+   <literal>RETURNING</> list, computed over the row(s) inserted or
+   updated by the command.
   </para>
  </refsect1>
 
@@ -311,7 +583,63 @@ WITH upd AS (
     RETURNING *
 )
 INSERT INTO employees_log SELECT *, current_timestamp FROM upd;
-</programlisting></para>
+</programlisting>
+  </para>
+  <para>
+   Insert or update new distributors as appropriate.  Assumes a unique
+   index has been defined that constrains values appearing in the
+   <literal>did</literal> column.  Note that an <varname>EXCLUDED</>
+   expression is used to reference values originally proposed for
+   insertion:
+<programlisting>
+  INSERT INTO distributors (did, dname)
+  VALUES (5, 'Gizmo transglobal'), (6, 'Associated Computing, inc')
+  ON CONFLICT (did) UPDATE SET dname = EXCLUDED.dname
+</programlisting>
+  </para>
+  <para>
+   Insert a distributor, or do nothing for rows proposed for insertion
+   when an existing, excluded row (a row with a matching constrained
+   column or columns after before row insert triggers fire) exists.
+   Example assumes a unique index has been defined that constrains
+   values appearing in the <literal>did</literal> column (although
+   since the <literal>IGNORE</> variant was used, the specification of
+   columns to infer a unique index from is not mandatory):
+<programlisting>
+  INSERT INTO distributors (did, dname) VALUES (7, 'Redline GmbH')
+  ON CONFLICT (did) IGNORE
+</programlisting>
+  </para>
+  <para>
+   Insert or update new distributors as appropriate.  Example assumes
+   a unique index has been defined that constrains values appearing in
+   the <literal>did</literal> column.  <literal>WHERE</> clause is
+   used to limit the rows actually updated (any existing row not
+   updated will still be locked, though):
+<programlisting>
+  -- Don't update existing distributors based in a certain ZIP code
+  INSERT INTO distributors (did, dname) VALUES (8, 'Anvil Distribution')
+  ON CONFLICT (did) UPDATE
+  SET dname = EXCLUDED.dname || ' (formerly ' || TARGET.dname || ')'
+  WHERE TARGET.zipcode != '21201'
+</programlisting>
+  </para>
+  <para>
+   Insert new distributor if possible;  otherwise
+   <literal>IGNORE</literal>.  Example assumes a unique index has been
+   defined that constrains values appearing in the
+   <literal>did</literal> column on a subset of rows where the
+   <literal>is_active</literal> boolean column evaluates to
+   <literal>true</literal>:
+<programlisting>
+  -- This statement could infer a partial unique index on did
+  -- with a predicate of WHERE is_active, but it could also
+  -- just use a regular unique constraint on did if that was
+  -- all that was available.
+  INSERT INTO distributors (did, dname) VALUES (9, 'Antwerp Design')
+  ON CONFLICT (did WHERE is_active) IGNORE
+</programlisting>
+  </para>
  </refsect1>
 
  <refsect1>
@@ -321,7 +649,8 @@ INSERT INTO employees_log SELECT *, current_timestamp FROM upd;
    <command>INSERT</command> conforms to the SQL standard, except that
    the <literal>RETURNING</> clause is a
    <productname>PostgreSQL</productname> extension, as is the ability
-   to use <literal>WITH</> with <command>INSERT</>.
+   to use <literal>WITH</> with <command>INSERT</>, and the ability to
+   specify an alternative path with <literal>ON CONFLICT</>.
    Also, the case in
    which a column name list is omitted, but not all the columns are
    filled from the <literal>VALUES</> clause or <replaceable>query</>,
diff --git a/doc/src/sgml/ref/set_constraints.sgml b/doc/src/sgml/ref/set_constraints.sgml
index 7c31871..1e0a2f8 100644
--- a/doc/src/sgml/ref/set_constraints.sgml
+++ b/doc/src/sgml/ref/set_constraints.sgml
@@ -69,7 +69,11 @@ SET CONSTRAINTS { ALL | <replaceable class="parameter">name</replaceable> [, ...
   <para>
    Currently, only <literal>UNIQUE</>, <literal>PRIMARY KEY</>,
    <literal>REFERENCES</> (foreign key), and <literal>EXCLUDE</>
-   constraints are affected by this setting.
+   constraints are affected by this setting.  Note that constraints
+   that were created with this clause cannot be used as arbiters of
+   whether or not to take the alternative path with an
+   <command>INSERT</command> statement that includes an <literal>ON
+   CONFLICT UPDATE</> clause.
    <literal>NOT NULL</> and <literal>CHECK</> constraints are
    always checked immediately when a row is inserted or modified
    (<emphasis>not</> at the end of the statement).
diff --git a/doc/src/sgml/trigger.sgml b/doc/src/sgml/trigger.sgml
index f94aea1..5141690 100644
--- a/doc/src/sgml/trigger.sgml
+++ b/doc/src/sgml/trigger.sgml
@@ -40,14 +40,17 @@
     On tables and foreign tables, triggers can be defined to execute either
     before or after any <command>INSERT</command>, <command>UPDATE</command>,
     or <command>DELETE</command> operation, either once per modified row,
-    or once per <acronym>SQL</acronym> statement.
-    <command>UPDATE</command> triggers can moreover be set to fire only if
-    certain columns are mentioned in the <literal>SET</literal> clause of the
-    <command>UPDATE</command> statement.
-    Triggers can also fire for <command>TRUNCATE</command> statements.
-    If a trigger event occurs, the trigger's function is called at the
-    appropriate time to handle the event.  Foreign tables do not support the
-    TRUNCATE statement at all.
+    or once per <acronym>SQL</acronym> statement.  If an
+    <command>INSERT</command> contains an <literal>ON CONFLICT UPDATE</>
+    clause, it is possible that the effects of a BEFORE insert trigger and
+    a BEFORE update trigger can both be applied twice, if a reference to
+    an <varname>EXCLUDED</> column appears.  <command>UPDATE</command>
+    triggers can moreover be set to fire only if certain columns are
+    mentioned in the <literal>SET</literal> clause of the
+    <command>UPDATE</command> statement.  Triggers can also fire for
+    <command>TRUNCATE</command> statements.  If a trigger event occurs,
+    the trigger's function is called at the appropriate time to handle the
+    event.  Foreign tables do not support the TRUNCATE statement at all.
    </para>
 
    <para>
@@ -119,6 +122,36 @@
    </para>
 
    <para>
+    If an <command>INSERT</command> contains an <literal>ON CONFLICT
+    UPDATE</> clause, it is possible that the effects of all row-level
+    <literal>BEFORE</> <command>INSERT</command> triggers and all
+    row-level BEFORE <command>UPDATE</command> triggers can both be
+    applied in a way that is apparent from the final state of the updated
+    row, if an <varname>EXCLUDED</> column is referenced.  There need not
+    be an <varname>EXCLUDED</> column reference for both sets of BEFORE
+    row-level triggers to execute, though.  The possibility of surprising
+    outcomes should be considered when there are both <literal>BEFORE</>
+    <command>INSERT</command> and <literal>BEFORE</>
+    <command>UPDATE</command> row-level triggers that both affect a row
+    being inserted/updated (this can still be problematic if the
+    modifications are more or less equivalent if they're not also
+    idempotent).  Note that statement-level <command>UPDATE</command>
+    triggers are executed when <literal>ON CONFLICT UPDATE</> is
+    specified, regardless of whether or not any rows were affected by
+    the <command>UPDATE</command>.  An <command>INSERT</command> with
+    an <literal>ON CONFLICT UPDATE</> clause will execute
+    statement-level <literal>BEFORE</> <command>INSERT</command>
+    triggers first, then statement-level <literal>BEFORE</>
+    <command>UPDATE</command> triggers, followed by statement-level
+    <literal>AFTER</> <command>UPDATE</command> triggers and finally
+    statement-level <literal>AFTER</> <command>INSERT</command>
+    triggers.  <literal>ON CONFLICT UPDATE</> is not supported on
+    views (Only <literal>ON CONFLICT IGNORE</> is supported on
+    updatable views); therefore, unpredictable interactions with
+    <literal>INSTEAD OF</> triggers are not possible.
+   </para>
+
+   <para>
     Trigger functions invoked by per-statement triggers should always
     return <symbol>NULL</symbol>. Trigger functions invoked by per-row
     triggers can return a table row (a value of
-- 
1.9.1

