Force a checkpoint in CREATE DATABASE before starting to copy the files,
[PostgreSQL.git] / src / backend / commands / variable.c
blobdbe2172f852b8e49e80619e0b13e5b41fc72ca54
1 /*-------------------------------------------------------------------------
3 * variable.c
4 * Routines for handling specialized SET variables.
7 * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
8 * Portions Copyright (c) 1994, Regents of the University of California
11 * IDENTIFICATION
12 * $PostgreSQL$
14 *-------------------------------------------------------------------------
17 #include "postgres.h"
19 #include <ctype.h>
21 #include "access/xact.h"
22 #include "catalog/pg_authid.h"
23 #include "commands/variable.h"
24 #include "miscadmin.h"
25 #include "utils/acl.h"
26 #include "utils/builtins.h"
27 #include "utils/syscache.h"
28 #include "utils/snapmgr.h"
29 #include "mb/pg_wchar.h"
32 * DATESTYLE
36 * assign_datestyle: GUC assign_hook for datestyle
38 const char *
39 assign_datestyle(const char *value, bool doit, GucSource source)
41 int newDateStyle = DateStyle;
42 int newDateOrder = DateOrder;
43 bool have_style = false;
44 bool have_order = false;
45 bool ok = true;
46 char *rawstring;
47 char *result;
48 List *elemlist;
49 ListCell *l;
51 /* Need a modifiable copy of string */
52 rawstring = pstrdup(value);
54 /* Parse string into list of identifiers */
55 if (!SplitIdentifierString(rawstring, ',', &elemlist))
57 /* syntax error in list */
58 pfree(rawstring);
59 list_free(elemlist);
60 ereport(GUC_complaint_elevel(source),
61 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
62 errmsg("invalid list syntax for parameter \"datestyle\"")));
63 return NULL;
66 foreach(l, elemlist)
68 char *tok = (char *) lfirst(l);
70 /* Ugh. Somebody ought to write a table driven version -- mjl */
72 if (pg_strcasecmp(tok, "ISO") == 0)
74 if (have_style && newDateStyle != USE_ISO_DATES)
75 ok = false; /* conflicting styles */
76 newDateStyle = USE_ISO_DATES;
77 have_style = true;
79 else if (pg_strcasecmp(tok, "SQL") == 0)
81 if (have_style && newDateStyle != USE_SQL_DATES)
82 ok = false; /* conflicting styles */
83 newDateStyle = USE_SQL_DATES;
84 have_style = true;
86 else if (pg_strncasecmp(tok, "POSTGRES", 8) == 0)
88 if (have_style && newDateStyle != USE_POSTGRES_DATES)
89 ok = false; /* conflicting styles */
90 newDateStyle = USE_POSTGRES_DATES;
91 have_style = true;
93 else if (pg_strcasecmp(tok, "GERMAN") == 0)
95 if (have_style && newDateStyle != USE_GERMAN_DATES)
96 ok = false; /* conflicting styles */
97 newDateStyle = USE_GERMAN_DATES;
98 have_style = true;
99 /* GERMAN also sets DMY, unless explicitly overridden */
100 if (!have_order)
101 newDateOrder = DATEORDER_DMY;
103 else if (pg_strcasecmp(tok, "YMD") == 0)
105 if (have_order && newDateOrder != DATEORDER_YMD)
106 ok = false; /* conflicting orders */
107 newDateOrder = DATEORDER_YMD;
108 have_order = true;
110 else if (pg_strcasecmp(tok, "DMY") == 0 ||
111 pg_strncasecmp(tok, "EURO", 4) == 0)
113 if (have_order && newDateOrder != DATEORDER_DMY)
114 ok = false; /* conflicting orders */
115 newDateOrder = DATEORDER_DMY;
116 have_order = true;
118 else if (pg_strcasecmp(tok, "MDY") == 0 ||
119 pg_strcasecmp(tok, "US") == 0 ||
120 pg_strncasecmp(tok, "NONEURO", 7) == 0)
122 if (have_order && newDateOrder != DATEORDER_MDY)
123 ok = false; /* conflicting orders */
124 newDateOrder = DATEORDER_MDY;
125 have_order = true;
127 else if (pg_strcasecmp(tok, "DEFAULT") == 0)
130 * Easiest way to get the current DEFAULT state is to fetch the
131 * DEFAULT string from guc.c and recursively parse it.
133 * We can't simply "return assign_datestyle(...)" because we need
134 * to handle constructs like "DEFAULT, ISO".
136 int saveDateStyle = DateStyle;
137 int saveDateOrder = DateOrder;
138 const char *subval;
140 subval = assign_datestyle(GetConfigOptionResetString("datestyle"),
141 true, source);
142 if (!have_style)
143 newDateStyle = DateStyle;
144 if (!have_order)
145 newDateOrder = DateOrder;
146 DateStyle = saveDateStyle;
147 DateOrder = saveDateOrder;
148 if (!subval)
150 ok = false;
151 break;
153 /* Here we know that our own return value is always malloc'd */
154 /* when doit is true */
155 free((char *) subval);
157 else
159 ereport(GUC_complaint_elevel(source),
160 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
161 errmsg("unrecognized \"datestyle\" key word: \"%s\"",
162 tok)));
163 ok = false;
164 break;
168 pfree(rawstring);
169 list_free(elemlist);
171 if (!ok)
173 ereport(GUC_complaint_elevel(source),
174 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
175 errmsg("conflicting \"datestyle\" specifications")));
176 return NULL;
180 * If we aren't going to do the assignment, just return OK indicator.
182 if (!doit)
183 return value;
186 * Prepare the canonical string to return. GUC wants it malloc'd.
188 result = (char *) malloc(32);
189 if (!result)
190 return NULL;
192 switch (newDateStyle)
194 case USE_ISO_DATES:
195 strcpy(result, "ISO");
196 break;
197 case USE_SQL_DATES:
198 strcpy(result, "SQL");
199 break;
200 case USE_GERMAN_DATES:
201 strcpy(result, "German");
202 break;
203 default:
204 strcpy(result, "Postgres");
205 break;
207 switch (newDateOrder)
209 case DATEORDER_YMD:
210 strcat(result, ", YMD");
211 break;
212 case DATEORDER_DMY:
213 strcat(result, ", DMY");
214 break;
215 default:
216 strcat(result, ", MDY");
217 break;
221 * Finally, it's safe to assign to the global variables; the assignment
222 * cannot fail now.
224 DateStyle = newDateStyle;
225 DateOrder = newDateOrder;
227 return result;
232 * TIMEZONE
236 * assign_timezone: GUC assign_hook for timezone
238 const char *
239 assign_timezone(const char *value, bool doit, GucSource source)
241 char *result;
242 char *endptr;
243 double hours;
246 * Check for INTERVAL 'foo'
248 if (pg_strncasecmp(value, "interval", 8) == 0)
250 const char *valueptr = value;
251 char *val;
252 Interval *interval;
254 valueptr += 8;
255 while (isspace((unsigned char) *valueptr))
256 valueptr++;
257 if (*valueptr++ != '\'')
258 return NULL;
259 val = pstrdup(valueptr);
260 /* Check and remove trailing quote */
261 endptr = strchr(val, '\'');
262 if (!endptr || endptr[1] != '\0')
264 pfree(val);
265 return NULL;
267 *endptr = '\0';
270 * Try to parse it. XXX an invalid interval format will result in
271 * ereport(ERROR), which is not desirable for GUC. We did what we
272 * could to guard against this in flatten_set_variable_args, but a
273 * string coming in from postgresql.conf might contain anything.
275 interval = DatumGetIntervalP(DirectFunctionCall3(interval_in,
276 CStringGetDatum(val),
277 ObjectIdGetDatum(InvalidOid),
278 Int32GetDatum(-1)));
280 pfree(val);
281 if (interval->month != 0)
283 ereport(GUC_complaint_elevel(source),
284 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
285 errmsg("invalid interval value for time zone: month not allowed")));
286 pfree(interval);
287 return NULL;
289 if (interval->day != 0)
291 ereport(GUC_complaint_elevel(source),
292 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
293 errmsg("invalid interval value for time zone: day not allowed")));
294 pfree(interval);
295 return NULL;
297 if (doit)
299 /* Here we change from SQL to Unix sign convention */
300 #ifdef HAVE_INT64_TIMESTAMP
301 CTimeZone = -(interval->time / USECS_PER_SEC);
302 #else
303 CTimeZone = -interval->time;
304 #endif
306 HasCTZSet = true;
308 pfree(interval);
310 else
313 * Try it as a numeric number of hours (possibly fractional).
315 hours = strtod(value, &endptr);
316 if (endptr != value && *endptr == '\0')
318 if (doit)
320 /* Here we change from SQL to Unix sign convention */
321 CTimeZone = -hours * SECS_PER_HOUR;
322 HasCTZSet = true;
325 else if (pg_strcasecmp(value, "UNKNOWN") == 0)
328 * UNKNOWN is the value shown as the "default" for TimeZone in
329 * guc.c. We interpret it as being a complete no-op; we don't
330 * change the timezone setting. Note that if there is a known
331 * timezone setting, we will return that name rather than UNKNOWN
332 * as the canonical spelling.
334 * During GUC initialization, since the timezone library isn't set
335 * up yet, pg_get_timezone_name will return NULL and we will leave
336 * the setting as UNKNOWN. If this isn't overridden from the
337 * config file then pg_timezone_initialize() will eventually
338 * select a default value from the environment.
340 if (doit)
342 const char *curzone = pg_get_timezone_name(session_timezone);
344 if (curzone)
345 value = curzone;
348 else
351 * Otherwise assume it is a timezone name, and try to load it.
353 pg_tz *new_tz;
355 new_tz = pg_tzset(value);
357 if (!new_tz)
359 ereport(GUC_complaint_elevel(source),
360 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
361 errmsg("unrecognized time zone name: \"%s\"",
362 value)));
363 return NULL;
366 if (!tz_acceptable(new_tz))
368 ereport(GUC_complaint_elevel(source),
369 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
370 errmsg("time zone \"%s\" appears to use leap seconds",
371 value),
372 errdetail("PostgreSQL does not support leap seconds.")));
373 return NULL;
376 if (doit)
378 /* Save the changed TZ */
379 session_timezone = new_tz;
380 HasCTZSet = false;
386 * If we aren't going to do the assignment, just return OK indicator.
388 if (!doit)
389 return value;
392 * Prepare the canonical string to return. GUC wants it malloc'd.
394 if (HasCTZSet)
396 result = (char *) malloc(64);
397 if (!result)
398 return NULL;
399 snprintf(result, 64, "%.5f",
400 (double) (-CTimeZone) / (double) SECS_PER_HOUR);
402 else
403 result = strdup(value);
405 return result;
409 * show_timezone: GUC show_hook for timezone
411 const char *
412 show_timezone(void)
414 const char *tzn;
416 if (HasCTZSet)
418 Interval interval;
420 interval.month = 0;
421 interval.day = 0;
422 #ifdef HAVE_INT64_TIMESTAMP
423 interval.time = -(CTimeZone * USECS_PER_SEC);
424 #else
425 interval.time = -CTimeZone;
426 #endif
428 tzn = DatumGetCString(DirectFunctionCall1(interval_out,
429 IntervalPGetDatum(&interval)));
431 else
432 tzn = pg_get_timezone_name(session_timezone);
434 if (tzn != NULL)
435 return tzn;
437 return "unknown";
442 * LOG_TIMEZONE
444 * For log_timezone, we don't support the interval-based methods of setting a
445 * zone, which are only there for SQL spec compliance not because they're
446 * actually useful.
450 * assign_log_timezone: GUC assign_hook for log_timezone
452 const char *
453 assign_log_timezone(const char *value, bool doit, GucSource source)
455 char *result;
457 if (pg_strcasecmp(value, "UNKNOWN") == 0)
460 * UNKNOWN is the value shown as the "default" for log_timezone in
461 * guc.c. We interpret it as being a complete no-op; we don't change
462 * the timezone setting. Note that if there is a known timezone
463 * setting, we will return that name rather than UNKNOWN as the
464 * canonical spelling.
466 * During GUC initialization, since the timezone library isn't set up
467 * yet, pg_get_timezone_name will return NULL and we will leave the
468 * setting as UNKNOWN. If this isn't overridden from the config file
469 * then pg_timezone_initialize() will eventually select a default
470 * value from the environment.
472 if (doit)
474 const char *curzone = pg_get_timezone_name(log_timezone);
476 if (curzone)
477 value = curzone;
480 else
483 * Otherwise assume it is a timezone name, and try to load it.
485 pg_tz *new_tz;
487 new_tz = pg_tzset(value);
489 if (!new_tz)
491 ereport(GUC_complaint_elevel(source),
492 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
493 errmsg("unrecognized time zone name: \"%s\"",
494 value)));
495 return NULL;
498 if (!tz_acceptable(new_tz))
500 ereport(GUC_complaint_elevel(source),
501 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
502 errmsg("time zone \"%s\" appears to use leap seconds",
503 value),
504 errdetail("PostgreSQL does not support leap seconds.")));
505 return NULL;
508 if (doit)
510 /* Save the changed TZ */
511 log_timezone = new_tz;
516 * If we aren't going to do the assignment, just return OK indicator.
518 if (!doit)
519 return value;
522 * Prepare the canonical string to return. GUC wants it malloc'd.
524 result = strdup(value);
526 return result;
530 * show_log_timezone: GUC show_hook for log_timezone
532 const char *
533 show_log_timezone(void)
535 const char *tzn;
537 tzn = pg_get_timezone_name(log_timezone);
539 if (tzn != NULL)
540 return tzn;
542 return "unknown";
547 * SET TRANSACTION ISOLATION LEVEL
550 const char *
551 assign_XactIsoLevel(const char *value, bool doit, GucSource source)
553 if (FirstSnapshotSet)
555 ereport(GUC_complaint_elevel(source),
556 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
557 errmsg("SET TRANSACTION ISOLATION LEVEL must be called before any query")));
558 /* source == PGC_S_OVERRIDE means do it anyway, eg at xact abort */
559 if (source != PGC_S_OVERRIDE)
560 return NULL;
562 else if (IsSubTransaction())
564 ereport(GUC_complaint_elevel(source),
565 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
566 errmsg("SET TRANSACTION ISOLATION LEVEL must not be called in a subtransaction")));
567 /* source == PGC_S_OVERRIDE means do it anyway, eg at xact abort */
568 if (source != PGC_S_OVERRIDE)
569 return NULL;
572 if (strcmp(value, "serializable") == 0)
574 if (doit)
575 XactIsoLevel = XACT_SERIALIZABLE;
577 else if (strcmp(value, "repeatable read") == 0)
579 if (doit)
580 XactIsoLevel = XACT_REPEATABLE_READ;
582 else if (strcmp(value, "read committed") == 0)
584 if (doit)
585 XactIsoLevel = XACT_READ_COMMITTED;
587 else if (strcmp(value, "read uncommitted") == 0)
589 if (doit)
590 XactIsoLevel = XACT_READ_UNCOMMITTED;
592 else if (strcmp(value, "default") == 0)
594 if (doit)
595 XactIsoLevel = DefaultXactIsoLevel;
597 else
598 return NULL;
600 return value;
603 const char *
604 show_XactIsoLevel(void)
606 switch (XactIsoLevel)
608 case XACT_READ_UNCOMMITTED:
609 return "read uncommitted";
610 case XACT_READ_COMMITTED:
611 return "read committed";
612 case XACT_REPEATABLE_READ:
613 return "repeatable read";
614 case XACT_SERIALIZABLE:
615 return "serializable";
616 default:
617 return "bogus";
623 * Random number seed
626 bool
627 assign_random_seed(double value, bool doit, GucSource source)
629 /* Can't really roll back on error, so ignore non-interactive setting */
630 if (doit && source >= PGC_S_INTERACTIVE)
631 DirectFunctionCall1(setseed, Float8GetDatum(value));
632 return true;
635 const char *
636 show_random_seed(void)
638 return "unavailable";
643 * encoding handling functions
646 const char *
647 assign_client_encoding(const char *value, bool doit, GucSource source)
649 int encoding;
651 encoding = pg_valid_client_encoding(value);
652 if (encoding < 0)
653 return NULL;
656 * Note: if we are in startup phase then SetClientEncoding may not be able
657 * to really set the encoding. In this case we will assume that the
658 * encoding is okay, and InitializeClientEncoding() will fix things once
659 * initialization is complete.
661 if (SetClientEncoding(encoding, doit) < 0)
663 ereport(GUC_complaint_elevel(source),
664 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
665 errmsg("conversion between %s and %s is not supported",
666 value, GetDatabaseEncodingName())));
667 return NULL;
669 return value;
674 * SET SESSION AUTHORIZATION
676 * When resetting session auth after an error, we can't expect to do catalog
677 * lookups. Hence, the stored form of the value must provide a numeric oid
678 * that can be re-used directly. We store the string in the form of
679 * NAMEDATALEN 'x's, followed by T or F to indicate superuserness, followed
680 * by the numeric oid, followed by a comma, followed by the role name.
681 * This cannot be confused with a plain role name because of the NAMEDATALEN
682 * limit on names, so we can tell whether we're being passed an initial
683 * role name or a saved/restored value. (NOTE: we rely on guc.c to have
684 * properly truncated any incoming value, but not to truncate already-stored
685 * values. See GUC_IS_NAME processing.)
687 extern char *session_authorization_string; /* in guc.c */
689 const char *
690 assign_session_authorization(const char *value, bool doit, GucSource source)
692 Oid roleid = InvalidOid;
693 bool is_superuser = false;
694 const char *actual_rolename = NULL;
695 char *result;
697 if (strspn(value, "x") == NAMEDATALEN &&
698 (value[NAMEDATALEN] == 'T' || value[NAMEDATALEN] == 'F'))
700 /* might be a saved userid string */
701 Oid savedoid;
702 char *endptr;
704 savedoid = (Oid) strtoul(value + NAMEDATALEN + 1, &endptr, 10);
706 if (endptr != value + NAMEDATALEN + 1 && *endptr == ',')
708 /* syntactically valid, so break out the data */
709 roleid = savedoid;
710 is_superuser = (value[NAMEDATALEN] == 'T');
711 actual_rolename = endptr + 1;
715 if (roleid == InvalidOid)
717 /* not a saved ID, so look it up */
718 HeapTuple roleTup;
720 if (InSecurityDefinerContext())
723 * Disallow SET SESSION AUTHORIZATION inside a security definer
724 * context. We need to do this because when we exit the context,
725 * GUC won't be notified, leaving things out of sync. Note that
726 * this test is positioned so that restoring a previously saved
727 * setting isn't prevented.
729 ereport(GUC_complaint_elevel(source),
730 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
731 errmsg("cannot set session authorization within security-definer function")));
732 return NULL;
735 if (!IsTransactionState())
738 * Can't do catalog lookups, so fail. The upshot of this is that
739 * session_authorization cannot be set in postgresql.conf, which
740 * seems like a good thing anyway.
742 return NULL;
745 roleTup = SearchSysCache(AUTHNAME,
746 PointerGetDatum(value),
747 0, 0, 0);
748 if (!HeapTupleIsValid(roleTup))
750 ereport(GUC_complaint_elevel(source),
751 (errcode(ERRCODE_UNDEFINED_OBJECT),
752 errmsg("role \"%s\" does not exist", value)));
753 return NULL;
756 roleid = HeapTupleGetOid(roleTup);
757 is_superuser = ((Form_pg_authid) GETSTRUCT(roleTup))->rolsuper;
758 actual_rolename = value;
760 ReleaseSysCache(roleTup);
763 if (doit)
764 SetSessionAuthorization(roleid, is_superuser);
766 result = (char *) malloc(NAMEDATALEN + 32 + strlen(actual_rolename));
767 if (!result)
768 return NULL;
770 memset(result, 'x', NAMEDATALEN);
772 sprintf(result + NAMEDATALEN, "%c%u,%s",
773 is_superuser ? 'T' : 'F',
774 roleid,
775 actual_rolename);
777 return result;
780 const char *
781 show_session_authorization(void)
784 * Extract the user name from the stored string; see
785 * assign_session_authorization
787 const char *value = session_authorization_string;
788 Oid savedoid;
789 char *endptr;
791 Assert(strspn(value, "x") == NAMEDATALEN &&
792 (value[NAMEDATALEN] == 'T' || value[NAMEDATALEN] == 'F'));
794 savedoid = (Oid) strtoul(value + NAMEDATALEN + 1, &endptr, 10);
796 Assert(endptr != value + NAMEDATALEN + 1 && *endptr == ',');
798 return endptr + 1;
803 * SET ROLE
805 * When resetting session auth after an error, we can't expect to do catalog
806 * lookups. Hence, the stored form of the value must provide a numeric oid
807 * that can be re-used directly. We implement this exactly like SET
808 * SESSION AUTHORIZATION.
810 * The SQL spec requires "SET ROLE NONE" to unset the role, so we hardwire
811 * a translation of "none" to InvalidOid.
813 extern char *role_string; /* in guc.c */
815 const char *
816 assign_role(const char *value, bool doit, GucSource source)
818 Oid roleid = InvalidOid;
819 bool is_superuser = false;
820 const char *actual_rolename = value;
821 char *result;
823 if (strspn(value, "x") == NAMEDATALEN &&
824 (value[NAMEDATALEN] == 'T' || value[NAMEDATALEN] == 'F'))
826 /* might be a saved userid string */
827 Oid savedoid;
828 char *endptr;
830 savedoid = (Oid) strtoul(value + NAMEDATALEN + 1, &endptr, 10);
832 if (endptr != value + NAMEDATALEN + 1 && *endptr == ',')
834 /* syntactically valid, so break out the data */
835 roleid = savedoid;
836 is_superuser = (value[NAMEDATALEN] == 'T');
837 actual_rolename = endptr + 1;
841 if (roleid == InvalidOid && InSecurityDefinerContext())
844 * Disallow SET ROLE inside a security definer context. We need to do
845 * this because when we exit the context, GUC won't be notified,
846 * leaving things out of sync. Note that this test is arranged so
847 * that restoring a previously saved setting isn't prevented.
849 * XXX it would be nice to allow this case in future, with the
850 * behavior being that the SET ROLE's effects end when the security
851 * definer context is exited.
853 ereport(GUC_complaint_elevel(source),
854 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
855 errmsg("cannot set role within security-definer function")));
856 return NULL;
859 if (roleid == InvalidOid &&
860 strcmp(actual_rolename, "none") != 0)
862 /* not a saved ID, so look it up */
863 HeapTuple roleTup;
865 if (!IsTransactionState())
868 * Can't do catalog lookups, so fail. The upshot of this is that
869 * role cannot be set in postgresql.conf, which seems like a good
870 * thing anyway.
872 return NULL;
875 roleTup = SearchSysCache(AUTHNAME,
876 PointerGetDatum(value),
877 0, 0, 0);
878 if (!HeapTupleIsValid(roleTup))
880 ereport(GUC_complaint_elevel(source),
881 (errcode(ERRCODE_UNDEFINED_OBJECT),
882 errmsg("role \"%s\" does not exist", value)));
883 return NULL;
886 roleid = HeapTupleGetOid(roleTup);
887 is_superuser = ((Form_pg_authid) GETSTRUCT(roleTup))->rolsuper;
889 ReleaseSysCache(roleTup);
892 * Verify that session user is allowed to become this role
894 if (!is_member_of_role(GetSessionUserId(), roleid))
896 ereport(GUC_complaint_elevel(source),
897 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
898 errmsg("permission denied to set role \"%s\"",
899 value)));
900 return NULL;
904 if (doit)
905 SetCurrentRoleId(roleid, is_superuser);
907 result = (char *) malloc(NAMEDATALEN + 32 + strlen(actual_rolename));
908 if (!result)
909 return NULL;
911 memset(result, 'x', NAMEDATALEN);
913 sprintf(result + NAMEDATALEN, "%c%u,%s",
914 is_superuser ? 'T' : 'F',
915 roleid,
916 actual_rolename);
918 return result;
921 const char *
922 show_role(void)
925 * Extract the role name from the stored string; see assign_role
927 const char *value = role_string;
928 Oid savedoid;
929 char *endptr;
931 /* This special case only applies if no SET ROLE has been done */
932 if (value == NULL || strcmp(value, "none") == 0)
933 return "none";
935 Assert(strspn(value, "x") == NAMEDATALEN &&
936 (value[NAMEDATALEN] == 'T' || value[NAMEDATALEN] == 'F'));
938 savedoid = (Oid) strtoul(value + NAMEDATALEN + 1, &endptr, 10);
940 Assert(endptr != value + NAMEDATALEN + 1 && *endptr == ',');
943 * Check that the stored string still matches the effective setting, else
944 * return "none". This is a kluge to deal with the fact that SET SESSION
945 * AUTHORIZATION logically resets SET ROLE to NONE, but we cannot set the
946 * GUC role variable from assign_session_authorization (because we haven't
947 * got enough info to call set_config_option).
949 if (savedoid != GetCurrentRoleId())
950 return "none";
952 return endptr + 1;