Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit3853664

Browse files
committed
Introduce GUC_NO_RESET flag.
Previously, the transaction-property GUCs such as transaction_isolationcould be reset after starting a transaction, because we marked themas GUC_NO_RESET_ALL but still allowed a targeted RESET. That leads toassertion failures or worse, because those properties aren't supposedto change after we've acquired a transaction snapshot.There are some NO_RESET_ALL variables for which RESET is okay, sowe can't just redefine the semantics of that flag. Instead introducea separate GUC_NO_RESET flag. Mark "seed", as well as the transactionproperty GUCs, as GUC_NO_RESET.We have to disallow GUC_ACTION_SAVE as well as straight RESET, becauseotherwise a function having a "SET transaction_isolation" clause canstill break things: the end-of-function restore action is equivalentto a RESET.No back-patch, as it's conceivable that someone is doing somethingthis patch will forbid (like resetting one of these GUCs at transactionstart, or "CREATE FUNCTION ... SET transaction_read_only = 1") and notrunning into problems with it today. Given how long we've had thisissue and not noticed, the side effects in non-assert builds can't betoo serious.Per bug #17385 from Andrew Bille.Masahiko SawadaDiscussion:https://postgr.es/m/17385-9ee529fb091f0ce5@postgresql.org
1 parent4148c8b commit3853664

File tree

11 files changed

+103
-13
lines changed

11 files changed

+103
-13
lines changed

‎doc/src/sgml/func.sgml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24353,6 +24353,12 @@ SELECT collation for ('foo' COLLATE "de_DE");
2435324353
<command>SHOW ALL</command> commands.
2435424354
</entry>
2435524355
</row>
24356+
<row>
24357+
<entry><literal>NO_RESET</literal></entry>
24358+
<entry>Parameters with this flag do not support
24359+
<command>RESET</command> commands.
24360+
</entry>
24361+
</row>
2435624362
<row>
2435724363
<entry><literal>NO_RESET_ALL</literal></entry>
2435824364
<entry>Parameters with this flag are excluded from

‎src/backend/utils/misc/guc.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3243,6 +3243,26 @@ set_config_option_ext(const char *name, const char *value,
32433243
}
32443244
}
32453245

3246+
/* Disallow resetting and saving GUC_NO_RESET values */
3247+
if (record->flags&GUC_NO_RESET)
3248+
{
3249+
if (value==NULL)
3250+
{
3251+
ereport(elevel,
3252+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3253+
errmsg("parameter \"%s\" cannot be reset",name)));
3254+
return0;
3255+
}
3256+
if (action==GUC_ACTION_SAVE)
3257+
{
3258+
ereport(elevel,
3259+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3260+
errmsg("parameter \"%s\" cannot be set locally in functions",
3261+
name)));
3262+
return0;
3263+
}
3264+
}
3265+
32463266
/*
32473267
* Should we set reset/stacked values?(If so, the behavior is not
32483268
* transactional.)This is done either when we get a default value from

‎src/backend/utils/misc/guc_funcs.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -141,9 +141,6 @@ ExecSetVariableStmt(VariableSetStmt *stmt, bool isTopLevel)
141141
WarnNoTransactionBlock(isTopLevel,"SET LOCAL");
142142
/* fall through */
143143
caseVAR_RESET:
144-
if (strcmp(stmt->name,"transaction_isolation")==0)
145-
WarnNoTransactionBlock(isTopLevel,"RESET TRANSACTION");
146-
147144
(void)set_config_option(stmt->name,
148145
NULL,
149146
(superuser() ?PGC_SUSET :PGC_USERSET),
@@ -539,7 +536,7 @@ ShowAllGUCConfig(DestReceiver *dest)
539536
Datum
540537
pg_settings_get_flags(PG_FUNCTION_ARGS)
541538
{
542-
#defineMAX_GUC_FLAGS5
539+
#defineMAX_GUC_FLAGS6
543540
char*varname=TextDatumGetCString(PG_GETARG_DATUM(0));
544541
structconfig_generic*record;
545542
intcnt=0;
@@ -554,6 +551,8 @@ pg_settings_get_flags(PG_FUNCTION_ARGS)
554551

555552
if (record->flags&GUC_EXPLAIN)
556553
flags[cnt++]=CStringGetTextDatum("EXPLAIN");
554+
if (record->flags&GUC_NO_RESET)
555+
flags[cnt++]=CStringGetTextDatum("NO_RESET");
557556
if (record->flags&GUC_NO_RESET_ALL)
558557
flags[cnt++]=CStringGetTextDatum("NO_RESET_ALL");
559558
if (record->flags&GUC_NO_SHOW_ALL)

‎src/backend/utils/misc/guc_tables.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1505,7 +1505,7 @@ struct config_bool ConfigureNamesBool[] =
15051505
{"transaction_read_only",PGC_USERSET,CLIENT_CONN_STATEMENT,
15061506
gettext_noop("Sets the current transaction's read-only status."),
15071507
NULL,
1508-
GUC_NO_RESET_ALL |GUC_NOT_IN_SAMPLE |GUC_DISALLOW_IN_FILE
1508+
GUC_NO_RESET |GUC_NO_RESET_ALL |GUC_NOT_IN_SAMPLE |GUC_DISALLOW_IN_FILE
15091509
},
15101510
&XactReadOnly,
15111511
false,
@@ -1524,7 +1524,7 @@ struct config_bool ConfigureNamesBool[] =
15241524
{"transaction_deferrable",PGC_USERSET,CLIENT_CONN_STATEMENT,
15251525
gettext_noop("Whether to defer a read-only serializable transaction until it can be executed with no possible serialization failures."),
15261526
NULL,
1527-
GUC_NO_RESET_ALL |GUC_NOT_IN_SAMPLE |GUC_DISALLOW_IN_FILE
1527+
GUC_NO_RESET |GUC_NO_RESET_ALL |GUC_NOT_IN_SAMPLE |GUC_DISALLOW_IN_FILE
15281528
},
15291529
&XactDeferrable,
15301530
false,
@@ -3606,7 +3606,7 @@ struct config_real ConfigureNamesReal[] =
36063606
{"seed",PGC_USERSET,UNGROUPED,
36073607
gettext_noop("Sets the seed for random-number generation."),
36083608
NULL,
3609-
GUC_NO_SHOW_ALL |GUC_NO_RESET_ALL |GUC_NOT_IN_SAMPLE |GUC_DISALLOW_IN_FILE
3609+
GUC_NO_SHOW_ALL |GUC_NO_RESET |GUC_NO_RESET_ALL |GUC_NOT_IN_SAMPLE |GUC_DISALLOW_IN_FILE
36103610
},
36113611
&phony_random_seed,
36123612
0.0,-1.0,1.0,
@@ -4557,7 +4557,7 @@ struct config_enum ConfigureNamesEnum[] =
45574557
{"transaction_isolation",PGC_USERSET,CLIENT_CONN_STATEMENT,
45584558
gettext_noop("Sets the current transaction's isolation level."),
45594559
NULL,
4560-
GUC_NO_RESET_ALL |GUC_NOT_IN_SAMPLE |GUC_DISALLOW_IN_FILE
4560+
GUC_NO_RESET |GUC_NO_RESET_ALL |GUC_NOT_IN_SAMPLE |GUC_DISALLOW_IN_FILE
45614561
},
45624562
&XactIsoLevel,
45634563
XACT_READ_COMMITTED,isolation_level_options,

‎src/include/utils/guc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@ typedef enum
207207
#defineGUC_LIST_INPUT0x0001/* input can be list format */
208208
#defineGUC_LIST_QUOTE0x0002/* double-quote list elements */
209209
#defineGUC_NO_SHOW_ALL0x0004/* exclude from SHOW ALL */
210+
#defineGUC_NO_RESET 0x400000/* disallow RESET and SAVE */
210211
#defineGUC_NO_RESET_ALL0x0008/* exclude from RESET ALL */
211212
#defineGUC_REPORT0x0010/* auto-report changes to client */
212213
#defineGUC_NOT_IN_SAMPLE0x0020/* not in postgresql.conf.sample */

‎src/pl/plpgsql/src/expected/plpgsql_transaction.out

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -576,16 +576,15 @@ BEGIN
576576
PERFORM 1;
577577
RAISE INFO '%', current_setting('transaction_isolation');
578578
COMMIT;
579-
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
580-
RESET TRANSACTION ISOLATION LEVEL;
579+
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
581580
PERFORM 1;
582581
RAISE INFO '%', current_setting('transaction_isolation');
583582
COMMIT;
584583
END;
585584
$$;
586585
INFO: read committed
587586
INFO: repeatable read
588-
INFO:read committed
587+
INFO:serializable
589588
-- error cases
590589
DO LANGUAGE plpgsql $$
591590
BEGIN

‎src/pl/plpgsql/src/sql/plpgsql_transaction.sql

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -481,8 +481,7 @@ BEGIN
481481
PERFORM1;
482482
RAISE INFO'%', current_setting('transaction_isolation');
483483
COMMIT;
484-
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
485-
RESET TRANSACTION ISOLATION LEVEL;
484+
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
486485
PERFORM1;
487486
RAISE INFO'%', current_setting('transaction_isolation');
488487
COMMIT;

‎src/test/regress/expected/guc.out

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -839,6 +839,7 @@ SELECT pg_settings_get_flags('does_not_exist');
839839

840840
CREATE TABLE tab_settings_flags AS SELECT name, category,
841841
'EXPLAIN' = ANY(flags) AS explain,
842+
'NO_RESET' = ANY(flags) AS no_reset,
842843
'NO_RESET_ALL' = ANY(flags) AS no_reset_all,
843844
'NO_SHOW_ALL' = ANY(flags) AS no_show_all,
844845
'NOT_IN_SAMPLE' = ANY(flags) AS not_in_sample,
@@ -906,4 +907,12 @@ SELECT name FROM tab_settings_flags
906907
------
907908
(0 rows)
908909

910+
-- NO_RESET implies NO_RESET_ALL.
911+
SELECT name FROM tab_settings_flags
912+
WHERE no_reset AND NOT no_reset_all
913+
ORDER BY 1;
914+
name
915+
------
916+
(0 rows)
917+
909918
DROP TABLE tab_settings_flags;

‎src/test/regress/expected/transactions.out

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,40 @@ SELECT * FROM xacttest;
4444
777 | 777.777
4545
(5 rows)
4646

47+
-- Test that transaction characteristics cannot be reset.
48+
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
49+
SELECT COUNT(*) FROM xacttest;
50+
count
51+
-------
52+
5
53+
(1 row)
54+
55+
RESET transaction_isolation; -- error
56+
ERROR: parameter "transaction_isolation" cannot be reset
57+
END;
58+
BEGIN TRANSACTION READ ONLY;
59+
SELECT COUNT(*) FROM xacttest;
60+
count
61+
-------
62+
5
63+
(1 row)
64+
65+
RESET transaction_read_only; -- error
66+
ERROR: parameter "transaction_read_only" cannot be reset
67+
END;
68+
BEGIN TRANSACTION DEFERRABLE;
69+
SELECT COUNT(*) FROM xacttest;
70+
count
71+
-------
72+
5
73+
(1 row)
74+
75+
RESET transaction_deferrable; -- error
76+
ERROR: parameter "transaction_deferrable" cannot be reset
77+
END;
78+
CREATE FUNCTION errfunc() RETURNS int LANGUAGE SQL AS 'SELECT 1'
79+
SET transaction_read_only = on; -- error
80+
ERROR: parameter "transaction_read_only" cannot be set locally in functions
4781
-- Read-only tests
4882
CREATE TABLE writetest (a int);
4983
CREATE TEMPORARY TABLE temptest (a int);

‎src/test/regress/sql/guc.sql

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,7 @@ SELECT pg_settings_get_flags(NULL);
324324
SELECT pg_settings_get_flags('does_not_exist');
325325
CREATETABLEtab_settings_flagsASSELECT name, category,
326326
'EXPLAIN'= ANY(flags)AS explain,
327+
'NO_RESET'= ANY(flags)AS no_reset,
327328
'NO_RESET_ALL'= ANY(flags)AS no_reset_all,
328329
'NO_SHOW_ALL'= ANY(flags)AS no_show_all,
329330
'NOT_IN_SAMPLE'= ANY(flags)AS not_in_sample,
@@ -360,4 +361,8 @@ SELECT name FROM tab_settings_flags
360361
SELECT nameFROM tab_settings_flags
361362
WHERE no_show_allAND NOT not_in_sample
362363
ORDER BY1;
364+
-- NO_RESET implies NO_RESET_ALL.
365+
SELECT nameFROM tab_settings_flags
366+
WHERE no_resetAND NOT no_reset_all
367+
ORDER BY1;
363368
DROPTABLE tab_settings_flags;

‎src/test/regress/sql/transactions.sql

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,24 @@ SELECT oid FROM pg_class WHERE relname = 'disappear';
3535
-- should have members again
3636
SELECT*FROM xacttest;
3737

38+
-- Test that transaction characteristics cannot be reset.
39+
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
40+
SELECTCOUNT(*)FROM xacttest;
41+
RESET transaction_isolation;-- error
42+
END;
43+
44+
BEGIN TRANSACTION READ ONLY;
45+
SELECTCOUNT(*)FROM xacttest;
46+
RESET transaction_read_only;-- error
47+
END;
48+
49+
BEGIN TRANSACTION DEFERRABLE;
50+
SELECTCOUNT(*)FROM xacttest;
51+
RESET transaction_deferrable;-- error
52+
END;
53+
54+
CREATEFUNCTIONerrfunc() RETURNSint LANGUAGE SQLAS'SELECT 1'
55+
SET transaction_read_only=on;-- error
3856

3957
-- Read-only tests
4058

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp