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