@@ -543,14 +543,63 @@ show_log_timezone(void)
543
543
}
544
544
545
545
546
+ /*
547
+ * SET TRANSACTION READ ONLY and SET TRANSACTION READ WRITE
548
+ *
549
+ * We allow idempotent changes (r/w -> r/w and r/o -> r/o) at any time, and
550
+ * we also always allow changes from read-write to read-only. However,
551
+ * read-only to read-write may be changed only when source == PGC_S_OVERRIDE
552
+ * (i.e. we're aborting a read only transaction and restoring the previous
553
+ * setting) or in a top-level transaction that has not yet taken an initial
554
+ * snapshot.
555
+ */
556
+ bool
557
+ assign_transaction_read_only (bool newval , bool doit , GucSource source )
558
+ {
559
+ if (source != PGC_S_OVERRIDE && newval == false && XactReadOnly )
560
+ {
561
+ /* Can't go to r/w mode inside a r/o transaction */
562
+ if (IsSubTransaction ())
563
+ {
564
+ ereport (GUC_complaint_elevel (source ),
565
+ (errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
566
+ errmsg ("cannot set transaction read-write mode inside a read-only transaction" )));
567
+ return false;
568
+ }
569
+ /* Top level transaction can't change to r/w after first snapshot. */
570
+ if (FirstSnapshotSet )
571
+ {
572
+ ereport (GUC_complaint_elevel (source ),
573
+ (errcode (ERRCODE_ACTIVE_SQL_TRANSACTION ),
574
+ errmsg ("transaction read-write mode must be set before any query" )));
575
+ return false;
576
+ }
577
+ /* Can't go to r/w mode while recovery is still active */
578
+ if (RecoveryInProgress ())
579
+ {
580
+ ereport (GUC_complaint_elevel (source ),
581
+ (errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
582
+ errmsg ("cannot set transaction read-write mode during recovery" )));
583
+ return false;
584
+ }
585
+ }
586
+
587
+ return true;
588
+ }
589
+
546
590
/*
547
591
* SET TRANSACTION ISOLATION LEVEL
592
+ *
593
+ * We allow idempotent changes at any time, but otherwise this can only be
594
+ * changed from a toplevel transaction that has not yet taken a snapshot, or
595
+ * when source == PGC_S_OVERRIDE (i.e. we're aborting a transaction and
596
+ * restoring the previously set value).
548
597
*/
549
598
const char *
550
599
assign_XactIsoLevel (const char * value , bool doit , GucSource source )
551
600
{
552
601
/* source == PGC_S_OVERRIDE means do it anyway, eg at xact abort */
553
- if (source != PGC_S_OVERRIDE )
602
+ if (source != PGC_S_OVERRIDE && strcmp ( value , XactIsoLevel_string ) != 0 )
554
603
{
555
604
if (FirstSnapshotSet )
556
605
{
@@ -560,7 +609,7 @@ assign_XactIsoLevel(const char *value, bool doit, GucSource source)
560
609
return NULL ;
561
610
}
562
611
/* We ignore a subtransaction setting it to the existing value. */
563
- if (IsSubTransaction () && strcmp ( value , XactIsoLevel_string ) != 0 )
612
+ if (IsSubTransaction ())
564
613
{
565
614
ereport (GUC_complaint_elevel (source ),
566
615
(errcode (ERRCODE_ACTIVE_SQL_TRANSACTION ),
0 commit comments