PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
variable.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * variable.c
4  * Routines for handling specialized SET variables.
5  *
6  *
7  * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
8  * Portions Copyright (c) 1994, Regents of the University of California
9  *
10  *
11  * IDENTIFICATION
12  * src/backend/commands/variable.c
13  *
14  *-------------------------------------------------------------------------
15  */
16 
17 #include "postgres.h"
18 
19 #include <ctype.h>
20 
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 "miscadmin.h"
28 #include "utils/acl.h"
29 #include "utils/builtins.h"
30 #include "utils/syscache.h"
31 #include "utils/snapmgr.h"
32 #include "utils/timestamp.h"
33 #include "utils/varlena.h"
34 #include "mb/pg_wchar.h"
35 
36 /*
37  * DATESTYLE
38  */
39 
40 /*
41  * check_datestyle: GUC check_hook for datestyle
42  */
43 bool
44 check_datestyle(char **newval, void **extra, GucSource source)
45 {
46  int newDateStyle = DateStyle;
47  int newDateOrder = DateOrder;
48  bool have_style = false;
49  bool have_order = false;
50  bool ok = true;
51  char *rawstring;
52  int *myextra;
53  char *result;
54  List *elemlist;
55  ListCell *l;
56 
57  /* Need a modifiable copy of string */
58  rawstring = pstrdup(*newval);
59 
60  /* Parse string into list of identifiers */
61  if (!SplitIdentifierString(rawstring, ',', &elemlist))
62  {
63  /* syntax error in list */
64  GUC_check_errdetail("List syntax is invalid.");
65  pfree(rawstring);
66  list_free(elemlist);
67  return false;
68  }
69 
70  foreach(l, elemlist)
71  {
72  char *tok = (char *) lfirst(l);
73 
74  /* Ugh. Somebody ought to write a table driven version -- mjl */
75 
76  if (pg_strcasecmp(tok, "ISO") == 0)
77  {
78  if (have_style && newDateStyle != USE_ISO_DATES)
79  ok = false; /* conflicting styles */
80  newDateStyle = USE_ISO_DATES;
81  have_style = true;
82  }
83  else if (pg_strcasecmp(tok, "SQL") == 0)
84  {
85  if (have_style && newDateStyle != USE_SQL_DATES)
86  ok = false; /* conflicting styles */
87  newDateStyle = USE_SQL_DATES;
88  have_style = true;
89  }
90  else if (pg_strncasecmp(tok, "POSTGRES", 8) == 0)
91  {
92  if (have_style && newDateStyle != USE_POSTGRES_DATES)
93  ok = false; /* conflicting styles */
94  newDateStyle = USE_POSTGRES_DATES;
95  have_style = true;
96  }
97  else if (pg_strcasecmp(tok, "GERMAN") == 0)
98  {
99  if (have_style && newDateStyle != USE_GERMAN_DATES)
100  ok = false; /* conflicting styles */
101  newDateStyle = USE_GERMAN_DATES;
102  have_style = true;
103  /* GERMAN also sets DMY, unless explicitly overridden */
104  if (!have_order)
105  newDateOrder = DATEORDER_DMY;
106  }
107  else if (pg_strcasecmp(tok, "YMD") == 0)
108  {
109  if (have_order && newDateOrder != DATEORDER_YMD)
110  ok = false; /* conflicting orders */
111  newDateOrder = DATEORDER_YMD;
112  have_order = true;
113  }
114  else if (pg_strcasecmp(tok, "DMY") == 0 ||
115  pg_strncasecmp(tok, "EURO", 4) == 0)
116  {
117  if (have_order && newDateOrder != DATEORDER_DMY)
118  ok = false; /* conflicting orders */
119  newDateOrder = DATEORDER_DMY;
120  have_order = true;
121  }
122  else if (pg_strcasecmp(tok, "MDY") == 0 ||
123  pg_strcasecmp(tok, "US") == 0 ||
124  pg_strncasecmp(tok, "NONEURO", 7) == 0)
125  {
126  if (have_order && newDateOrder != DATEORDER_MDY)
127  ok = false; /* conflicting orders */
128  newDateOrder = DATEORDER_MDY;
129  have_order = true;
130  }
131  else if (pg_strcasecmp(tok, "DEFAULT") == 0)
132  {
133  /*
134  * Easiest way to get the current DEFAULT state is to fetch the
135  * DEFAULT string from guc.c and recursively parse it.
136  *
137  * We can't simply "return check_datestyle(...)" because we need
138  * to handle constructs like "DEFAULT, ISO".
139  */
140  char *subval;
141  void *subextra = NULL;
142 
143  subval = strdup(GetConfigOptionResetString("datestyle"));
144  if (!subval)
145  {
146  ok = false;
147  break;
148  }
149  if (!check_datestyle(&subval, &subextra, source))
150  {
151  free(subval);
152  ok = false;
153  break;
154  }
155  myextra = (int *) subextra;
156  if (!have_style)
157  newDateStyle = myextra[0];
158  if (!have_order)
159  newDateOrder = myextra[1];
160  free(subval);
161  free(subextra);
162  }
163  else
164  {
165  GUC_check_errdetail("Unrecognized key word: \"%s\".", tok);
166  pfree(rawstring);
167  list_free(elemlist);
168  return false;
169  }
170  }
171 
172  pfree(rawstring);
173  list_free(elemlist);
174 
175  if (!ok)
176  {
177  GUC_check_errdetail("Conflicting \"datestyle\" specifications.");
178  return false;
179  }
180 
181  /*
182  * Prepare the canonical string to return. GUC wants it malloc'd.
183  */
184  result = (char *) malloc(32);
185  if (!result)
186  return false;
187 
188  switch (newDateStyle)
189  {
190  case USE_ISO_DATES:
191  strcpy(result, "ISO");
192  break;
193  case USE_SQL_DATES:
194  strcpy(result, "SQL");
195  break;
196  case USE_GERMAN_DATES:
197  strcpy(result, "German");
198  break;
199  default:
200  strcpy(result, "Postgres");
201  break;
202  }
203  switch (newDateOrder)
204  {
205  case DATEORDER_YMD:
206  strcat(result, ", YMD");
207  break;
208  case DATEORDER_DMY:
209  strcat(result, ", DMY");
210  break;
211  default:
212  strcat(result, ", MDY");
213  break;
214  }
215 
216  free(*newval);
217  *newval = result;
218 
219  /*
220  * Set up the "extra" struct actually used by assign_datestyle.
221  */
222  myextra = (int *) malloc(2 * sizeof(int));
223  if (!myextra)
224  return false;
225  myextra[0] = newDateStyle;
226  myextra[1] = newDateOrder;
227  *extra = (void *) myextra;
228 
229  return true;
230 }
231 
232 /*
233  * assign_datestyle: GUC assign_hook for datestyle
234  */
235 void
236 assign_datestyle(const char *newval, void *extra)
237 {
238  int *myextra = (int *) extra;
239 
240  DateStyle = myextra[0];
241  DateOrder = myextra[1];
242 }
243 
244 
245 /*
246  * TIMEZONE
247  */
248 
249 /*
250  * check_timezone: GUC check_hook for timezone
251  */
252 bool
253 check_timezone(char **newval, void **extra, GucSource source)
254 {
255  pg_tz *new_tz;
256  long gmtoffset;
257  char *endptr;
258  double hours;
259 
260  if (pg_strncasecmp(*newval, "interval", 8) == 0)
261  {
262  /*
263  * Support INTERVAL 'foo'. This is for SQL spec compliance, not
264  * because it has any actual real-world usefulness.
265  */
266  const char *valueptr = *newval;
267  char *val;
269 
270  valueptr += 8;
271  while (isspace((unsigned char) *valueptr))
272  valueptr++;
273  if (*valueptr++ != '\'')
274  return false;
275  val = pstrdup(valueptr);
276  /* Check and remove trailing quote */
277  endptr = strchr(val, '\'');
278  if (!endptr || endptr[1] != '\0')
279  {
280  pfree(val);
281  return false;
282  }
283  *endptr = '\0';
284 
285  /*
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.
290  */
292  CStringGetDatum(val),
294  Int32GetDatum(-1)));
295 
296  pfree(val);
297  if (interval->month != 0)
298  {
299  GUC_check_errdetail("Cannot specify months in time zone interval.");
300  pfree(interval);
301  return false;
302  }
303  if (interval->day != 0)
304  {
305  GUC_check_errdetail("Cannot specify days in time zone interval.");
306  pfree(interval);
307  return false;
308  }
309 
310  /* Here we change from SQL to Unix sign convention */
311 #ifdef HAVE_INT64_TIMESTAMP
312  gmtoffset = -(interval->time / USECS_PER_SEC);
313 #else
314  gmtoffset = -interval->time;
315 #endif
316  new_tz = pg_tzset_offset(gmtoffset);
317 
318  pfree(interval);
319  }
320  else
321  {
322  /*
323  * Try it as a numeric number of hours (possibly fractional).
324  */
325  hours = strtod(*newval, &endptr);
326  if (endptr != *newval && *endptr == '\0')
327  {
328  /* Here we change from SQL to Unix sign convention */
329  gmtoffset = -hours * SECS_PER_HOUR;
330  new_tz = pg_tzset_offset(gmtoffset);
331  }
332  else
333  {
334  /*
335  * Otherwise assume it is a timezone name, and try to load it.
336  */
337  new_tz = pg_tzset(*newval);
338 
339  if (!new_tz)
340  {
341  /* Doesn't seem to be any great value in errdetail here */
342  return false;
343  }
344 
345  if (!pg_tz_acceptable(new_tz))
346  {
347  GUC_check_errmsg("time zone \"%s\" appears to use leap seconds",
348  *newval);
349  GUC_check_errdetail("PostgreSQL does not support leap seconds.");
350  return false;
351  }
352  }
353  }
354 
355  /* Test for failure in pg_tzset_offset, which we assume is out-of-range */
356  if (!new_tz)
357  {
358  GUC_check_errdetail("UTC timezone offset is out of range.");
359  return false;
360  }
361 
362  /*
363  * Pass back data for assign_timezone to use
364  */
365  *extra = malloc(sizeof(pg_tz *));
366  if (!*extra)
367  return false;
368  *((pg_tz **) *extra) = new_tz;
369 
370  return true;
371 }
372 
373 /*
374  * assign_timezone: GUC assign_hook for timezone
375  */
376 void
377 assign_timezone(const char *newval, void *extra)
378 {
379  session_timezone = *((pg_tz **) extra);
380 }
381 
382 /*
383  * show_timezone: GUC show_hook for timezone
384  */
385 const char *
387 {
388  const char *tzn;
389 
390  /* Always show the zone's canonical name */
392 
393  if (tzn != NULL)
394  return tzn;
395 
396  return "unknown";
397 }
398 
399 
400 /*
401  * LOG_TIMEZONE
402  *
403  * For log_timezone, we don't support the interval-based methods of setting a
404  * zone, which are only there for SQL spec compliance not because they're
405  * actually useful.
406  */
407 
408 /*
409  * check_log_timezone: GUC check_hook for log_timezone
410  */
411 bool
412 check_log_timezone(char **newval, void **extra, GucSource source)
413 {
414  pg_tz *new_tz;
415 
416  /*
417  * Assume it is a timezone name, and try to load it.
418  */
419  new_tz = pg_tzset(*newval);
420 
421  if (!new_tz)
422  {
423  /* Doesn't seem to be any great value in errdetail here */
424  return false;
425  }
426 
427  if (!pg_tz_acceptable(new_tz))
428  {
429  GUC_check_errmsg("time zone \"%s\" appears to use leap seconds",
430  *newval);
431  GUC_check_errdetail("PostgreSQL does not support leap seconds.");
432  return false;
433  }
434 
435  /*
436  * Pass back data for assign_log_timezone to use
437  */
438  *extra = malloc(sizeof(pg_tz *));
439  if (!*extra)
440  return false;
441  *((pg_tz **) *extra) = new_tz;
442 
443  return true;
444 }
445 
446 /*
447  * assign_log_timezone: GUC assign_hook for log_timezone
448  */
449 void
450 assign_log_timezone(const char *newval, void *extra)
451 {
452  log_timezone = *((pg_tz **) extra);
453 }
454 
455 /*
456  * show_log_timezone: GUC show_hook for log_timezone
457  */
458 const char *
460 {
461  const char *tzn;
462 
463  /* Always show the zone's canonical name */
465 
466  if (tzn != NULL)
467  return tzn;
468 
469  return "unknown";
470 }
471 
472 
473 /*
474  * SET TRANSACTION READ ONLY and SET TRANSACTION READ WRITE
475  *
476  * We allow idempotent changes (r/w -> r/w and r/o -> r/o) at any time, and
477  * we also always allow changes from read-write to read-only. However,
478  * read-only may be changed to read-write only when in a top-level transaction
479  * that has not yet taken an initial snapshot. Can't do it in a hot standby
480  * slave, either.
481  *
482  * If we are not in a transaction at all, just allow the change; it means
483  * nothing since XactReadOnly will be reset by the next StartTransaction().
484  * The IsTransactionState() test protects us against trying to check
485  * RecoveryInProgress() in contexts where shared memory is not accessible.
486  * (Similarly, if we're restoring state in a parallel worker, just allow
487  * the change.)
488  */
489 bool
490 check_transaction_read_only(bool *newval, void **extra, GucSource source)
491 {
492  if (*newval == false && XactReadOnly && IsTransactionState() && !InitializingParallelWorker)
493  {
494  /* Can't go to r/w mode inside a r/o transaction */
495  if (IsSubTransaction())
496  {
497  GUC_check_errcode(ERRCODE_ACTIVE_SQL_TRANSACTION);
498  GUC_check_errmsg("cannot set transaction read-write mode inside a read-only transaction");
499  return false;
500  }
501  /* Top level transaction can't change to r/w after first snapshot. */
502  if (FirstSnapshotSet)
503  {
504  GUC_check_errcode(ERRCODE_ACTIVE_SQL_TRANSACTION);
505  GUC_check_errmsg("transaction read-write mode must be set before any query");
506  return false;
507  }
508  /* Can't go to r/w mode while recovery is still active */
509  if (RecoveryInProgress())
510  {
511  GUC_check_errcode(ERRCODE_FEATURE_NOT_SUPPORTED);
512  GUC_check_errmsg("cannot set transaction read-write mode during recovery");
513  return false;
514  }
515  }
516 
517  return true;
518 }
519 
520 /*
521  * SET TRANSACTION ISOLATION LEVEL
522  *
523  * We allow idempotent changes at any time, but otherwise this can only be
524  * changed in a toplevel transaction that has not yet taken a snapshot.
525  *
526  * As in check_transaction_read_only, allow it if not inside a transaction.
527  */
528 bool
529 check_XactIsoLevel(char **newval, void **extra, GucSource source)
530 {
531  int newXactIsoLevel;
532 
533  if (strcmp(*newval, "serializable") == 0)
534  {
535  newXactIsoLevel = XACT_SERIALIZABLE;
536  }
537  else if (strcmp(*newval, "repeatable read") == 0)
538  {
539  newXactIsoLevel = XACT_REPEATABLE_READ;
540  }
541  else if (strcmp(*newval, "read committed") == 0)
542  {
543  newXactIsoLevel = XACT_READ_COMMITTED;
544  }
545  else if (strcmp(*newval, "read uncommitted") == 0)
546  {
547  newXactIsoLevel = XACT_READ_UNCOMMITTED;
548  }
549  else if (strcmp(*newval, "default") == 0)
550  {
551  newXactIsoLevel = DefaultXactIsoLevel;
552  }
553  else
554  return false;
555 
556  if (newXactIsoLevel != XactIsoLevel && IsTransactionState())
557  {
558  if (FirstSnapshotSet)
559  {
560  GUC_check_errcode(ERRCODE_ACTIVE_SQL_TRANSACTION);
561  GUC_check_errmsg("SET TRANSACTION ISOLATION LEVEL must be called before any query");
562  return false;
563  }
564  /* We ignore a subtransaction setting it to the existing value. */
565  if (IsSubTransaction())
566  {
567  GUC_check_errcode(ERRCODE_ACTIVE_SQL_TRANSACTION);
568  GUC_check_errmsg("SET TRANSACTION ISOLATION LEVEL must not be called in a subtransaction");
569  return false;
570  }
571  /* Can't go to serializable mode while recovery is still active */
572  if (newXactIsoLevel == XACT_SERIALIZABLE && RecoveryInProgress())
573  {
574  GUC_check_errcode(ERRCODE_FEATURE_NOT_SUPPORTED);
575  GUC_check_errmsg("cannot use serializable mode in a hot standby");
576  GUC_check_errhint("You can use REPEATABLE READ instead.");
577  return false;
578  }
579  }
580 
581  *extra = malloc(sizeof(int));
582  if (!*extra)
583  return false;
584  *((int *) *extra) = newXactIsoLevel;
585 
586  return true;
587 }
588 
589 void
590 assign_XactIsoLevel(const char *newval, void *extra)
591 {
592  XactIsoLevel = *((int *) extra);
593 }
594 
595 const char *
597 {
598  /* We need this because we don't want to show "default". */
599  switch (XactIsoLevel)
600  {
602  return "read uncommitted";
603  case XACT_READ_COMMITTED:
604  return "read committed";
606  return "repeatable read";
607  case XACT_SERIALIZABLE:
608  return "serializable";
609  default:
610  return "bogus";
611  }
612 }
613 
614 /*
615  * SET TRANSACTION [NOT] DEFERRABLE
616  */
617 
618 bool
619 check_transaction_deferrable(bool *newval, void **extra, GucSource source)
620 {
621  if (IsSubTransaction())
622  {
623  GUC_check_errcode(ERRCODE_ACTIVE_SQL_TRANSACTION);
624  GUC_check_errmsg("SET TRANSACTION [NOT] DEFERRABLE cannot be called within a subtransaction");
625  return false;
626  }
627  if (FirstSnapshotSet)
628  {
629  GUC_check_errcode(ERRCODE_ACTIVE_SQL_TRANSACTION);
630  GUC_check_errmsg("SET TRANSACTION [NOT] DEFERRABLE must be called before any query");
631  return false;
632  }
633 
634  return true;
635 }
636 
637 /*
638  * Random number seed
639  *
640  * We can't roll back the random sequence on error, and we don't want
641  * config file reloads to affect it, so we only want interactive SET SEED
642  * commands to set it. We use the "extra" storage to ensure that rollbacks
643  * don't try to do the operation again.
644  */
645 
646 bool
647 check_random_seed(double *newval, void **extra, GucSource source)
648 {
649  *extra = malloc(sizeof(int));
650  if (!*extra)
651  return false;
652  /* Arm the assign only if source of value is an interactive SET */
653  *((int *) *extra) = (source >= PGC_S_INTERACTIVE);
654 
655  return true;
656 }
657 
658 void
659 assign_random_seed(double newval, void *extra)
660 {
661  /* We'll do this at most once for any setting of the GUC variable */
662  if (*((int *) extra))
664  *((int *) extra) = 0;
665 }
666 
667 const char *
669 {
670  return "unavailable";
671 }
672 
673 
674 /*
675  * SET CLIENT_ENCODING
676  */
677 
678 bool
679 check_client_encoding(char **newval, void **extra, GucSource source)
680 {
681  int encoding;
682  const char *canonical_name;
683 
684  /* Look up the encoding by name */
685  encoding = pg_valid_client_encoding(*newval);
686  if (encoding < 0)
687  return false;
688 
689  /* Get the canonical name (no aliases, uniform case) */
690  canonical_name = pg_encoding_to_char(encoding);
691 
692  /*
693  * If we are not within a transaction then PrepareClientEncoding will not
694  * be able to look up the necessary conversion procs. If we are still
695  * starting up, it will return "OK" anyway, and InitializeClientEncoding
696  * will fix things once initialization is far enough along. After
697  * startup, we'll fail. This would only happen if someone tries to change
698  * client_encoding in postgresql.conf and then SIGHUP existing sessions.
699  * It seems like a bad idea for client_encoding to change that way anyhow,
700  * so we don't go out of our way to support it.
701  *
702  * Note: in the postmaster, or any other process that never calls
703  * InitializeClientEncoding, PrepareClientEncoding will always succeed,
704  * and so will SetClientEncoding; but they won't do anything, which is OK.
705  */
706  if (PrepareClientEncoding(encoding) < 0)
707  {
708  if (IsTransactionState())
709  {
710  /* Must be a genuine no-such-conversion problem */
711  GUC_check_errcode(ERRCODE_FEATURE_NOT_SUPPORTED);
712  GUC_check_errdetail("Conversion between %s and %s is not supported.",
713  canonical_name,
715  }
716  else
717  {
718  /* Provide a useful complaint */
719  GUC_check_errdetail("Cannot change \"client_encoding\" now.");
720  }
721  return false;
722  }
723 
724  /*
725  * Replace the user-supplied string with the encoding's canonical name.
726  * This gets rid of aliases and case-folding variations.
727  *
728  * XXX Although canonicalizing seems like a good idea in the abstract, it
729  * breaks pre-9.1 JDBC drivers, which expect that if they send "UNICODE"
730  * as the client_encoding setting then it will read back the same way. As
731  * a workaround, don't replace the string if it's "UNICODE". Remove that
732  * hack when pre-9.1 JDBC drivers are no longer in use.
733  */
734  if (strcmp(*newval, canonical_name) != 0 &&
735  strcmp(*newval, "UNICODE") != 0)
736  {
737  free(*newval);
738  *newval = strdup(canonical_name);
739  if (!*newval)
740  return false;
741  }
742 
743  /*
744  * Save the encoding's ID in *extra, for use by assign_client_encoding.
745  */
746  *extra = malloc(sizeof(int));
747  if (!*extra)
748  return false;
749  *((int *) *extra) = encoding;
750 
751  return true;
752 }
753 
754 void
755 assign_client_encoding(const char *newval, void *extra)
756 {
757  int encoding = *((int *) extra);
758 
759  /*
760  * Parallel workers send data to the leader, not the client. They always
761  * send data using the database encoding.
762  */
763  if (IsParallelWorker())
764  {
765  /*
766  * During parallel worker startup, we want to accept the leader's
767  * client_encoding setting so that anyone who looks at the value in
768  * the worker sees the same value that they would see in the leader.
769  */
771  return;
772 
773  /*
774  * A change other than during startup, for example due to a SET clause
775  * attached to a function definition, should be rejected, as there is
776  * nothing we can do inside the worker to make it take effect.
777  */
778  ereport(ERROR,
779  (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
780  errmsg("cannot change client_encoding in a parallel worker")));
781  }
782 
783  /* We do not expect an error if PrepareClientEncoding succeeded */
784  if (SetClientEncoding(encoding) < 0)
785  elog(LOG, "SetClientEncoding(%d) failed", encoding);
786 }
787 
788 
789 /*
790  * SET SESSION AUTHORIZATION
791  */
792 
793 typedef struct
794 {
795  /* This is the "extra" state for both SESSION AUTHORIZATION and ROLE */
799 
800 bool
801 check_session_authorization(char **newval, void **extra, GucSource source)
802 {
803  HeapTuple roleTup;
804  Oid roleid;
805  bool is_superuser;
806  role_auth_extra *myextra;
807 
808  /* Do nothing for the boot_val default of NULL */
809  if (*newval == NULL)
810  return true;
811 
812  if (!IsTransactionState())
813  {
814  /*
815  * Can't do catalog lookups, so fail. The result of this is that
816  * session_authorization cannot be set in postgresql.conf, which seems
817  * like a good thing anyway, so we don't work hard to avoid it.
818  */
819  return false;
820  }
821 
822  /* Look up the username */
823  roleTup = SearchSysCache1(AUTHNAME, PointerGetDatum(*newval));
824  if (!HeapTupleIsValid(roleTup))
825  {
826  GUC_check_errmsg("role \"%s\" does not exist", *newval);
827  return false;
828  }
829 
830  roleid = HeapTupleGetOid(roleTup);
831  is_superuser = ((Form_pg_authid) GETSTRUCT(roleTup))->rolsuper;
832 
833  ReleaseSysCache(roleTup);
834 
835  /* Set up "extra" struct for assign_session_authorization to use */
836  myextra = (role_auth_extra *) malloc(sizeof(role_auth_extra));
837  if (!myextra)
838  return false;
839  myextra->roleid = roleid;
840  myextra->is_superuser = is_superuser;
841  *extra = (void *) myextra;
842 
843  return true;
844 }
845 
846 void
847 assign_session_authorization(const char *newval, void *extra)
848 {
849  role_auth_extra *myextra = (role_auth_extra *) extra;
850 
851  /* Do nothing for the boot_val default of NULL */
852  if (!myextra)
853  return;
854 
855  SetSessionAuthorization(myextra->roleid, myextra->is_superuser);
856 }
857 
858 
859 /*
860  * SET ROLE
861  *
862  * The SQL spec requires "SET ROLE NONE" to unset the role, so we hardwire
863  * a translation of "none" to InvalidOid. Otherwise this is much like
864  * SET SESSION AUTHORIZATION.
865  */
866 extern char *role_string; /* in guc.c */
867 
868 bool
869 check_role(char **newval, void **extra, GucSource source)
870 {
871  HeapTuple roleTup;
872  Oid roleid;
873  bool is_superuser;
874  role_auth_extra *myextra;
875 
876  if (strcmp(*newval, "none") == 0)
877  {
878  /* hardwired translation */
879  roleid = InvalidOid;
880  is_superuser = false;
881  }
882  else
883  {
884  if (!IsTransactionState())
885  {
886  /*
887  * Can't do catalog lookups, so fail. The result of this is that
888  * role cannot be set in postgresql.conf, which seems like a good
889  * thing anyway, so we don't work hard to avoid it.
890  */
891  return false;
892  }
893 
894  /* Look up the username */
895  roleTup = SearchSysCache1(AUTHNAME, PointerGetDatum(*newval));
896  if (!HeapTupleIsValid(roleTup))
897  {
898  GUC_check_errmsg("role \"%s\" does not exist", *newval);
899  return false;
900  }
901 
902  roleid = HeapTupleGetOid(roleTup);
903  is_superuser = ((Form_pg_authid) GETSTRUCT(roleTup))->rolsuper;
904 
905  ReleaseSysCache(roleTup);
906 
907  /*
908  * Verify that session user is allowed to become this role, but skip
909  * this in parallel mode, where we must blindly recreate the parallel
910  * leader's state.
911  */
914  {
915  GUC_check_errcode(ERRCODE_INSUFFICIENT_PRIVILEGE);
916  GUC_check_errmsg("permission denied to set role \"%s\"",
917  *newval);
918  return false;
919  }
920  }
921 
922  /* Set up "extra" struct for assign_role to use */
923  myextra = (role_auth_extra *) malloc(sizeof(role_auth_extra));
924  if (!myextra)
925  return false;
926  myextra->roleid = roleid;
927  myextra->is_superuser = is_superuser;
928  *extra = (void *) myextra;
929 
930  return true;
931 }
932 
933 void
934 assign_role(const char *newval, void *extra)
935 {
936  role_auth_extra *myextra = (role_auth_extra *) extra;
937 
938  SetCurrentRoleId(myextra->roleid, myextra->is_superuser);
939 }
940 
941 const char *
943 {
944  /*
945  * Check whether SET ROLE is active; if not return "none". This is a
946  * kluge to deal with the fact that SET SESSION AUTHORIZATION logically
947  * resets SET ROLE to NONE, but we cannot set the GUC role variable from
948  * assign_session_authorization (because we haven't got enough info to
949  * call set_config_option).
950  */
952  return "none";
953 
954  /* Otherwise we can just use the GUC string */
955  return role_string ? role_string : "none";
956 }
bool check_transaction_deferrable(bool *newval, void **extra, GucSource source)
Definition: variable.c:619
void assign_timezone(const char *newval, void *extra)
Definition: variable.c:377
void assign_client_encoding(const char *newval, void *extra)
Definition: variable.c:755
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define DatumGetIntervalP(X)
Definition: timestamp.h:49
int PrepareClientEncoding(int encoding)
Definition: mbutils.c:114
bool check_random_seed(double *newval, void **extra, GucSource source)
Definition: variable.c:647
#define USECS_PER_SEC
Definition: timestamp.h:106
#define GUC_check_errdetail
Definition: guc.h:407
#define PointerGetDatum(X)
Definition: postgres.h:564
Datum interval_in(PG_FUNCTION_ARGS)
Definition: timestamp.c:934
void assign_XactIsoLevel(const char *newval, void *extra)
Definition: variable.c:590
char * pstrdup(const char *in)
Definition: mcxt.c:1165
#define XACT_REPEATABLE_READ
Definition: xact.h:30
#define XACT_READ_UNCOMMITTED
Definition: xact.h:28
int pg_valid_client_encoding(const char *name)
Definition: encnames.c:411
int errcode(int sqlerrcode)
Definition: elog.c:575
#define GUC_check_errmsg
Definition: guc.h:403
void assign_datestyle(const char *newval, void *extra)
Definition: variable.c:236
#define USE_SQL_DATES
Definition: miscadmin.h:211
bool check_transaction_read_only(bool *newval, void **extra, GucSource source)
Definition: variable.c:490
int DefaultXactIsoLevel
Definition: xact.c:73
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:555
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
bool check_timezone(char **newval, void **extra, GucSource source)
Definition: variable.c:253
#define LOG
Definition: elog.h:26
unsigned int Oid
Definition: postgres_ext.h:31
bool RecoveryInProgress(void)
Definition: xlog.c:7804
#define OidIsValid(objectId)
Definition: c.h:534
void GUC_check_errcode(int sqlerrcode)
Definition: guc.c:9730
Oid GetSessionUserId(void)
Definition: miscinit.c:317
void assign_session_authorization(const char *newval, void *extra)
Definition: variable.c:847
bool check_XactIsoLevel(char **newval, void **extra, GucSource source)
Definition: variable.c:529
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:149
#define XACT_SERIALIZABLE
Definition: xact.h:31
#define USE_ISO_DATES
Definition: miscadmin.h:210
Datum Float8GetDatum(float8 X)
Definition: fmgr.c:2126
int32 day
Definition: timestamp.h:60
GucSource
Definition: guc.h:105
pg_tz * log_timezone
Definition: pgtz.c:30
Oid GetCurrentRoleId(void)
Definition: miscinit.c:635
#define malloc(a)
Definition: header.h:45
pg_tz * pg_tzset(const char *tzname)
Definition: pgtz.c:218
FormData_pg_authid * Form_pg_authid
Definition: pg_authid.h:72
int pg_strncasecmp(const char *s1, const char *s2, size_t n)
Definition: pgstrcasecmp.c:69
void pfree(void *pointer)
Definition: mcxt.c:992
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
void SetSessionAuthorization(Oid userid, bool is_superuser)
Definition: miscinit.c:610
bool FirstSnapshotSet
Definition: snapmgr.c:203
const char * show_XactIsoLevel(void)
Definition: variable.c:596
Datum setseed(PG_FUNCTION_ARGS)
Definition: float.c:2431
const char * pg_get_timezone_name(pg_tz *tz)
Definition: localtime.c:1770
bool SplitIdentifierString(char *rawstring, char separator, List **namelist)
Definition: varlena.c:3129
#define CStringGetDatum(X)
Definition: postgres.h:586
TimeOffset time
Definition: timestamp.h:58
#define USE_POSTGRES_DATES
Definition: miscadmin.h:209
int SetClientEncoding(int encoding)
Definition: mbutils.c:212
#define ereport(elevel, rest)
Definition: elog.h:122
int DateOrder
Definition: globals.c:107
#define IsParallelWorker()
Definition: parallel.h:53
#define SECS_PER_HOUR
Definition: timestamp.h:99
pg_tz * pg_tzset_offset(long gmtoffset)
Definition: pgtz.c:304
#define DirectFunctionCall3(func, arg1, arg2, arg3)
Definition: fmgr.h:559
#define DATEORDER_YMD
Definition: miscadmin.h:216
int32 month
Definition: timestamp.h:61
const char * show_timezone(void)
Definition: variable.c:386
void assign_log_timezone(const char *newval, void *extra)
Definition: variable.c:450
const char * show_role(void)
Definition: variable.c:942
bool pg_tz_acceptable(pg_tz *tz)
Definition: localtime.c:1785
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1083
bool check_client_encoding(char **newval, void **extra, GucSource source)
Definition: variable.c:679
Definition: pgtz.h:59
bool check_session_authorization(char **newval, void **extra, GucSource source)
Definition: variable.c:801
bool check_role(char **newval, void **extra, GucSource source)
Definition: variable.c:869
bool check_datestyle(char **newval, void **extra, GucSource source)
Definition: variable.c:44
#define DATEORDER_DMY
Definition: miscadmin.h:217
#define InvalidOid
Definition: postgres_ext.h:36
#define DATEORDER_MDY
Definition: miscadmin.h:218
bool XactReadOnly
Definition: xact.c:77
bool is_superuser(void)
Definition: common.c:1985
static char * encoding
Definition: initdb.c:121
#define free(a)
Definition: header.h:60
bool is_member_of_role(Oid member, Oid role)
Definition: acl.c:4855
const char * pg_encoding_to_char(int encoding)
Definition: encnames.c:531
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:226
#define lfirst(lc)
Definition: pg_list.h:106
const char * GetDatabaseEncodingName(void)
Definition: mbutils.c:1021
#define XACT_READ_COMMITTED
Definition: xact.h:29
#define newval
int XactIsoLevel
Definition: xact.c:74
bool IsTransactionState(void)
Definition: xact.c:349
int DateStyle
Definition: globals.c:106
bool IsSubTransaction(void)
Definition: xact.c:4374
#define Int32GetDatum(X)
Definition: postgres.h:487
char * role_string
Definition: guc.c:524
#define GUC_check_errhint
Definition: guc.h:411
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define USE_GERMAN_DATES
Definition: miscadmin.h:212
void SetCurrentRoleId(Oid roleid, bool is_superuser)
Definition: miscinit.c:656
void list_free(List *list)
Definition: list.c:1133
bool InitializingParallelWorker
Definition: parallel.c:102
void assign_role(const char *newval, void *extra)
Definition: variable.c:934
pg_tz * session_timezone
Definition: pgtz.c:27
#define elog
Definition: elog.h:219
void assign_random_seed(double newval, void *extra)
Definition: variable.c:659
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:695
Definition: pg_list.h:45
long val
Definition: informix.c:689
const char * GetConfigOptionResetString(const char *name)
Definition: guc.c:6712
const char * show_random_seed(void)
Definition: variable.c:668
const char * show_log_timezone(void)
Definition: variable.c:459
bool is_superuser
Definition: variable.c:797
bool check_log_timezone(char **newval, void **extra, GucSource source)
Definition: variable.c:412