1 /*-------------------------------------------------------------------------
4 * Routines for handling specialized SET variables.
7 * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
8 * Portions Copyright (c) 1994, Regents of the University of California
12 * src/backend/commands/variable.c
14 *-------------------------------------------------------------------------
21 #include "access/htup_details.h"
22 #include "access/parallel.h"
23 #include "access/xact.h"
24 #include "access/xlog.h"
25 #include "catalog/pg_authid.h"
26 #include "commands/variable.h"
27 #include "mb/pg_wchar.h"
28 #include "miscadmin.h"
29 #include "utils/acl.h"
30 #include "utils/builtins.h"
31 #include "utils/snapmgr.h"
32 #include "utils/syscache.h"
33 #include "utils/timestamp.h"
34 #include "utils/varlena.h"
41 * check_datestyle: GUC check_hook for datestyle
44 check_datestyle(char **newval
, void **extra
, GucSource source
)
46 int newDateStyle
= DateStyle
;
47 int newDateOrder
= DateOrder
;
48 bool have_style
= false;
49 bool have_order
= false;
57 /* Need a modifiable copy of string */
58 rawstring
= pstrdup(*newval
);
60 /* Parse string into list of identifiers */
61 if (!SplitIdentifierString(rawstring
, ',', &elemlist
))
63 /* syntax error in list */
64 GUC_check_errdetail("List syntax is invalid.");
72 char *tok
= (char *) lfirst(l
);
74 /* Ugh. Somebody ought to write a table driven version -- mjl */
76 if (pg_strcasecmp(tok
, "ISO") == 0)
78 if (have_style
&& newDateStyle
!= USE_ISO_DATES
)
79 ok
= false; /* conflicting styles */
80 newDateStyle
= USE_ISO_DATES
;
83 else if (pg_strcasecmp(tok
, "SQL") == 0)
85 if (have_style
&& newDateStyle
!= USE_SQL_DATES
)
86 ok
= false; /* conflicting styles */
87 newDateStyle
= USE_SQL_DATES
;
90 else if (pg_strncasecmp(tok
, "POSTGRES", 8) == 0)
92 if (have_style
&& newDateStyle
!= USE_POSTGRES_DATES
)
93 ok
= false; /* conflicting styles */
94 newDateStyle
= USE_POSTGRES_DATES
;
97 else if (pg_strcasecmp(tok
, "GERMAN") == 0)
99 if (have_style
&& newDateStyle
!= USE_GERMAN_DATES
)
100 ok
= false; /* conflicting styles */
101 newDateStyle
= USE_GERMAN_DATES
;
103 /* GERMAN also sets DMY, unless explicitly overridden */
105 newDateOrder
= DATEORDER_DMY
;
107 else if (pg_strcasecmp(tok
, "YMD") == 0)
109 if (have_order
&& newDateOrder
!= DATEORDER_YMD
)
110 ok
= false; /* conflicting orders */
111 newDateOrder
= DATEORDER_YMD
;
114 else if (pg_strcasecmp(tok
, "DMY") == 0 ||
115 pg_strncasecmp(tok
, "EURO", 4) == 0)
117 if (have_order
&& newDateOrder
!= DATEORDER_DMY
)
118 ok
= false; /* conflicting orders */
119 newDateOrder
= DATEORDER_DMY
;
122 else if (pg_strcasecmp(tok
, "MDY") == 0 ||
123 pg_strcasecmp(tok
, "US") == 0 ||
124 pg_strncasecmp(tok
, "NONEURO", 7) == 0)
126 if (have_order
&& newDateOrder
!= DATEORDER_MDY
)
127 ok
= false; /* conflicting orders */
128 newDateOrder
= DATEORDER_MDY
;
131 else if (pg_strcasecmp(tok
, "DEFAULT") == 0)
134 * Easiest way to get the current DEFAULT state is to fetch the
135 * DEFAULT string from guc.c and recursively parse it.
137 * We can't simply "return check_datestyle(...)" because we need
138 * to handle constructs like "DEFAULT, ISO".
141 void *subextra
= NULL
;
143 subval
= strdup(GetConfigOptionResetString("datestyle"));
149 if (!check_datestyle(&subval
, &subextra
, source
))
155 myextra
= (int *) subextra
;
157 newDateStyle
= myextra
[0];
159 newDateOrder
= myextra
[1];
165 GUC_check_errdetail("Unrecognized key word: \"%s\".", tok
);
177 GUC_check_errdetail("Conflicting \"datestyle\" specifications.");
182 * Prepare the canonical string to return. GUC wants it malloc'd.
184 result
= (char *) malloc(32);
188 switch (newDateStyle
)
191 strcpy(result
, "ISO");
194 strcpy(result
, "SQL");
196 case USE_GERMAN_DATES
:
197 strcpy(result
, "German");
200 strcpy(result
, "Postgres");
203 switch (newDateOrder
)
206 strcat(result
, ", YMD");
209 strcat(result
, ", DMY");
212 strcat(result
, ", MDY");
220 * Set up the "extra" struct actually used by assign_datestyle.
222 myextra
= (int *) malloc(2 * sizeof(int));
225 myextra
[0] = newDateStyle
;
226 myextra
[1] = newDateOrder
;
227 *extra
= (void *) myextra
;
233 * assign_datestyle: GUC assign_hook for datestyle
236 assign_datestyle(const char *newval
, void *extra
)
238 int *myextra
= (int *) extra
;
240 DateStyle
= myextra
[0];
241 DateOrder
= myextra
[1];
250 * check_timezone: GUC check_hook for timezone
253 check_timezone(char **newval
, void **extra
, GucSource source
)
260 if (pg_strncasecmp(*newval
, "interval", 8) == 0)
263 * Support INTERVAL 'foo'. This is for SQL spec compliance, not
264 * because it has any actual real-world usefulness.
266 const char *valueptr
= *newval
;
271 while (isspace((unsigned char) *valueptr
))
273 if (*valueptr
++ != '\'')
275 val
= pstrdup(valueptr
);
276 /* Check and remove trailing quote */
277 endptr
= strchr(val
, '\'');
278 if (!endptr
|| endptr
[1] != '\0')
286 * Try to parse it. XXX an invalid interval format will result in
287 * ereport(ERROR), which is not desirable for GUC. We did what we
288 * could to guard against this in flatten_set_variable_args, but a
289 * string coming in from postgresql.conf might contain anything.
291 interval
= DatumGetIntervalP(DirectFunctionCall3(interval_in
,
292 CStringGetDatum(val
),
293 ObjectIdGetDatum(InvalidOid
),
297 if (interval
->month
!= 0)
299 GUC_check_errdetail("Cannot specify months in time zone interval.");
303 if (interval
->day
!= 0)
305 GUC_check_errdetail("Cannot specify days in time zone interval.");
310 /* Here we change from SQL to Unix sign convention */
311 gmtoffset
= -(interval
->time
/ USECS_PER_SEC
);
312 new_tz
= pg_tzset_offset(gmtoffset
);
319 * Try it as a numeric number of hours (possibly fractional).
321 hours
= strtod(*newval
, &endptr
);
322 if (endptr
!= *newval
&& *endptr
== '\0')
324 /* Here we change from SQL to Unix sign convention */
325 gmtoffset
= -hours
* SECS_PER_HOUR
;
326 new_tz
= pg_tzset_offset(gmtoffset
);
331 * Otherwise assume it is a timezone name, and try to load it.
333 new_tz
= pg_tzset(*newval
);
337 /* Doesn't seem to be any great value in errdetail here */
341 if (!pg_tz_acceptable(new_tz
))
343 GUC_check_errmsg("time zone \"%s\" appears to use leap seconds",
345 GUC_check_errdetail("PostgreSQL does not support leap seconds.");
351 /* Test for failure in pg_tzset_offset, which we assume is out-of-range */
354 GUC_check_errdetail("UTC timezone offset is out of range.");
359 * Pass back data for assign_timezone to use
361 *extra
= malloc(sizeof(pg_tz
*));
364 *((pg_tz
**) *extra
) = new_tz
;
370 * assign_timezone: GUC assign_hook for timezone
373 assign_timezone(const char *newval
, void *extra
)
375 session_timezone
= *((pg_tz
**) extra
);
379 * show_timezone: GUC show_hook for timezone
386 /* Always show the zone's canonical name */
387 tzn
= pg_get_timezone_name(session_timezone
);
399 * For log_timezone, we don't support the interval-based methods of setting a
400 * zone, which are only there for SQL spec compliance not because they're
405 * check_log_timezone: GUC check_hook for log_timezone
408 check_log_timezone(char **newval
, void **extra
, GucSource source
)
413 * Assume it is a timezone name, and try to load it.
415 new_tz
= pg_tzset(*newval
);
419 /* Doesn't seem to be any great value in errdetail here */
423 if (!pg_tz_acceptable(new_tz
))
425 GUC_check_errmsg("time zone \"%s\" appears to use leap seconds",
427 GUC_check_errdetail("PostgreSQL does not support leap seconds.");
432 * Pass back data for assign_log_timezone to use
434 *extra
= malloc(sizeof(pg_tz
*));
437 *((pg_tz
**) *extra
) = new_tz
;
443 * assign_log_timezone: GUC assign_hook for log_timezone
446 assign_log_timezone(const char *newval
, void *extra
)
448 log_timezone
= *((pg_tz
**) extra
);
452 * show_log_timezone: GUC show_hook for log_timezone
455 show_log_timezone(void)
459 /* Always show the zone's canonical name */
460 tzn
= pg_get_timezone_name(log_timezone
);
470 * SET TRANSACTION READ ONLY and SET TRANSACTION READ WRITE
472 * We allow idempotent changes (r/w -> r/w and r/o -> r/o) at any time, and
473 * we also always allow changes from read-write to read-only. However,
474 * read-only may be changed to read-write only when in a top-level transaction
475 * that has not yet taken an initial snapshot. Can't do it in a hot standby,
478 * If we are not in a transaction at all, just allow the change; it means
479 * nothing since XactReadOnly will be reset by the next StartTransaction().
480 * The IsTransactionState() test protects us against trying to check
481 * RecoveryInProgress() in contexts where shared memory is not accessible.
482 * (Similarly, if we're restoring state in a parallel worker, just allow
486 check_transaction_read_only(bool *newval
, void **extra
, GucSource source
)
488 if (*newval
== false && XactReadOnly
&& IsTransactionState() && !InitializingParallelWorker
)
490 /* Can't go to r/w mode inside a r/o transaction */
491 if (IsSubTransaction())
493 GUC_check_errcode(ERRCODE_ACTIVE_SQL_TRANSACTION
);
494 GUC_check_errmsg("cannot set transaction read-write mode inside a read-only transaction");
497 /* Top level transaction can't change to r/w after first snapshot. */
498 if (FirstSnapshotSet
)
500 GUC_check_errcode(ERRCODE_ACTIVE_SQL_TRANSACTION
);
501 GUC_check_errmsg("transaction read-write mode must be set before any query");
504 /* Can't go to r/w mode while recovery is still active */
505 if (RecoveryInProgress())
507 GUC_check_errcode(ERRCODE_FEATURE_NOT_SUPPORTED
);
508 GUC_check_errmsg("cannot set transaction read-write mode during recovery");
517 * SET TRANSACTION ISOLATION LEVEL
519 * We allow idempotent changes at any time, but otherwise this can only be
520 * changed in a toplevel transaction that has not yet taken a snapshot.
522 * As in check_transaction_read_only, allow it if not inside a transaction.
525 check_XactIsoLevel(int *newval
, void **extra
, GucSource source
)
527 int newXactIsoLevel
= *newval
;
529 if (newXactIsoLevel
!= XactIsoLevel
&& IsTransactionState())
531 if (FirstSnapshotSet
)
533 GUC_check_errcode(ERRCODE_ACTIVE_SQL_TRANSACTION
);
534 GUC_check_errmsg("SET TRANSACTION ISOLATION LEVEL must be called before any query");
537 /* We ignore a subtransaction setting it to the existing value. */
538 if (IsSubTransaction())
540 GUC_check_errcode(ERRCODE_ACTIVE_SQL_TRANSACTION
);
541 GUC_check_errmsg("SET TRANSACTION ISOLATION LEVEL must not be called in a subtransaction");
544 /* Can't go to serializable mode while recovery is still active */
545 if (newXactIsoLevel
== XACT_SERIALIZABLE
&& RecoveryInProgress())
547 GUC_check_errcode(ERRCODE_FEATURE_NOT_SUPPORTED
);
548 GUC_check_errmsg("cannot use serializable mode in a hot standby");
549 GUC_check_errhint("You can use REPEATABLE READ instead.");
558 * SET TRANSACTION [NOT] DEFERRABLE
562 check_transaction_deferrable(bool *newval
, void **extra
, GucSource source
)
564 if (IsSubTransaction())
566 GUC_check_errcode(ERRCODE_ACTIVE_SQL_TRANSACTION
);
567 GUC_check_errmsg("SET TRANSACTION [NOT] DEFERRABLE cannot be called within a subtransaction");
570 if (FirstSnapshotSet
)
572 GUC_check_errcode(ERRCODE_ACTIVE_SQL_TRANSACTION
);
573 GUC_check_errmsg("SET TRANSACTION [NOT] DEFERRABLE must be called before any query");
583 * We can't roll back the random sequence on error, and we don't want
584 * config file reloads to affect it, so we only want interactive SET SEED
585 * commands to set it. We use the "extra" storage to ensure that rollbacks
586 * don't try to do the operation again.
590 check_random_seed(double *newval
, void **extra
, GucSource source
)
592 *extra
= malloc(sizeof(int));
595 /* Arm the assign only if source of value is an interactive SET */
596 *((int *) *extra
) = (source
>= PGC_S_INTERACTIVE
);
602 assign_random_seed(double newval
, void *extra
)
604 /* We'll do this at most once for any setting of the GUC variable */
605 if (*((int *) extra
))
606 DirectFunctionCall1(setseed
, Float8GetDatum(newval
));
607 *((int *) extra
) = 0;
611 show_random_seed(void)
613 return "unavailable";
618 * SET CLIENT_ENCODING
622 check_client_encoding(char **newval
, void **extra
, GucSource source
)
625 const char *canonical_name
;
627 /* Look up the encoding by name */
628 encoding
= pg_valid_client_encoding(*newval
);
632 /* Get the canonical name (no aliases, uniform case) */
633 canonical_name
= pg_encoding_to_char(encoding
);
636 * If we are not within a transaction then PrepareClientEncoding will not
637 * be able to look up the necessary conversion procs. If we are still
638 * starting up, it will return "OK" anyway, and InitializeClientEncoding
639 * will fix things once initialization is far enough along. After
640 * startup, we'll fail. This would only happen if someone tries to change
641 * client_encoding in postgresql.conf and then SIGHUP existing sessions.
642 * It seems like a bad idea for client_encoding to change that way anyhow,
643 * so we don't go out of our way to support it.
645 * Note: in the postmaster, or any other process that never calls
646 * InitializeClientEncoding, PrepareClientEncoding will always succeed,
647 * and so will SetClientEncoding; but they won't do anything, which is OK.
649 if (PrepareClientEncoding(encoding
) < 0)
651 if (IsTransactionState())
653 /* Must be a genuine no-such-conversion problem */
654 GUC_check_errcode(ERRCODE_FEATURE_NOT_SUPPORTED
);
655 GUC_check_errdetail("Conversion between %s and %s is not supported.",
657 GetDatabaseEncodingName());
661 /* Provide a useful complaint */
662 GUC_check_errdetail("Cannot change \"client_encoding\" now.");
668 * Replace the user-supplied string with the encoding's canonical name.
669 * This gets rid of aliases and case-folding variations.
671 * XXX Although canonicalizing seems like a good idea in the abstract, it
672 * breaks pre-9.1 JDBC drivers, which expect that if they send "UNICODE"
673 * as the client_encoding setting then it will read back the same way. As
674 * a workaround, don't replace the string if it's "UNICODE". Remove that
675 * hack when pre-9.1 JDBC drivers are no longer in use.
677 if (strcmp(*newval
, canonical_name
) != 0 &&
678 strcmp(*newval
, "UNICODE") != 0)
681 *newval
= strdup(canonical_name
);
687 * Save the encoding's ID in *extra, for use by assign_client_encoding.
689 *extra
= malloc(sizeof(int));
692 *((int *) *extra
) = encoding
;
698 assign_client_encoding(const char *newval
, void *extra
)
700 int encoding
= *((int *) extra
);
703 * Parallel workers send data to the leader, not the client. They always
704 * send data using the database encoding.
706 if (IsParallelWorker())
709 * During parallel worker startup, we want to accept the leader's
710 * client_encoding setting so that anyone who looks at the value in
711 * the worker sees the same value that they would see in the leader.
713 if (InitializingParallelWorker
)
717 * A change other than during startup, for example due to a SET clause
718 * attached to a function definition, should be rejected, as there is
719 * nothing we can do inside the worker to make it take effect.
722 (errcode(ERRCODE_INVALID_TRANSACTION_STATE
),
723 errmsg("cannot change client_encoding during a parallel operation")));
726 /* We do not expect an error if PrepareClientEncoding succeeded */
727 if (SetClientEncoding(encoding
) < 0)
728 elog(LOG
, "SetClientEncoding(%d) failed", encoding
);
733 * SET SESSION AUTHORIZATION
738 /* This is the "extra" state for both SESSION AUTHORIZATION and ROLE */
744 check_session_authorization(char **newval
, void **extra
, GucSource source
)
747 Form_pg_authid roleform
;
750 role_auth_extra
*myextra
;
752 /* Do nothing for the boot_val default of NULL */
756 if (!IsTransactionState())
759 * Can't do catalog lookups, so fail. The result of this is that
760 * session_authorization cannot be set in postgresql.conf, which seems
761 * like a good thing anyway, so we don't work hard to avoid it.
766 /* Look up the username */
767 roleTup
= SearchSysCache1(AUTHNAME
, PointerGetDatum(*newval
));
768 if (!HeapTupleIsValid(roleTup
))
770 GUC_check_errmsg("role \"%s\" does not exist", *newval
);
774 roleform
= (Form_pg_authid
) GETSTRUCT(roleTup
);
775 roleid
= roleform
->oid
;
776 is_superuser
= roleform
->rolsuper
;
778 ReleaseSysCache(roleTup
);
780 /* Set up "extra" struct for assign_session_authorization to use */
781 myextra
= (role_auth_extra
*) malloc(sizeof(role_auth_extra
));
784 myextra
->roleid
= roleid
;
785 myextra
->is_superuser
= is_superuser
;
786 *extra
= (void *) myextra
;
792 assign_session_authorization(const char *newval
, void *extra
)
794 role_auth_extra
*myextra
= (role_auth_extra
*) extra
;
796 /* Do nothing for the boot_val default of NULL */
800 SetSessionAuthorization(myextra
->roleid
, myextra
->is_superuser
);
807 * The SQL spec requires "SET ROLE NONE" to unset the role, so we hardwire
808 * a translation of "none" to InvalidOid. Otherwise this is much like
809 * SET SESSION AUTHORIZATION.
811 extern char *role_string
; /* in guc.c */
814 check_role(char **newval
, void **extra
, GucSource source
)
819 role_auth_extra
*myextra
;
820 Form_pg_authid roleform
;
822 if (strcmp(*newval
, "none") == 0)
824 /* hardwired translation */
826 is_superuser
= false;
830 if (!IsTransactionState())
833 * Can't do catalog lookups, so fail. The result of this is that
834 * role cannot be set in postgresql.conf, which seems like a good
835 * thing anyway, so we don't work hard to avoid it.
840 /* Look up the username */
841 roleTup
= SearchSysCache1(AUTHNAME
, PointerGetDatum(*newval
));
842 if (!HeapTupleIsValid(roleTup
))
844 GUC_check_errmsg("role \"%s\" does not exist", *newval
);
848 roleform
= (Form_pg_authid
) GETSTRUCT(roleTup
);
849 roleid
= roleform
->oid
;
850 is_superuser
= roleform
->rolsuper
;
852 ReleaseSysCache(roleTup
);
855 * Verify that session user is allowed to become this role, but skip
856 * this in parallel mode, where we must blindly recreate the parallel
859 if (!InitializingParallelWorker
&&
860 !is_member_of_role(GetSessionUserId(), roleid
))
862 GUC_check_errcode(ERRCODE_INSUFFICIENT_PRIVILEGE
);
863 GUC_check_errmsg("permission denied to set role \"%s\"",
869 /* Set up "extra" struct for assign_role to use */
870 myextra
= (role_auth_extra
*) malloc(sizeof(role_auth_extra
));
873 myextra
->roleid
= roleid
;
874 myextra
->is_superuser
= is_superuser
;
875 *extra
= (void *) myextra
;
881 assign_role(const char *newval
, void *extra
)
883 role_auth_extra
*myextra
= (role_auth_extra
*) extra
;
885 SetCurrentRoleId(myextra
->roleid
, myextra
->is_superuser
);
892 * Check whether SET ROLE is active; if not return "none". This is a
893 * kluge to deal with the fact that SET SESSION AUTHORIZATION logically
894 * resets SET ROLE to NONE, but we cannot set the GUC role variable from
895 * assign_session_authorization (because we haven't got enough info to
896 * call set_config_option).
898 if (!OidIsValid(GetCurrentRoleId()))
901 /* Otherwise we can just use the GUC string */
902 return role_string
? role_string
: "none";