From 6c6f395a8aca8a9525d62cbf46fbafd130bdb9e5 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Tue, 21 May 2002 22:59:01 +0000 Subject: [PATCH] Since COPY fires triggers, it seems like a good idea for it to use a frozen (copied) snapshot too. Move execMain's snapshot copying code out into a subroutine in case we find other places that need it. --- src/backend/commands/copy.c | 7 +++++-- src/backend/executor/execMain.c | 20 ++---------------- src/backend/utils/time/tqual.c | 36 ++++++++++++++++++++++++++++++++- src/include/utils/tqual.h | 3 ++- 4 files changed, 44 insertions(+), 22 deletions(-) diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c index 83ca5b32c5..16c23d320e 100644 --- a/src/backend/commands/copy.c +++ b/src/backend/commands/copy.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.155 2002/05/21 22:05:54 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.156 2002/05/21 22:59:00 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -447,6 +447,7 @@ CopyTo(Relation rel, bool binary, bool oids, FILE *fp, bool *isvarlena; int16 fld_size; char *string; + Snapshot mySnapshot; if (oids && !rel->rd_rel->relhasoids) elog(ERROR, "COPY: table %s does not have OIDs", @@ -494,7 +495,9 @@ CopyTo(Relation rel, bool binary, bool oids, FILE *fp, CopySendData(&tmp, sizeof(int32), fp); } - scandesc = heap_beginscan(rel, QuerySnapshot, 0, NULL); + mySnapshot = CopyQuerySnapshot(); + + scandesc = heap_beginscan(rel, mySnapshot, 0, NULL); while ((tuple = heap_getnext(scandesc, ForwardScanDirection)) != NULL) { diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index a8c776bab2..29687a54ba 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -27,7 +27,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.162 2002/05/21 22:05:55 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.163 2002/05/21 22:59:01 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -101,7 +101,6 @@ TupleDesc ExecutorStart(QueryDesc *queryDesc, EState *estate) { TupleDesc result; - Snapshot es_snapshot; /* sanity checks */ Assert(queryDesc != NULL); @@ -121,22 +120,7 @@ ExecutorStart(QueryDesc *queryDesc, EState *estate) * for the life of this query, even if it outlives the current command * and current snapshot. */ - if (QuerySnapshot == NULL) /* should be set already, but... */ - SetQuerySnapshot(); - - es_snapshot = (Snapshot) palloc(sizeof(SnapshotData)); - memcpy(es_snapshot, QuerySnapshot, sizeof(SnapshotData)); - if (es_snapshot->xcnt > 0) - { - es_snapshot->xip = (TransactionId *) - palloc(es_snapshot->xcnt * sizeof(TransactionId)); - memcpy(es_snapshot->xip, QuerySnapshot->xip, - es_snapshot->xcnt * sizeof(TransactionId)); - } - else - es_snapshot->xip = NULL; - - estate->es_snapshot = es_snapshot; + estate->es_snapshot = CopyQuerySnapshot(); /* * Initialize the plan diff --git a/src/backend/utils/time/tqual.c b/src/backend/utils/time/tqual.c index 58534159f7..582ec28183 100644 --- a/src/backend/utils/time/tqual.c +++ b/src/backend/utils/time/tqual.c @@ -16,7 +16,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/time/tqual.c,v 1.51 2002/05/21 22:05:55 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/time/tqual.c,v 1.52 2002/05/21 22:59:01 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -963,6 +963,40 @@ SetQuerySnapshot(void) Assert(QuerySnapshot != NULL); } +/* + * CopyQuerySnapshot + * Copy the current query snapshot. + * + * Copying the snapshot is done so that a query is guaranteed to use a + * consistent snapshot for its entire execution life, even if the command + * counter is incremented or SetQuerySnapshot() is called while it runs + * (as could easily happen, due to triggers etc. executing queries). + * + * The copy is palloc'd in the current memory context. + */ +Snapshot +CopyQuerySnapshot(void) +{ + Snapshot snapshot; + + if (QuerySnapshot == NULL) /* should be set already, but... */ + SetQuerySnapshot(); + + snapshot = (Snapshot) palloc(sizeof(SnapshotData)); + memcpy(snapshot, QuerySnapshot, sizeof(SnapshotData)); + if (snapshot->xcnt > 0) + { + snapshot->xip = (TransactionId *) + palloc(snapshot->xcnt * sizeof(TransactionId)); + memcpy(snapshot->xip, QuerySnapshot->xip, + snapshot->xcnt * sizeof(TransactionId)); + } + else + snapshot->xip = NULL; + + return snapshot; +} + /* * FreeXactSnapshot * Free snapshot(s) at end of transaction. diff --git a/src/include/utils/tqual.h b/src/include/utils/tqual.h index f5f03ea01a..3ddceff5f8 100644 --- a/src/include/utils/tqual.h +++ b/src/include/utils/tqual.h @@ -8,7 +8,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: tqual.h,v 1.39 2002/05/21 22:05:55 tgl Exp $ + * $Id: tqual.h,v 1.40 2002/05/21 22:59:01 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -112,6 +112,7 @@ extern HTSV_Result HeapTupleSatisfiesVacuum(HeapTupleHeader tuple, extern Snapshot GetSnapshotData(bool serializable); extern void SetQuerySnapshot(void); +extern Snapshot CopyQuerySnapshot(void); extern void FreeXactSnapshot(void); #endif /* TQUAL_H */ -- 2.40.0