PostgreSQL Source Code  git master
misc.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * misc.c
4  *
5  *
6  * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  * src/backend/utils/adt/misc.c
12  *
13  *-------------------------------------------------------------------------
14  */
15 #include "postgres.h"
16 
17 #include <sys/file.h>
18 #include <dirent.h>
19 #include <fcntl.h>
20 #include <math.h>
21 #include <unistd.h>
22 
23 #include "access/sysattr.h"
24 #include "access/table.h"
25 #include "catalog/catalog.h"
26 #include "catalog/pg_tablespace.h"
27 #include "catalog/pg_type.h"
28 #include "catalog/system_fk_info.h"
29 #include "commands/dbcommands.h"
30 #include "commands/tablespace.h"
31 #include "common/keywords.h"
32 #include "funcapi.h"
33 #include "miscadmin.h"
34 #include "parser/scansup.h"
35 #include "pgstat.h"
36 #include "postmaster/syslogger.h"
37 #include "rewrite/rewriteHandler.h"
38 #include "storage/fd.h"
39 #include "tcop/tcopprot.h"
40 #include "utils/builtins.h"
41 #include "utils/fmgroids.h"
42 #include "utils/lsyscache.h"
43 #include "utils/ruleutils.h"
44 #include "utils/timestamp.h"
45 
46 /*
47  * Common subroutine for num_nulls() and num_nonnulls().
48  * Returns true if successful, false if function should return NULL.
49  * If successful, total argument count and number of nulls are
50  * returned into *nargs and *nulls.
51  */
52 static bool
54  int32 *nargs, int32 *nulls)
55 {
56  int32 count = 0;
57  int i;
58 
59  /* Did we get a VARIADIC array argument, or separate arguments? */
60  if (get_fn_expr_variadic(fcinfo->flinfo))
61  {
62  ArrayType *arr;
63  int ndims,
64  nitems,
65  *dims;
66  bits8 *bitmap;
67 
68  Assert(PG_NARGS() == 1);
69 
70  /*
71  * If we get a null as VARIADIC array argument, we can't say anything
72  * useful about the number of elements, so return NULL. This behavior
73  * is consistent with other variadic functions - see concat_internal.
74  */
75  if (PG_ARGISNULL(0))
76  return false;
77 
78  /*
79  * Non-null argument had better be an array. We assume that any call
80  * context that could let get_fn_expr_variadic return true will have
81  * checked that a VARIADIC-labeled parameter actually is an array. So
82  * it should be okay to just Assert that it's an array rather than
83  * doing a full-fledged error check.
84  */
86 
87  /* OK, safe to fetch the array value */
88  arr = PG_GETARG_ARRAYTYPE_P(0);
89 
90  /* Count the array elements */
91  ndims = ARR_NDIM(arr);
92  dims = ARR_DIMS(arr);
93  nitems = ArrayGetNItems(ndims, dims);
94 
95  /* Count those that are NULL */
96  bitmap = ARR_NULLBITMAP(arr);
97  if (bitmap)
98  {
99  int bitmask = 1;
100 
101  for (i = 0; i < nitems; i++)
102  {
103  if ((*bitmap & bitmask) == 0)
104  count++;
105 
106  bitmask <<= 1;
107  if (bitmask == 0x100)
108  {
109  bitmap++;
110  bitmask = 1;
111  }
112  }
113  }
114 
115  *nargs = nitems;
116  *nulls = count;
117  }
118  else
119  {
120  /* Separate arguments, so just count 'em */
121  for (i = 0; i < PG_NARGS(); i++)
122  {
123  if (PG_ARGISNULL(i))
124  count++;
125  }
126 
127  *nargs = PG_NARGS();
128  *nulls = count;
129  }
130 
131  return true;
132 }
133 
134 /*
135  * num_nulls()
136  * Count the number of NULL arguments
137  */
138 Datum
140 {
141  int32 nargs,
142  nulls;
143 
144  if (!count_nulls(fcinfo, &nargs, &nulls))
145  PG_RETURN_NULL();
146 
147  PG_RETURN_INT32(nulls);
148 }
149 
150 /*
151  * num_nonnulls()
152  * Count the number of non-NULL arguments
153  */
154 Datum
156 {
157  int32 nargs,
158  nulls;
159 
160  if (!count_nulls(fcinfo, &nargs, &nulls))
161  PG_RETURN_NULL();
162 
163  PG_RETURN_INT32(nargs - nulls);
164 }
165 
166 
167 /*
168  * current_database()
169  * Expose the current database to the user
170  */
171 Datum
173 {
174  Name db;
175 
176  db = (Name) palloc(NAMEDATALEN);
177 
179  PG_RETURN_NAME(db);
180 }
181 
182 
183 /*
184  * current_query()
185  * Expose the current query to the user (useful in stored procedures)
186  * We might want to use ActivePortal->sourceText someday.
187  */
188 Datum
190 {
191  /* there is no easy way to access the more concise 'query_string' */
192  if (debug_query_string)
194  else
195  PG_RETURN_NULL();
196 }
197 
198 /* Function to find out which databases make use of a tablespace */
199 
200 Datum
202 {
203  Oid tablespaceOid = PG_GETARG_OID(0);
204  ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
205  bool randomAccess;
206  TupleDesc tupdesc;
207  Tuplestorestate *tupstore;
208  char *location;
209  DIR *dirdesc;
210  struct dirent *de;
211  MemoryContext oldcontext;
212 
213  /* check to see if caller supports us returning a tuplestore */
214  if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
215  ereport(ERROR,
216  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
217  errmsg("set-valued function called in context that cannot accept a set")));
218  if (!(rsinfo->allowedModes & SFRM_Materialize))
219  ereport(ERROR,
220  (errcode(ERRCODE_SYNTAX_ERROR),
221  errmsg("materialize mode required, but it is not allowed in this context")));
222 
223  /* The tupdesc and tuplestore must be created in ecxt_per_query_memory */
225 
226  tupdesc = CreateTemplateTupleDesc(1);
227  TupleDescInitEntry(tupdesc, (AttrNumber) 1, "pg_tablespace_databases",
228  OIDOID, -1, 0);
229 
230  randomAccess = (rsinfo->allowedModes & SFRM_Materialize_Random) != 0;
231  tupstore = tuplestore_begin_heap(randomAccess, false, work_mem);
232 
233  rsinfo->returnMode = SFRM_Materialize;
234  rsinfo->setResult = tupstore;
235  rsinfo->setDesc = tupdesc;
236 
237  MemoryContextSwitchTo(oldcontext);
238 
239  if (tablespaceOid == GLOBALTABLESPACE_OID)
240  {
242  (errmsg("global tablespace never has databases")));
243  /* return empty tuplestore */
244  return (Datum) 0;
245  }
246 
247  if (tablespaceOid == DEFAULTTABLESPACE_OID)
248  location = psprintf("base");
249  else
250  location = psprintf("pg_tblspc/%u/%s", tablespaceOid,
252 
253  dirdesc = AllocateDir(location);
254 
255  if (!dirdesc)
256  {
257  /* the only expected error is ENOENT */
258  if (errno != ENOENT)
259  ereport(ERROR,
261  errmsg("could not open directory \"%s\": %m",
262  location)));
264  (errmsg("%u is not a tablespace OID", tablespaceOid)));
265  /* return empty tuplestore */
266  return (Datum) 0;
267  }
268 
269  while ((de = ReadDir(dirdesc, location)) != NULL)
270  {
271  Oid datOid = atooid(de->d_name);
272  char *subdir;
273  bool isempty;
274  Datum values[1];
275  bool nulls[1];
276 
277  /* this test skips . and .., but is awfully weak */
278  if (!datOid)
279  continue;
280 
281  /* if database subdir is empty, don't report tablespace as used */
282 
283  subdir = psprintf("%s/%s", location, de->d_name);
284  isempty = directory_is_empty(subdir);
285  pfree(subdir);
286 
287  if (isempty)
288  continue; /* indeed, nothing in it */
289 
290  values[0] = ObjectIdGetDatum(datOid);
291  nulls[0] = false;
292 
293  tuplestore_putvalues(tupstore, tupdesc, values, nulls);
294  }
295 
296  FreeDir(dirdesc);
297  return (Datum) 0;
298 }
299 
300 
301 /*
302  * pg_tablespace_location - get location for a tablespace
303  */
304 Datum
306 {
307  Oid tablespaceOid = PG_GETARG_OID(0);
308  char sourcepath[MAXPGPATH];
309  char targetpath[MAXPGPATH];
310  int rllen;
311 
312  /*
313  * It's useful to apply this function to pg_class.reltablespace, wherein
314  * zero means "the database's default tablespace". So, rather than
315  * throwing an error for zero, we choose to assume that's what is meant.
316  */
317  if (tablespaceOid == InvalidOid)
318  tablespaceOid = MyDatabaseTableSpace;
319 
320  /*
321  * Return empty string for the cluster's default tablespaces
322  */
323  if (tablespaceOid == DEFAULTTABLESPACE_OID ||
324  tablespaceOid == GLOBALTABLESPACE_OID)
326 
327 #if defined(HAVE_READLINK) || defined(WIN32)
328 
329  /*
330  * Find the location of the tablespace by reading the symbolic link that
331  * is in pg_tblspc/<oid>.
332  */
333  snprintf(sourcepath, sizeof(sourcepath), "pg_tblspc/%u", tablespaceOid);
334 
335  rllen = readlink(sourcepath, targetpath, sizeof(targetpath));
336  if (rllen < 0)
337  ereport(ERROR,
339  errmsg("could not read symbolic link \"%s\": %m",
340  sourcepath)));
341  if (rllen >= sizeof(targetpath))
342  ereport(ERROR,
343  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
344  errmsg("symbolic link \"%s\" target is too long",
345  sourcepath)));
346  targetpath[rllen] = '\0';
347 
348  PG_RETURN_TEXT_P(cstring_to_text(targetpath));
349 #else
350  ereport(ERROR,
351  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
352  errmsg("tablespaces are not supported on this platform")));
353  PG_RETURN_NULL();
354 #endif
355 }
356 
357 /*
358  * pg_sleep - delay for N seconds
359  */
360 Datum
362 {
363  float8 secs = PG_GETARG_FLOAT8(0);
364  float8 endtime;
365 
366  /*
367  * We sleep using WaitLatch, to ensure that we'll wake up promptly if an
368  * important signal (such as SIGALRM or SIGINT) arrives. Because
369  * WaitLatch's upper limit of delay is INT_MAX milliseconds, and the user
370  * might ask for more than that, we sleep for at most 10 minutes and then
371  * loop.
372  *
373  * By computing the intended stop time initially, we avoid accumulation of
374  * extra delay across multiple sleeps. This also ensures we won't delay
375  * less than the specified time when WaitLatch is terminated early by a
376  * non-query-canceling signal such as SIGHUP.
377  */
378 #define GetNowFloat() ((float8) GetCurrentTimestamp() / 1000000.0)
379 
380  endtime = GetNowFloat() + secs;
381 
382  for (;;)
383  {
384  float8 delay;
385  long delay_ms;
386 
388 
389  delay = endtime - GetNowFloat();
390  if (delay >= 600.0)
391  delay_ms = 600000;
392  else if (delay > 0.0)
393  delay_ms = (long) ceil(delay * 1000.0);
394  else
395  break;
396 
397  (void) WaitLatch(MyLatch,
399  delay_ms,
402  }
403 
404  PG_RETURN_VOID();
405 }
406 
407 /* Function to return the list of grammar keywords */
408 Datum
410 {
411  FuncCallContext *funcctx;
412 
413  if (SRF_IS_FIRSTCALL())
414  {
415  MemoryContext oldcontext;
416  TupleDesc tupdesc;
417 
418  funcctx = SRF_FIRSTCALL_INIT();
419  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
420 
421  tupdesc = CreateTemplateTupleDesc(5);
422  TupleDescInitEntry(tupdesc, (AttrNumber) 1, "word",
423  TEXTOID, -1, 0);
424  TupleDescInitEntry(tupdesc, (AttrNumber) 2, "catcode",
425  CHAROID, -1, 0);
426  TupleDescInitEntry(tupdesc, (AttrNumber) 3, "barelabel",
427  BOOLOID, -1, 0);
428  TupleDescInitEntry(tupdesc, (AttrNumber) 4, "catdesc",
429  TEXTOID, -1, 0);
430  TupleDescInitEntry(tupdesc, (AttrNumber) 5, "baredesc",
431  TEXTOID, -1, 0);
432 
433  funcctx->attinmeta = TupleDescGetAttInMetadata(tupdesc);
434 
435  MemoryContextSwitchTo(oldcontext);
436  }
437 
438  funcctx = SRF_PERCALL_SETUP();
439 
440  if (funcctx->call_cntr < ScanKeywords.num_keywords)
441  {
442  char *values[5];
443  HeapTuple tuple;
444 
445  /* cast-away-const is ugly but alternatives aren't much better */
446  values[0] = unconstify(char *,
447  GetScanKeyword(funcctx->call_cntr,
448  &ScanKeywords));
449 
450  switch (ScanKeywordCategories[funcctx->call_cntr])
451  {
452  case UNRESERVED_KEYWORD:
453  values[1] = "U";
454  values[3] = _("unreserved");
455  break;
456  case COL_NAME_KEYWORD:
457  values[1] = "C";
458  values[3] = _("unreserved (cannot be function or type name)");
459  break;
461  values[1] = "T";
462  values[3] = _("reserved (can be function or type name)");
463  break;
464  case RESERVED_KEYWORD:
465  values[1] = "R";
466  values[3] = _("reserved");
467  break;
468  default: /* shouldn't be possible */
469  values[1] = NULL;
470  values[3] = NULL;
471  break;
472  }
473 
474  if (ScanKeywordBareLabel[funcctx->call_cntr])
475  {
476  values[2] = "true";
477  values[4] = _("can be bare label");
478  }
479  else
480  {
481  values[2] = "false";
482  values[4] = _("requires AS");
483  }
484 
485  tuple = BuildTupleFromCStrings(funcctx->attinmeta, values);
486 
487  SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tuple));
488  }
489 
490  SRF_RETURN_DONE(funcctx);
491 }
492 
493 
494 /* Function to return the list of catalog foreign key relationships */
495 Datum
497 {
498  FuncCallContext *funcctx;
499  FmgrInfo *arrayinp;
500 
501  if (SRF_IS_FIRSTCALL())
502  {
503  MemoryContext oldcontext;
504  TupleDesc tupdesc;
505 
506  funcctx = SRF_FIRSTCALL_INIT();
507  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
508 
509  tupdesc = CreateTemplateTupleDesc(6);
510  TupleDescInitEntry(tupdesc, (AttrNumber) 1, "fktable",
511  REGCLASSOID, -1, 0);
512  TupleDescInitEntry(tupdesc, (AttrNumber) 2, "fkcols",
513  TEXTARRAYOID, -1, 0);
514  TupleDescInitEntry(tupdesc, (AttrNumber) 3, "pktable",
515  REGCLASSOID, -1, 0);
516  TupleDescInitEntry(tupdesc, (AttrNumber) 4, "pkcols",
517  TEXTARRAYOID, -1, 0);
518  TupleDescInitEntry(tupdesc, (AttrNumber) 5, "is_array",
519  BOOLOID, -1, 0);
520  TupleDescInitEntry(tupdesc, (AttrNumber) 6, "is_opt",
521  BOOLOID, -1, 0);
522 
523  funcctx->tuple_desc = BlessTupleDesc(tupdesc);
524 
525  /*
526  * We use array_in to convert the C strings in sys_fk_relationships[]
527  * to text arrays. But we cannot use DirectFunctionCallN to call
528  * array_in, and it wouldn't be very efficient if we could. Fill an
529  * FmgrInfo to use for the call.
530  */
531  arrayinp = (FmgrInfo *) palloc(sizeof(FmgrInfo));
532  fmgr_info(F_ARRAY_IN, arrayinp);
533  funcctx->user_fctx = arrayinp;
534 
535  MemoryContextSwitchTo(oldcontext);
536  }
537 
538  funcctx = SRF_PERCALL_SETUP();
539  arrayinp = (FmgrInfo *) funcctx->user_fctx;
540 
541  if (funcctx->call_cntr < lengthof(sys_fk_relationships))
542  {
543  const SysFKRelationship *fkrel = &sys_fk_relationships[funcctx->call_cntr];
544  Datum values[6];
545  bool nulls[6];
546  HeapTuple tuple;
547 
548  memset(nulls, false, sizeof(nulls));
549 
550  values[0] = ObjectIdGetDatum(fkrel->fk_table);
551  values[1] = FunctionCall3(arrayinp,
552  CStringGetDatum(fkrel->fk_columns),
553  ObjectIdGetDatum(TEXTOID),
554  Int32GetDatum(-1));
555  values[2] = ObjectIdGetDatum(fkrel->pk_table);
556  values[3] = FunctionCall3(arrayinp,
557  CStringGetDatum(fkrel->pk_columns),
558  ObjectIdGetDatum(TEXTOID),
559  Int32GetDatum(-1));
560  values[4] = BoolGetDatum(fkrel->is_array);
561  values[5] = BoolGetDatum(fkrel->is_opt);
562 
563  tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);
564 
565  SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tuple));
566  }
567 
568  SRF_RETURN_DONE(funcctx);
569 }
570 
571 
572 /*
573  * Return the type of the argument.
574  */
575 Datum
577 {
578  PG_RETURN_OID(get_fn_expr_argtype(fcinfo->flinfo, 0));
579 }
580 
581 
582 /*
583  * Implementation of the COLLATE FOR expression; returns the collation
584  * of the argument.
585  */
586 Datum
588 {
589  Oid typeid;
590  Oid collid;
591 
592  typeid = get_fn_expr_argtype(fcinfo->flinfo, 0);
593  if (!typeid)
594  PG_RETURN_NULL();
595  if (!type_is_collatable(typeid) && typeid != UNKNOWNOID)
596  ereport(ERROR,
597  (errcode(ERRCODE_DATATYPE_MISMATCH),
598  errmsg("collations are not supported by type %s",
599  format_type_be(typeid))));
600 
601  collid = PG_GET_COLLATION();
602  if (!collid)
603  PG_RETURN_NULL();
605 }
606 
607 
608 /*
609  * pg_relation_is_updatable - determine which update events the specified
610  * relation supports.
611  *
612  * This relies on relation_is_updatable() in rewriteHandler.c, which see
613  * for additional information.
614  */
615 Datum
617 {
618  Oid reloid = PG_GETARG_OID(0);
619  bool include_triggers = PG_GETARG_BOOL(1);
620 
621  PG_RETURN_INT32(relation_is_updatable(reloid, NIL, include_triggers, NULL));
622 }
623 
624 /*
625  * pg_column_is_updatable - determine whether a column is updatable
626  *
627  * This function encapsulates the decision about just what
628  * information_schema.columns.is_updatable actually means. It's not clear
629  * whether deletability of the column's relation should be required, so
630  * we want that decision in C code where we could change it without initdb.
631  */
632 Datum
634 {
635  Oid reloid = PG_GETARG_OID(0);
638  bool include_triggers = PG_GETARG_BOOL(2);
639  int events;
640 
641  /* System columns are never updatable */
642  if (attnum <= 0)
643  PG_RETURN_BOOL(false);
644 
645  events = relation_is_updatable(reloid, NIL, include_triggers,
646  bms_make_singleton(col));
647 
648  /* We require both updatability and deletability of the relation */
649 #define REQ_EVENTS ((1 << CMD_UPDATE) | (1 << CMD_DELETE))
650 
651  PG_RETURN_BOOL((events & REQ_EVENTS) == REQ_EVENTS);
652 }
653 
654 
655 /*
656  * Is character a valid identifier start?
657  * Must match scan.l's {ident_start} character class.
658  */
659 static bool
660 is_ident_start(unsigned char c)
661 {
662  /* Underscores and ASCII letters are OK */
663  if (c == '_')
664  return true;
665  if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
666  return true;
667  /* Any high-bit-set character is OK (might be part of a multibyte char) */
668  if (IS_HIGHBIT_SET(c))
669  return true;
670  return false;
671 }
672 
673 /*
674  * Is character a valid identifier continuation?
675  * Must match scan.l's {ident_cont} character class.
676  */
677 static bool
678 is_ident_cont(unsigned char c)
679 {
680  /* Can be digit or dollar sign ... */
681  if ((c >= '0' && c <= '9') || c == '$')
682  return true;
683  /* ... or an identifier start character */
684  return is_ident_start(c);
685 }
686 
687 /*
688  * parse_ident - parse a SQL qualified identifier into separate identifiers.
689  * When strict mode is active (second parameter), then any chars after
690  * the last identifier are disallowed.
691  */
692 Datum
694 {
695  text *qualname = PG_GETARG_TEXT_PP(0);
696  bool strict = PG_GETARG_BOOL(1);
697  char *qualname_str = text_to_cstring(qualname);
698  ArrayBuildState *astate = NULL;
699  char *nextp;
700  bool after_dot = false;
701 
702  /*
703  * The code below scribbles on qualname_str in some cases, so we should
704  * reconvert qualname if we need to show the original string in error
705  * messages.
706  */
707  nextp = qualname_str;
708 
709  /* skip leading whitespace */
710  while (scanner_isspace(*nextp))
711  nextp++;
712 
713  for (;;)
714  {
715  char *curname;
716  bool missing_ident = true;
717 
718  if (*nextp == '"')
719  {
720  char *endp;
721 
722  curname = nextp + 1;
723  for (;;)
724  {
725  endp = strchr(nextp + 1, '"');
726  if (endp == NULL)
727  ereport(ERROR,
728  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
729  errmsg("string is not a valid identifier: \"%s\"",
730  text_to_cstring(qualname)),
731  errdetail("String has unclosed double quotes.")));
732  if (endp[1] != '"')
733  break;
734  memmove(endp, endp + 1, strlen(endp));
735  nextp = endp;
736  }
737  nextp = endp + 1;
738  *endp = '\0';
739 
740  if (endp - curname == 0)
741  ereport(ERROR,
742  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
743  errmsg("string is not a valid identifier: \"%s\"",
744  text_to_cstring(qualname)),
745  errdetail("Quoted identifier must not be empty.")));
746 
747  astate = accumArrayResult(astate, CStringGetTextDatum(curname),
748  false, TEXTOID, CurrentMemoryContext);
749  missing_ident = false;
750  }
751  else if (is_ident_start((unsigned char) *nextp))
752  {
753  char *downname;
754  int len;
755  text *part;
756 
757  curname = nextp++;
758  while (is_ident_cont((unsigned char) *nextp))
759  nextp++;
760 
761  len = nextp - curname;
762 
763  /*
764  * We don't implicitly truncate identifiers. This is useful for
765  * allowing the user to check for specific parts of the identifier
766  * being too long. It's easy enough for the user to get the
767  * truncated names by casting our output to name[].
768  */
769  downname = downcase_identifier(curname, len, false, false);
770  part = cstring_to_text_with_len(downname, len);
771  astate = accumArrayResult(astate, PointerGetDatum(part), false,
772  TEXTOID, CurrentMemoryContext);
773  missing_ident = false;
774  }
775 
776  if (missing_ident)
777  {
778  /* Different error messages based on where we failed. */
779  if (*nextp == '.')
780  ereport(ERROR,
781  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
782  errmsg("string is not a valid identifier: \"%s\"",
783  text_to_cstring(qualname)),
784  errdetail("No valid identifier before \".\".")));
785  else if (after_dot)
786  ereport(ERROR,
787  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
788  errmsg("string is not a valid identifier: \"%s\"",
789  text_to_cstring(qualname)),
790  errdetail("No valid identifier after \".\".")));
791  else
792  ereport(ERROR,
793  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
794  errmsg("string is not a valid identifier: \"%s\"",
795  text_to_cstring(qualname))));
796  }
797 
798  while (scanner_isspace(*nextp))
799  nextp++;
800 
801  if (*nextp == '.')
802  {
803  after_dot = true;
804  nextp++;
805  while (scanner_isspace(*nextp))
806  nextp++;
807  }
808  else if (*nextp == '\0')
809  {
810  break;
811  }
812  else
813  {
814  if (strict)
815  ereport(ERROR,
816  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
817  errmsg("string is not a valid identifier: \"%s\"",
818  text_to_cstring(qualname))));
819  break;
820  }
821  }
822 
824 }
825 
826 /*
827  * pg_current_logfile
828  *
829  * Report current log file used by log collector by scanning current_logfiles.
830  */
831 Datum
833 {
834  FILE *fd;
835  char lbuffer[MAXPGPATH];
836  char *logfmt;
837 
838  /* The log format parameter is optional */
839  if (PG_NARGS() == 0 || PG_ARGISNULL(0))
840  logfmt = NULL;
841  else
842  {
843  logfmt = text_to_cstring(PG_GETARG_TEXT_PP(0));
844 
845  if (strcmp(logfmt, "stderr") != 0 && strcmp(logfmt, "csvlog") != 0)
846  ereport(ERROR,
847  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
848  errmsg("log format \"%s\" is not supported", logfmt),
849  errhint("The supported log formats are \"stderr\" and \"csvlog\".")));
850  }
851 
853  if (fd == NULL)
854  {
855  if (errno != ENOENT)
856  ereport(ERROR,
858  errmsg("could not read file \"%s\": %m",
860  PG_RETURN_NULL();
861  }
862 
863 #ifdef WIN32
864  /* syslogger.c writes CRLF line endings on Windows */
865  _setmode(_fileno(fd), _O_TEXT);
866 #endif
867 
868  /*
869  * Read the file to gather current log filename(s) registered by the
870  * syslogger.
871  */
872  while (fgets(lbuffer, sizeof(lbuffer), fd) != NULL)
873  {
874  char *log_format;
875  char *log_filepath;
876  char *nlpos;
877 
878  /* Extract log format and log file path from the line. */
879  log_format = lbuffer;
880  log_filepath = strchr(lbuffer, ' ');
881  if (log_filepath == NULL)
882  {
883  /* Uh oh. No space found, so file content is corrupted. */
884  elog(ERROR,
885  "missing space character in \"%s\"", LOG_METAINFO_DATAFILE);
886  break;
887  }
888 
889  *log_filepath = '\0';
890  log_filepath++;
891  nlpos = strchr(log_filepath, '\n');
892  if (nlpos == NULL)
893  {
894  /* Uh oh. No newline found, so file content is corrupted. */
895  elog(ERROR,
896  "missing newline character in \"%s\"", LOG_METAINFO_DATAFILE);
897  break;
898  }
899  *nlpos = '\0';
900 
901  if (logfmt == NULL || strcmp(logfmt, log_format) == 0)
902  {
903  FreeFile(fd);
904  PG_RETURN_TEXT_P(cstring_to_text(log_filepath));
905  }
906  }
907 
908  /* Close the current log filename file. */
909  FreeFile(fd);
910 
911  PG_RETURN_NULL();
912 }
913 
914 /*
915  * Report current log file used by log collector (1 argument version)
916  *
917  * note: this wrapper is necessary to pass the sanity check in opr_sanity,
918  * which checks that all built-in functions that share the implementing C
919  * function take the same number of arguments
920  */
921 Datum
923 {
924  return pg_current_logfile(fcinfo);
925 }
926 
927 /*
928  * SQL wrapper around RelationGetReplicaIndex().
929  */
930 Datum
932 {
933  Oid reloid = PG_GETARG_OID(0);
934  Oid idxoid;
935  Relation rel;
936 
937  rel = table_open(reloid, AccessShareLock);
938  idxoid = RelationGetReplicaIndex(rel);
940 
941  if (OidIsValid(idxoid))
942  PG_RETURN_OID(idxoid);
943  else
944  PG_RETURN_NULL();
945 }
void tuplestore_putvalues(Tuplestorestate *state, TupleDesc tdesc, Datum *values, bool *isnull)
Definition: tuplestore.c:750
#define PG_GETARG_FLOAT8(n)
Definition: fmgr.h:282
uint64 call_cntr
Definition: funcapi.h:65
#define NIL
Definition: pg_list.h:65
static bool is_ident_start(unsigned char c)
Definition: misc.c:660
Definition: fmgr.h:56
#define IsA(nodeptr, _type_)
Definition: nodes.h:584
Datum pg_get_replica_identity_index(PG_FUNCTION_ARGS)
Definition: misc.c:931
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
int errhint(const char *fmt,...)
Definition: elog.c:1152
Datum pg_relation_is_updatable(PG_FUNCTION_ARGS)
Definition: misc.c:616
Datum parse_ident(PG_FUNCTION_ARGS)
Definition: misc.c:693
Oid RelationGetReplicaIndex(Relation relation)
Definition: relcache.c:4735
#define WL_TIMEOUT
Definition: latch.h:128
static bool count_nulls(FunctionCallInfo fcinfo, int32 *nargs, int32 *nulls)
Definition: misc.c:53
TupleDesc CreateTemplateTupleDesc(int natts)
Definition: tupdesc.c:44
void namestrcpy(Name name, const char *str)
Definition: name.c:233
#define SRF_IS_FIRSTCALL()
Definition: funcapi.h:294
#define PointerGetDatum(X)
Definition: postgres.h:556
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define PG_RETURN_INT32(x)
Definition: fmgr.h:354
#define AccessShareLock
Definition: lockdefs.h:36
Datum pg_collation_for(PG_FUNCTION_ARGS)
Definition: misc.c:587
bool get_fn_expr_variadic(FmgrInfo *flinfo)
Definition: fmgr.c:1937
int errcode(int sqlerrcode)
Definition: elog.c:694
#define LOG_METAINFO_DATAFILE
Definition: syslogger.h:95
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
bool directory_is_empty(const char *path)
Definition: tablespace.c:858
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:27
const uint8 ScanKeywordCategories[SCANKEYWORDS_NUM_KEYWORDS]
Definition: keywords.c:29
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
#define UNRESERVED_KEYWORD
Definition: keywords.h:20
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:274
#define lengthof(array)
Definition: c.h:734
unsigned int Oid
Definition: postgres_ext.h:31
Definition: dirent.h:9
#define OidIsValid(objectId)
Definition: c.h:710
#define SRF_PERCALL_SETUP()
Definition: funcapi.h:298
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define PG_GET_COLLATION()
Definition: fmgr.h:198
void ResetLatch(Latch *latch)
Definition: latch.c:660
Datum pg_typeof(PG_FUNCTION_ARGS)
Definition: misc.c:576
char * generate_collation_name(Oid collid)
Definition: ruleutils.c:11506
static const char * GetScanKeyword(int n, const ScanKeywordList *keywords)
Definition: kwlookup.h:39
TupleDesc tuple_desc
Definition: funcapi.h:112
signed int int32
Definition: c.h:429
Oid MyDatabaseTableSpace
Definition: globals.c:88
int WaitLatch(Latch *latch, int wakeEvents, long timeout, uint32 wait_event_info)
Definition: latch.c:452
HeapTuple BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values)
Definition: execTuples.c:2116
Datum current_database(PG_FUNCTION_ARGS)
Definition: misc.c:172
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:309
PGDLLIMPORT const ScanKeywordList ScanKeywords
#define FunctionCall3(flinfo, arg1, arg2, arg3)
Definition: fmgr.h:648
Datum current_query(PG_FUNCTION_ARGS)
Definition: misc.c:189
#define NAMEDATALEN
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition: funcapi.h:300
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:256
#define GetNowFloat()
void pfree(void *pointer)
Definition: mcxt.c:1057
Datum pg_current_logfile(PG_FUNCTION_ARGS)
Definition: misc.c:832
#define IS_HIGHBIT_SET(ch)
Definition: c.h:1156
Datum pg_tablespace_location(PG_FUNCTION_ARGS)
Definition: misc.c:305
Definition: dirent.c:25
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:45
double float8
Definition: c.h:565
Datum pg_num_nulls(PG_FUNCTION_ARGS)
Definition: misc.c:139
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:1803
#define ARR_DIMS(a)
Definition: array.h:287
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:126
#define MAXPGPATH
char * get_database_name(Oid dbid)
Definition: dbcommands.c:2155
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:2052
Definition: c.h:675
#define TYPE_FUNC_NAME_KEYWORD
Definition: keywords.h:22
#define TABLESPACE_VERSION_DIRECTORY
Definition: relpath.h:26
char * c
Bitmapset * bms_make_singleton(int x)
Definition: bitmapset.c:186
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:201
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
#define readlink(path, buf, size)
Definition: win32_port.h:228
AttInMetadata * attinmeta
Definition: funcapi.h:91
int errdetail(const char *fmt,...)
Definition: elog.c:1038
int errcode_for_file_access(void)
Definition: elog.c:717
const bool ScanKeywordBareLabel[SCANKEYWORDS_NUM_KEYWORDS]
Definition: keywords.c:42
#define CStringGetDatum(X)
Definition: postgres.h:578
FILE * AllocateFile(const char *name, const char *mode)
Definition: fd.c:2354
Datum pg_current_logfile_1arg(PG_FUNCTION_ARGS)
Definition: misc.c:922
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2615
Datum pg_sleep(PG_FUNCTION_ARGS)
Definition: misc.c:361
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition: tupdesc.c:603
#define atooid(x)
Definition: postgres_ext.h:42
Datum pg_tablespace_databases(PG_FUNCTION_ARGS)
Definition: misc.c:201
Datum makeArrayResult(ArrayBuildState *astate, MemoryContext rcontext)
Definition: arrayfuncs.c:5149
int relation_is_updatable(Oid reloid, List *outer_reloids, bool include_triggers, Bitmapset *include_cols)
#define WARNING
Definition: elog.h:40
const char * debug_query_string
Definition: postgres.c:89
#define unconstify(underlying_type, expr)
Definition: c.h:1243
Datum pg_num_nonnulls(PG_FUNCTION_ARGS)
Definition: misc.c:155
Tuplestorestate * tuplestore_begin_heap(bool randomAccess, bool interXact, int maxKBytes)
Definition: tuplestore.c:318
uint8 bits8
Definition: c.h:448
int num_keywords
Definition: kwlookup.h:30
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359
uintptr_t Datum
Definition: postgres.h:367
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:353
FmgrInfo * flinfo
Definition: fmgr.h:87
Oid MyDatabaseId
Definition: globals.c:86
AttInMetadata * TupleDescGetAttInMetadata(TupleDesc tupdesc)
Definition: execTuples.c:2067
bool scanner_isspace(char ch)
Definition: scansup.c:117
#define PG_GETARG_INT16(n)
Definition: fmgr.h:271
int work_mem
Definition: globals.c:122
#define REQ_EVENTS
#define RESERVED_KEYWORD
Definition: keywords.h:23
#define BoolGetDatum(X)
Definition: postgres.h:402
#define InvalidOid
Definition: postgres_ext.h:36
char * downcase_identifier(const char *ident, int len, bool warn, bool truncate)
Definition: scansup.c:46
int16 attnum
Definition: pg_attribute.h:83
#define ereport(elevel,...)
Definition: elog.h:155
int allowedModes
Definition: execnodes.h:304
#define PG_RETURN_VOID()
Definition: fmgr.h:349
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:372
SetFunctionReturnMode returnMode
Definition: execnodes.h:306
text * cstring_to_text(const char *s)
Definition: varlena.c:189
#define PG_ARGISNULL(n)
Definition: fmgr.h:209
#define Assert(condition)
Definition: c.h:804
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2681
MemoryContext multi_call_memory_ctx
Definition: funcapi.h:101
static bool is_ident_cont(unsigned char c)
Definition: misc.c:678
#define PG_NARGS()
Definition: fmgr.h:203
#define HeapTupleGetDatum(tuple)
Definition: funcapi.h:221
MemoryContext ecxt_per_query_memory
Definition: execnodes.h:232
#define ARR_NDIM(a)
Definition: array.h:283
#define COL_NAME_KEYWORD
Definition: keywords.h:21
Datum pg_get_catalog_foreign_keys(PG_FUNCTION_ARGS)
Definition: misc.c:496
Tuplestorestate * setResult
Definition: execnodes.h:309
int FreeFile(FILE *file)
Definition: fd.c:2553
static Datum values[MAXATTR]
Definition: bootstrap.c:165
char * text_to_cstring(const text *t)
Definition: varlena.c:222
ArrayBuildState * accumArrayResult(ArrayBuildState *astate, Datum dvalue, bool disnull, Oid element_type, MemoryContext rcontext)
Definition: arrayfuncs.c:5085
Oid get_base_element_type(Oid typid)
Definition: lsyscache.c:2779
ExprContext * econtext
Definition: execnodes.h:302
#define Int32GetDatum(X)
Definition: postgres.h:479
void * user_fctx
Definition: funcapi.h:82
TupleDesc setDesc
Definition: execnodes.h:310
void * palloc(Size size)
Definition: mcxt.c:950
int errmsg(const char *fmt,...)
Definition: elog.c:905
#define elog(elevel,...)
Definition: elog.h:227
int i
#define CStringGetTextDatum(s)
Definition: builtins.h:82
struct Latch * MyLatch
Definition: globals.c:55
Definition: c.h:621
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:100
Datum pg_get_keywords(PG_FUNCTION_ARGS)
Definition: misc.c:409
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
NameData * Name
Definition: c.h:679
bool type_is_collatable(Oid typid)
Definition: lsyscache.c:3028
#define PG_RETURN_OID(x)
Definition: fmgr.h:360
#define snprintf
Definition: port.h:216
#define WL_LATCH_SET
Definition: latch.h:125
int16 AttrNumber
Definition: attnum.h:21
#define _(x)
Definition: elog.c:89
#define ARR_NULLBITMAP(a)
Definition: array.h:293
#define PG_RETURN_NULL()
Definition: fmgr.h:345
#define PG_RETURN_NAME(x)
Definition: fmgr.h:363
int FreeDir(DIR *dir)
Definition: fd.c:2733
#define WL_EXIT_ON_PM_DEATH
Definition: latch.h:130
Datum pg_column_is_updatable(PG_FUNCTION_ARGS)
Definition: misc.c:633
#define SRF_RETURN_DONE(_funcctx)
Definition: funcapi.h:318
#define SRF_FIRSTCALL_INIT()
Definition: funcapi.h:296