Tom Lane <t...@sss.pgh.pa.us> wrote:
 
> +1 for adding parens; we might want to make a function of it
> someday.
 
> How about IsolationUsesXactSnapshot
 
Patch attached.
 
Joe said that he'll review this weekend and probably commit in a day
or two if there are no objections.
 
-Kevin
*** a/src/backend/catalog/index.c
--- b/src/backend/catalog/index.c
***************
*** 2049,2055 **** IndexCheckExclusion(Relation heapRelation,
   *
   * After completing validate_index(), we wait until all transactions that
   * were alive at the time of the reference snapshot are gone; this is
!  * necessary to be sure there are none left with a serializable snapshot
   * older than the reference (and hence possibly able to see tuples we did
   * not index).        Then we mark the index "indisvalid" and commit.  
Subsequent
   * transactions will be able to use it for queries.
--- 2049,2055 ----
   *
   * After completing validate_index(), we wait until all transactions that
   * were alive at the time of the reference snapshot are gone; this is
!  * necessary to be sure there are none left with a transaction-based snapshot
   * older than the reference (and hence possibly able to see tuples we did
   * not index).        Then we mark the index "indisvalid" and commit.  
Subsequent
   * transactions will be able to use it for queries.
*** a/src/backend/commands/trigger.c
--- b/src/backend/commands/trigger.c
***************
*** 2387,2393 **** ltrmark:;
  
                        case HeapTupleUpdated:
                                ReleaseBuffer(buffer);
!                               if (IsXactIsoLevelSerializable)
                                        ereport(ERROR,
                                                        
(errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
                                                         errmsg("could not 
serialize access due to concurrent update")));
--- 2387,2393 ----
  
                        case HeapTupleUpdated:
                                ReleaseBuffer(buffer);
!                               if (IsolationUsesXactSnapshot())
                                        ereport(ERROR,
                                                        
(errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
                                                         errmsg("could not 
serialize access due to concurrent update")));
*** a/src/backend/executor/execMain.c
--- b/src/backend/executor/execMain.c
***************
*** 1554,1560 **** EvalPlanQualFetch(EState *estate, Relation relation, int 
lockmode,
  
                                case HeapTupleUpdated:
                                        ReleaseBuffer(buffer);
!                                       if (IsXactIsoLevelSerializable)
                                                ereport(ERROR,
                                                                
(errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
                                                                 errmsg("could 
not serialize access due to concurrent update")));
--- 1554,1560 ----
  
                                case HeapTupleUpdated:
                                        ReleaseBuffer(buffer);
!                                       if (IsolationUsesXactSnapshot())
                                                ereport(ERROR,
                                                                
(errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
                                                                 errmsg("could 
not serialize access due to concurrent update")));
*** a/src/backend/executor/nodeLockRows.c
--- b/src/backend/executor/nodeLockRows.c
***************
*** 130,136 **** lnext:
                                break;
  
                        case HeapTupleUpdated:
!                               if (IsXactIsoLevelSerializable)
                                        ereport(ERROR,
                                                        
(errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
                                                         errmsg("could not 
serialize access due to concurrent update")));
--- 130,136 ----
                                break;
  
                        case HeapTupleUpdated:
!                               if (IsolationUsesXactSnapshot())
                                        ereport(ERROR,
                                                        
(errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
                                                         errmsg("could not 
serialize access due to concurrent update")));
*** a/src/backend/executor/nodeModifyTable.c
--- b/src/backend/executor/nodeModifyTable.c
***************
*** 328,334 **** ldelete:;
                        break;
  
                case HeapTupleUpdated:
!                       if (IsXactIsoLevelSerializable)
                                ereport(ERROR,
                                                
(errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
                                                 errmsg("could not serialize 
access due to concurrent update")));
--- 328,334 ----
                        break;
  
                case HeapTupleUpdated:
!                       if (IsolationUsesXactSnapshot())
                                ereport(ERROR,
                                                
(errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
                                                 errmsg("could not serialize 
access due to concurrent update")));
***************
*** 516,522 **** lreplace:;
                        break;
  
                case HeapTupleUpdated:
!                       if (IsXactIsoLevelSerializable)
                                ereport(ERROR,
                                                
(errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
                                                 errmsg("could not serialize 
access due to concurrent update")));
--- 516,522 ----
                        break;
  
                case HeapTupleUpdated:
!                       if (IsolationUsesXactSnapshot())
                                ereport(ERROR,
                                                
(errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
                                                 errmsg("could not serialize 
access due to concurrent update")));
*** a/src/backend/utils/adt/ri_triggers.c
--- b/src/backend/utils/adt/ri_triggers.c
***************
*** 3332,3346 **** ri_PerformCheck(RI_QueryKey *qkey, SPIPlanPtr qplan,
        /*
         * In READ COMMITTED mode, we just need to use an up-to-date regular
         * snapshot, and we will see all rows that could be interesting. But in
!        * SERIALIZABLE mode, we can't change the transaction snapshot. If the
!        * caller passes detectNewRows == false then it's okay to do the query
         * with the transaction snapshot; otherwise we use a current snapshot, 
and
         * tell the executor to error out if it finds any rows under the current
         * snapshot that wouldn't be visible per the transaction snapshot.  Note
         * that SPI_execute_snapshot will register the snapshots, so we don't 
need
         * to bother here.
         */
!       if (IsXactIsoLevelSerializable && detectNewRows)
        {
                CommandCounterIncrement();              /* be sure all my own 
work is visible */
                test_snapshot = GetLatestSnapshot();
--- 3332,3346 ----
        /*
         * In READ COMMITTED mode, we just need to use an up-to-date regular
         * snapshot, and we will see all rows that could be interesting. But in
!        * xact-snapshot-based modes, we can't change the transaction snapshot. 
If
!        * the caller passes detectNewRows == false then it's okay to do the 
query
         * with the transaction snapshot; otherwise we use a current snapshot, 
and
         * tell the executor to error out if it finds any rows under the current
         * snapshot that wouldn't be visible per the transaction snapshot.  Note
         * that SPI_execute_snapshot will register the snapshots, so we don't 
need
         * to bother here.
         */
!       if (IsolationUsesXactSnapshot() && detectNewRows)
        {
                CommandCounterIncrement();              /* be sure all my own 
work is visible */
                test_snapshot = GetLatestSnapshot();
*** a/src/backend/utils/time/snapmgr.c
--- b/src/backend/utils/time/snapmgr.c
***************
*** 37,44 ****
  
  
  /*
!  * CurrentSnapshot points to the only snapshot taken in a serializable
!  * transaction, and to the latest one taken in a read-committed transaction.
   * SecondarySnapshot is a snapshot that's always up-to-date as of the current
   * instant, even on a serializable transaction.  It should only be used for
   * special-purpose code (say, RI checking.)
--- 37,44 ----
  
  
  /*
!  * CurrentSnapshot points to the only snapshot taken in a xact-snapshot-based
!  * transaction; otherwise to the latest one taken.
   * SecondarySnapshot is a snapshot that's always up-to-date as of the current
   * instant, even on a serializable transaction.  It should only be used for
   * special-purpose code (say, RI checking.)
***************
*** 97,107 **** static int      RegisteredSnapshots = 0;
  bool          FirstSnapshotSet = false;
  
  /*
!  * Remembers whether this transaction registered a serializable snapshot at
   * start.  We cannot trust FirstSnapshotSet in combination with
!  * IsXactIsoLevelSerializable, because GUC may be reset before us.
   */
! static bool registered_serializable = false;
  
  
  static Snapshot CopySnapshot(Snapshot snapshot);
--- 97,107 ----
  bool          FirstSnapshotSet = false;
  
  /*
!  * Remembers whether this transaction registered a transaction-based snapshot 
at
   * start.  We cannot trust FirstSnapshotSet in combination with
!  * IsolationUsesXactSnapshot(), because GUC may be reset before us.
   */
! static bool registered_xact_snapshot = false;
  
  
  static Snapshot CopySnapshot(Snapshot snapshot);
***************
*** 130,150 **** GetTransactionSnapshot(void)
                FirstSnapshotSet = true;
  
                /*
!                * In serializable mode, the first snapshot must live until end 
of
!                * xact regardless of what the caller does with it, so we must
!                * register it internally here and unregister it at end of xact.
                 */
!               if (IsXactIsoLevelSerializable)
                {
                        CurrentSnapshot = 
RegisterSnapshotOnOwner(CurrentSnapshot,
                                                                                
                TopTransactionResourceOwner);
!                       registered_serializable = true;
                }
  
                return CurrentSnapshot;
        }
  
!       if (IsXactIsoLevelSerializable)
                return CurrentSnapshot;
  
        CurrentSnapshot = GetSnapshotData(&CurrentSnapshotData);
--- 130,151 ----
                FirstSnapshotSet = true;
  
                /*
!                * In xact-snapshot-based isolation levels, the first snapshot 
must
!                * live until end of xact regardless of what the caller does 
with it,
!                * so we must register it internally here and unregister it at 
end of
!                * xact.
                 */
!               if (IsolationUsesXactSnapshot())
                {
                        CurrentSnapshot = 
RegisterSnapshotOnOwner(CurrentSnapshot,
                                                                                
                TopTransactionResourceOwner);
!                       registered_xact_snapshot = true;
                }
  
                return CurrentSnapshot;
        }
  
!       if (IsolationUsesXactSnapshot())
                return CurrentSnapshot;
  
        CurrentSnapshot = GetSnapshotData(&CurrentSnapshotData);
***************
*** 155,161 **** GetTransactionSnapshot(void)
  /*
   * GetLatestSnapshot
   *            Get a snapshot that is up-to-date as of the current instant,
!  *            even if we are executing in SERIALIZABLE mode.
   */
  Snapshot
  GetLatestSnapshot(void)
--- 156,162 ----
  /*
   * GetLatestSnapshot
   *            Get a snapshot that is up-to-date as of the current instant,
!  *            even if we are executing in xact-snapshot-based mode.
   */
  Snapshot
  GetLatestSnapshot(void)
***************
*** 515,527 **** void
  AtEarlyCommit_Snapshot(void)
  {
        /*
!        * On a serializable transaction we must unregister our private refcount
!        * to the serializable snapshot.
         */
!       if (registered_serializable)
                UnregisterSnapshotFromOwner(CurrentSnapshot,
                                                                        
TopTransactionResourceOwner);
!       registered_serializable = false;
  
  }
  
--- 516,528 ----
  AtEarlyCommit_Snapshot(void)
  {
        /*
!        * On a xact-snapshot-based transaction we must unregister our private
!        * refcount to the xact snapshot.
         */
!       if (registered_xact_snapshot)
                UnregisterSnapshotFromOwner(CurrentSnapshot,
                                                                        
TopTransactionResourceOwner);
!       registered_xact_snapshot = false;
  
  }
  
***************
*** 557,561 **** AtEOXact_Snapshot(bool isCommit)
        SecondarySnapshot = NULL;
  
        FirstSnapshotSet = false;
!       registered_serializable = false;
  }
--- 558,562 ----
        SecondarySnapshot = NULL;
  
        FirstSnapshotSet = false;
!       registered_xact_snapshot = false;
  }
*** a/src/include/access/xact.h
--- b/src/include/access/xact.h
***************
*** 35,41 **** extern int       XactIsoLevel;
   * We only implement two isolation levels internally.  This macro should
   * be used to check which one is selected.
   */
! #define IsXactIsoLevelSerializable (XactIsoLevel >= XACT_REPEATABLE_READ)
  
  /* Xact read-only state */
  extern bool DefaultXactReadOnly;
--- 35,41 ----
   * We only implement two isolation levels internally.  This macro should
   * be used to check which one is selected.
   */
! #define IsolationUsesXactSnapshot() (XactIsoLevel >= XACT_REPEATABLE_READ)
  
  /* Xact read-only state */
  extern bool DefaultXactReadOnly;
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to