diff options
author | Robert Haas <rhaas@postgresql.org> | 2011-01-22 20:51:32 -0500 |
---|---|---|
committer | Robert Haas <rhaas@postgresql.org> | 2011-01-22 20:55:50 -0500 |
commit | 6f59777c65d557485e933a383ebc4c3fdfc1a2b7 (patch) | |
tree | b5ce0b0f7d50c18b09e38b75b2a43082bf4deac3 /src/backend/commands/variable.c | |
parent | cc73c160507588bdc5822d7f2bb79d6b3a386761 (diff) | |
download | postgresql-6f59777c65d557485e933a383ebc4c3fdfc1a2b7.tar.gz postgresql-6f59777c65d557485e933a383ebc4c3fdfc1a2b7.zip |
Code cleanup for assign_transaction_read_only.
As in commit fb4c5d2798730f60b102d775f22fb53c26a6445d on 2011-01-21,
this avoids spurious debug messages and allows idempotent changes at
any time. Along the way, make assign_XactIsoLevel allow idempotent
changes even when not within a subtransaction, to be consistent with
the new coding of assign_transaction_read_only and because there's
no compelling reason to do otherwise.
Kevin Grittner, with some adjustments.
Diffstat (limited to 'src/backend/commands/variable.c')
-rw-r--r-- | src/backend/commands/variable.c | 53 |
1 files changed, 51 insertions, 2 deletions
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c index 1e9bdc3f218..139148eec2e 100644 --- a/src/backend/commands/variable.c +++ b/src/backend/commands/variable.c @@ -544,13 +544,62 @@ show_log_timezone(void) /* + * SET TRANSACTION READ ONLY and SET TRANSACTION READ WRITE + * + * We allow idempotent changes (r/w -> r/w and r/o -> r/o) at any time, and + * we also always allow changes from read-write to read-only. However, + * read-only to read-write may be changed only when source == PGC_S_OVERRIDE + * (i.e. we're aborting a read only transaction and restoring the previous + * setting) or in a top-level transaction that has not yet taken an initial + * snapshot. + */ +bool +assign_transaction_read_only(bool newval, bool doit, GucSource source) +{ + if (source != PGC_S_OVERRIDE && newval == false && XactReadOnly) + { + /* Can't go to r/w mode inside a r/o transaction */ + if (IsSubTransaction()) + { + ereport(GUC_complaint_elevel(source), + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("cannot set transaction read-write mode inside a read-only transaction"))); + return false; + } + /* Top level transaction can't change to r/w after first snapshot. */ + if (FirstSnapshotSet) + { + ereport(GUC_complaint_elevel(source), + (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION), + errmsg("transaction read-write mode must be set before any query"))); + return false; + } + /* Can't go to r/w mode while recovery is still active */ + if (RecoveryInProgress()) + { + ereport(GUC_complaint_elevel(source), + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("cannot set transaction read-write mode during recovery"))); + return false; + } + } + + return true; +} + +/* * SET TRANSACTION ISOLATION LEVEL + * + * We allow idempotent changes at any time, but otherwise this can only be + * changed from a toplevel transaction that has not yet taken a snapshot, or + * when source == PGC_S_OVERRIDE (i.e. we're aborting a transaction and + * restoring the previously set value). */ const char * assign_XactIsoLevel(const char *value, bool doit, GucSource source) { /* source == PGC_S_OVERRIDE means do it anyway, eg at xact abort */ - if (source != PGC_S_OVERRIDE) + if (source != PGC_S_OVERRIDE && strcmp(value, XactIsoLevel_string) != 0) { if (FirstSnapshotSet) { @@ -560,7 +609,7 @@ assign_XactIsoLevel(const char *value, bool doit, GucSource source) return NULL; } /* We ignore a subtransaction setting it to the existing value. */ - if (IsSubTransaction() && strcmp(value, XactIsoLevel_string) != 0) + if (IsSubTransaction()) { ereport(GUC_complaint_elevel(source), (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION), |