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-2024, 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/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 "nodes/miscnodes.h"
35 #include "parser/parse_type.h"
36 #include "parser/scansup.h"
37 #include "pgstat.h"
38 #include "postmaster/syslogger.h"
39 #include "rewrite/rewriteHandler.h"
40 #include "storage/fd.h"
41 #include "storage/latch.h"
42 #include "tcop/tcopprot.h"
43 #include "utils/builtins.h"
44 #include "utils/fmgroids.h"
45 #include "utils/lsyscache.h"
46 #include "utils/ruleutils.h"
47 #include "utils/syscache.h"
48 #include "utils/timestamp.h"
49 
50 
51 /*
52  * structure to cache metadata needed in pg_input_is_valid_common
53  */
54 typedef struct ValidIOData
55 {
63 
65  text *txt, text *typname,
66  ErrorSaveContext *escontext);
67 
68 
69 /*
70  * Common subroutine for num_nulls() and num_nonnulls().
71  * Returns true if successful, false if function should return NULL.
72  * If successful, total argument count and number of nulls are
73  * returned into *nargs and *nulls.
74  */
75 static bool
77  int32 *nargs, int32 *nulls)
78 {
79  int32 count = 0;
80  int i;
81 
82  /* Did we get a VARIADIC array argument, or separate arguments? */
83  if (get_fn_expr_variadic(fcinfo->flinfo))
84  {
85  ArrayType *arr;
86  int ndims,
87  nitems,
88  *dims;
89  bits8 *bitmap;
90 
91  Assert(PG_NARGS() == 1);
92 
93  /*
94  * If we get a null as VARIADIC array argument, we can't say anything
95  * useful about the number of elements, so return NULL. This behavior
96  * is consistent with other variadic functions - see concat_internal.
97  */
98  if (PG_ARGISNULL(0))
99  return false;
100 
101  /*
102  * Non-null argument had better be an array. We assume that any call
103  * context that could let get_fn_expr_variadic return true will have
104  * checked that a VARIADIC-labeled parameter actually is an array. So
105  * it should be okay to just Assert that it's an array rather than
106  * doing a full-fledged error check.
107  */
109 
110  /* OK, safe to fetch the array value */
111  arr = PG_GETARG_ARRAYTYPE_P(0);
112 
113  /* Count the array elements */
114  ndims = ARR_NDIM(arr);
115  dims = ARR_DIMS(arr);
116  nitems = ArrayGetNItems(ndims, dims);
117 
118  /* Count those that are NULL */
119  bitmap = ARR_NULLBITMAP(arr);
120  if (bitmap)
121  {
122  int bitmask = 1;
123 
124  for (i = 0; i < nitems; i++)
125  {
126  if ((*bitmap & bitmask) == 0)
127  count++;
128 
129  bitmask <<= 1;
130  if (bitmask == 0x100)
131  {
132  bitmap++;
133  bitmask = 1;
134  }
135  }
136  }
137 
138  *nargs = nitems;
139  *nulls = count;
140  }
141  else
142  {
143  /* Separate arguments, so just count 'em */
144  for (i = 0; i < PG_NARGS(); i++)
145  {
146  if (PG_ARGISNULL(i))
147  count++;
148  }
149 
150  *nargs = PG_NARGS();
151  *nulls = count;
152  }
153 
154  return true;
155 }
156 
157 /*
158  * num_nulls()
159  * Count the number of NULL arguments
160  */
161 Datum
163 {
164  int32 nargs,
165  nulls;
166 
167  if (!count_nulls(fcinfo, &nargs, &nulls))
168  PG_RETURN_NULL();
169 
170  PG_RETURN_INT32(nulls);
171 }
172 
173 /*
174  * num_nonnulls()
175  * Count the number of non-NULL arguments
176  */
177 Datum
179 {
180  int32 nargs,
181  nulls;
182 
183  if (!count_nulls(fcinfo, &nargs, &nulls))
184  PG_RETURN_NULL();
185 
186  PG_RETURN_INT32(nargs - nulls);
187 }
188 
189 
190 /*
191  * current_database()
192  * Expose the current database to the user
193  */
194 Datum
196 {
197  Name db;
198 
199  db = (Name) palloc(NAMEDATALEN);
200 
202  PG_RETURN_NAME(db);
203 }
204 
205 
206 /*
207  * current_query()
208  * Expose the current query to the user (useful in stored procedures)
209  * We might want to use ActivePortal->sourceText someday.
210  */
211 Datum
213 {
214  /* there is no easy way to access the more concise 'query_string' */
215  if (debug_query_string)
217  else
218  PG_RETURN_NULL();
219 }
220 
221 /* Function to find out which databases make use of a tablespace */
222 
223 Datum
225 {
226  Oid tablespaceOid = PG_GETARG_OID(0);
227  ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
228  char *location;
229  DIR *dirdesc;
230  struct dirent *de;
231 
233 
234  if (tablespaceOid == GLOBALTABLESPACE_OID)
235  {
237  (errmsg("global tablespace never has databases")));
238  /* return empty tuplestore */
239  return (Datum) 0;
240  }
241 
242  if (tablespaceOid == DEFAULTTABLESPACE_OID)
243  location = "base";
244  else
245  location = psprintf("pg_tblspc/%u/%s", tablespaceOid,
247 
248  dirdesc = AllocateDir(location);
249 
250  if (!dirdesc)
251  {
252  /* the only expected error is ENOENT */
253  if (errno != ENOENT)
254  ereport(ERROR,
256  errmsg("could not open directory \"%s\": %m",
257  location)));
259  (errmsg("%u is not a tablespace OID", tablespaceOid)));
260  /* return empty tuplestore */
261  return (Datum) 0;
262  }
263 
264  while ((de = ReadDir(dirdesc, location)) != NULL)
265  {
266  Oid datOid = atooid(de->d_name);
267  char *subdir;
268  bool isempty;
269  Datum values[1];
270  bool nulls[1];
271 
272  /* this test skips . and .., but is awfully weak */
273  if (!datOid)
274  continue;
275 
276  /* if database subdir is empty, don't report tablespace as used */
277 
278  subdir = psprintf("%s/%s", location, de->d_name);
279  isempty = directory_is_empty(subdir);
280  pfree(subdir);
281 
282  if (isempty)
283  continue; /* indeed, nothing in it */
284 
285  values[0] = ObjectIdGetDatum(datOid);
286  nulls[0] = false;
287 
288  tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
289  values, nulls);
290  }
291 
292  FreeDir(dirdesc);
293  return (Datum) 0;
294 }
295 
296 
297 /*
298  * pg_tablespace_location - get location for a tablespace
299  */
300 Datum
302 {
303  Oid tablespaceOid = PG_GETARG_OID(0);
304  char sourcepath[MAXPGPATH];
305  char targetpath[MAXPGPATH];
306  int rllen;
307  struct stat st;
308 
309  /*
310  * It's useful to apply this function to pg_class.reltablespace, wherein
311  * zero means "the database's default tablespace". So, rather than
312  * throwing an error for zero, we choose to assume that's what is meant.
313  */
314  if (tablespaceOid == InvalidOid)
315  tablespaceOid = MyDatabaseTableSpace;
316 
317  /*
318  * Return empty string for the cluster's default tablespaces
319  */
320  if (tablespaceOid == DEFAULTTABLESPACE_OID ||
321  tablespaceOid == GLOBALTABLESPACE_OID)
323 
324  /*
325  * Find the location of the tablespace by reading the symbolic link that
326  * is in pg_tblspc/<oid>.
327  */
328  snprintf(sourcepath, sizeof(sourcepath), "pg_tblspc/%u", tablespaceOid);
329 
330  /*
331  * Before reading the link, check if the source path is a link or a
332  * junction point. Note that a directory is possible for a tablespace
333  * created with allow_in_place_tablespaces enabled. If a directory is
334  * found, a relative path to the data directory is returned.
335  */
336  if (lstat(sourcepath, &st) < 0)
337  {
338  ereport(ERROR,
340  errmsg("could not stat file \"%s\": %m",
341  sourcepath)));
342  }
343 
344  if (!S_ISLNK(st.st_mode))
345  PG_RETURN_TEXT_P(cstring_to_text(sourcepath));
346 
347  /*
348  * In presence of a link or a junction point, return the path pointing to.
349  */
350  rllen = readlink(sourcepath, targetpath, sizeof(targetpath));
351  if (rllen < 0)
352  ereport(ERROR,
354  errmsg("could not read symbolic link \"%s\": %m",
355  sourcepath)));
356  if (rllen >= sizeof(targetpath))
357  ereport(ERROR,
358  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
359  errmsg("symbolic link \"%s\" target is too long",
360  sourcepath)));
361  targetpath[rllen] = '\0';
362 
363  PG_RETURN_TEXT_P(cstring_to_text(targetpath));
364 }
365 
366 /*
367  * pg_sleep - delay for N seconds
368  */
369 Datum
371 {
372  float8 secs = PG_GETARG_FLOAT8(0);
373  float8 endtime;
374 
375  /*
376  * We sleep using WaitLatch, to ensure that we'll wake up promptly if an
377  * important signal (such as SIGALRM or SIGINT) arrives. Because
378  * WaitLatch's upper limit of delay is INT_MAX milliseconds, and the user
379  * might ask for more than that, we sleep for at most 10 minutes and then
380  * loop.
381  *
382  * By computing the intended stop time initially, we avoid accumulation of
383  * extra delay across multiple sleeps. This also ensures we won't delay
384  * less than the specified time when WaitLatch is terminated early by a
385  * non-query-canceling signal such as SIGHUP.
386  */
387 #define GetNowFloat() ((float8) GetCurrentTimestamp() / 1000000.0)
388 
389  endtime = GetNowFloat() + secs;
390 
391  for (;;)
392  {
393  float8 delay;
394  long delay_ms;
395 
397 
398  delay = endtime - GetNowFloat();
399  if (delay >= 600.0)
400  delay_ms = 600000;
401  else if (delay > 0.0)
402  delay_ms = (long) ceil(delay * 1000.0);
403  else
404  break;
405 
406  (void) WaitLatch(MyLatch,
408  delay_ms,
409  WAIT_EVENT_PG_SLEEP);
411  }
412 
413  PG_RETURN_VOID();
414 }
415 
416 /* Function to return the list of grammar keywords */
417 Datum
419 {
420  FuncCallContext *funcctx;
421 
422  if (SRF_IS_FIRSTCALL())
423  {
424  MemoryContext oldcontext;
425  TupleDesc tupdesc;
426 
427  funcctx = SRF_FIRSTCALL_INIT();
428  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
429 
430  if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
431  elog(ERROR, "return type must be a row type");
432  funcctx->tuple_desc = tupdesc;
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  if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
510  elog(ERROR, "return type must be a row type");
511  funcctx->tuple_desc = BlessTupleDesc(tupdesc);
512 
513  /*
514  * We use array_in to convert the C strings in sys_fk_relationships[]
515  * to text arrays. But we cannot use DirectFunctionCallN to call
516  * array_in, and it wouldn't be very efficient if we could. Fill an
517  * FmgrInfo to use for the call.
518  */
519  arrayinp = (FmgrInfo *) palloc(sizeof(FmgrInfo));
520  fmgr_info(F_ARRAY_IN, arrayinp);
521  funcctx->user_fctx = arrayinp;
522 
523  MemoryContextSwitchTo(oldcontext);
524  }
525 
526  funcctx = SRF_PERCALL_SETUP();
527  arrayinp = (FmgrInfo *) funcctx->user_fctx;
528 
529  if (funcctx->call_cntr < lengthof(sys_fk_relationships))
530  {
531  const SysFKRelationship *fkrel = &sys_fk_relationships[funcctx->call_cntr];
532  Datum values[6];
533  bool nulls[6];
534  HeapTuple tuple;
535 
536  memset(nulls, false, sizeof(nulls));
537 
538  values[0] = ObjectIdGetDatum(fkrel->fk_table);
539  values[1] = FunctionCall3(arrayinp,
540  CStringGetDatum(fkrel->fk_columns),
541  ObjectIdGetDatum(TEXTOID),
542  Int32GetDatum(-1));
543  values[2] = ObjectIdGetDatum(fkrel->pk_table);
544  values[3] = FunctionCall3(arrayinp,
545  CStringGetDatum(fkrel->pk_columns),
546  ObjectIdGetDatum(TEXTOID),
547  Int32GetDatum(-1));
548  values[4] = BoolGetDatum(fkrel->is_array);
549  values[5] = BoolGetDatum(fkrel->is_opt);
550 
551  tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);
552 
553  SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tuple));
554  }
555 
556  SRF_RETURN_DONE(funcctx);
557 }
558 
559 
560 /*
561  * Return the type of the argument.
562  */
563 Datum
565 {
566  PG_RETURN_OID(get_fn_expr_argtype(fcinfo->flinfo, 0));
567 }
568 
569 
570 /*
571  * Return the base type of the argument.
572  * If the given type is a domain, return its base type;
573  * otherwise return the type's own OID.
574  * Return NULL if the type OID doesn't exist or points to a
575  * non-existent base type.
576  *
577  * This is a SQL-callable version of getBaseType(). Unlike that function,
578  * we don't want to fail for a bogus type OID; this is helpful to keep race
579  * conditions from turning into query failures when scanning the catalogs.
580  * Hence we need our own implementation.
581  */
582 Datum
584 {
585  Oid typid = PG_GETARG_OID(0);
586 
587  /*
588  * We loop to find the bottom base type in a stack of domains.
589  */
590  for (;;)
591  {
592  HeapTuple tup;
593  Form_pg_type typTup;
594 
595  tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
596  if (!HeapTupleIsValid(tup))
597  PG_RETURN_NULL(); /* return NULL for bogus OID */
598  typTup = (Form_pg_type) GETSTRUCT(tup);
599  if (typTup->typtype != TYPTYPE_DOMAIN)
600  {
601  /* Not a domain, so done */
602  ReleaseSysCache(tup);
603  break;
604  }
605 
606  typid = typTup->typbasetype;
607  ReleaseSysCache(tup);
608  }
609 
610  PG_RETURN_OID(typid);
611 }
612 
613 
614 /*
615  * Implementation of the COLLATE FOR expression; returns the collation
616  * of the argument.
617  */
618 Datum
620 {
621  Oid typeid;
622  Oid collid;
623 
624  typeid = get_fn_expr_argtype(fcinfo->flinfo, 0);
625  if (!typeid)
626  PG_RETURN_NULL();
627  if (!type_is_collatable(typeid) && typeid != UNKNOWNOID)
628  ereport(ERROR,
629  (errcode(ERRCODE_DATATYPE_MISMATCH),
630  errmsg("collations are not supported by type %s",
631  format_type_be(typeid))));
632 
634  if (!collid)
635  PG_RETURN_NULL();
637 }
638 
639 
640 /*
641  * pg_relation_is_updatable - determine which update events the specified
642  * relation supports.
643  *
644  * This relies on relation_is_updatable() in rewriteHandler.c, which see
645  * for additional information.
646  */
647 Datum
649 {
650  Oid reloid = PG_GETARG_OID(0);
651  bool include_triggers = PG_GETARG_BOOL(1);
652 
653  PG_RETURN_INT32(relation_is_updatable(reloid, NIL, include_triggers, NULL));
654 }
655 
656 /*
657  * pg_column_is_updatable - determine whether a column is updatable
658  *
659  * This function encapsulates the decision about just what
660  * information_schema.columns.is_updatable actually means. It's not clear
661  * whether deletability of the column's relation should be required, so
662  * we want that decision in C code where we could change it without initdb.
663  */
664 Datum
666 {
667  Oid reloid = PG_GETARG_OID(0);
670  bool include_triggers = PG_GETARG_BOOL(2);
671  int events;
672 
673  /* System columns are never updatable */
674  if (attnum <= 0)
675  PG_RETURN_BOOL(false);
676 
677  events = relation_is_updatable(reloid, NIL, include_triggers,
678  bms_make_singleton(col));
679 
680  /* We require both updatability and deletability of the relation */
681 #define REQ_EVENTS ((1 << CMD_UPDATE) | (1 << CMD_DELETE))
682 
683  PG_RETURN_BOOL((events & REQ_EVENTS) == REQ_EVENTS);
684 }
685 
686 
687 /*
688  * pg_input_is_valid - test whether string is valid input for datatype.
689  *
690  * Returns true if OK, false if not.
691  *
692  * This will only work usefully if the datatype's input function has been
693  * updated to return "soft" errors via errsave/ereturn.
694  */
695 Datum
697 {
698  text *txt = PG_GETARG_TEXT_PP(0);
700  ErrorSaveContext escontext = {T_ErrorSaveContext};
701 
703  &escontext));
704 }
705 
706 /*
707  * pg_input_error_info - test whether string is valid input for datatype.
708  *
709  * Returns NULL if OK, else the primary message, detail message, hint message
710  * and sql error code from the error.
711  *
712  * This will only work usefully if the datatype's input function has been
713  * updated to return "soft" errors via errsave/ereturn.
714  */
715 Datum
717 {
718  text *txt = PG_GETARG_TEXT_PP(0);
720  ErrorSaveContext escontext = {T_ErrorSaveContext};
721  TupleDesc tupdesc;
722  Datum values[4];
723  bool isnull[4];
724 
725  if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
726  elog(ERROR, "return type must be a row type");
727 
728  /* Enable details_wanted */
729  escontext.details_wanted = true;
730 
731  if (pg_input_is_valid_common(fcinfo, txt, typname,
732  &escontext))
733  memset(isnull, true, sizeof(isnull));
734  else
735  {
736  char *sqlstate;
737 
738  Assert(escontext.error_occurred);
739  Assert(escontext.error_data != NULL);
740  Assert(escontext.error_data->message != NULL);
741 
742  memset(isnull, false, sizeof(isnull));
743 
744  values[0] = CStringGetTextDatum(escontext.error_data->message);
745 
746  if (escontext.error_data->detail != NULL)
747  values[1] = CStringGetTextDatum(escontext.error_data->detail);
748  else
749  isnull[1] = true;
750 
751  if (escontext.error_data->hint != NULL)
752  values[2] = CStringGetTextDatum(escontext.error_data->hint);
753  else
754  isnull[2] = true;
755 
756  sqlstate = unpack_sql_state(escontext.error_data->sqlerrcode);
757  values[3] = CStringGetTextDatum(sqlstate);
758  }
759 
760  return HeapTupleGetDatum(heap_form_tuple(tupdesc, values, isnull));
761 }
762 
763 /* Common subroutine for the above */
764 static bool
766  text *txt, text *typname,
767  ErrorSaveContext *escontext)
768 {
769  char *str = text_to_cstring(txt);
770  ValidIOData *my_extra;
771  Datum converted;
772 
773  /*
774  * We arrange to look up the needed I/O info just once per series of
775  * calls, assuming the data type doesn't change underneath us.
776  */
777  my_extra = (ValidIOData *) fcinfo->flinfo->fn_extra;
778  if (my_extra == NULL)
779  {
780  fcinfo->flinfo->fn_extra =
782  sizeof(ValidIOData));
783  my_extra = (ValidIOData *) fcinfo->flinfo->fn_extra;
784  my_extra->typoid = InvalidOid;
785  /* Detect whether typname argument is constant. */
786  my_extra->typname_constant = get_fn_expr_arg_stable(fcinfo->flinfo, 1);
787  }
788 
789  /*
790  * If the typname argument is constant, we only need to parse it the first
791  * time through.
792  */
793  if (my_extra->typoid == InvalidOid || !my_extra->typname_constant)
794  {
795  char *typnamestr = text_to_cstring(typname);
796  Oid typoid;
797 
798  /* Parse type-name argument to obtain type OID and encoded typmod. */
799  (void) parseTypeString(typnamestr, &typoid, &my_extra->typmod, NULL);
800 
801  /* Update type-specific info if typoid changed. */
802  if (my_extra->typoid != typoid)
803  {
804  getTypeInputInfo(typoid,
805  &my_extra->typiofunc,
806  &my_extra->typioparam);
807  fmgr_info_cxt(my_extra->typiofunc, &my_extra->inputproc,
808  fcinfo->flinfo->fn_mcxt);
809  my_extra->typoid = typoid;
810  }
811  }
812 
813  /* Now we can try to perform the conversion. */
814  return InputFunctionCallSafe(&my_extra->inputproc,
815  str,
816  my_extra->typioparam,
817  my_extra->typmod,
818  (Node *) escontext,
819  &converted);
820 }
821 
822 
823 /*
824  * Is character a valid identifier start?
825  * Must match scan.l's {ident_start} character class.
826  */
827 static bool
828 is_ident_start(unsigned char c)
829 {
830  /* Underscores and ASCII letters are OK */
831  if (c == '_')
832  return true;
833  if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
834  return true;
835  /* Any high-bit-set character is OK (might be part of a multibyte char) */
836  if (IS_HIGHBIT_SET(c))
837  return true;
838  return false;
839 }
840 
841 /*
842  * Is character a valid identifier continuation?
843  * Must match scan.l's {ident_cont} character class.
844  */
845 static bool
846 is_ident_cont(unsigned char c)
847 {
848  /* Can be digit or dollar sign ... */
849  if ((c >= '0' && c <= '9') || c == '$')
850  return true;
851  /* ... or an identifier start character */
852  return is_ident_start(c);
853 }
854 
855 /*
856  * parse_ident - parse a SQL qualified identifier into separate identifiers.
857  * When strict mode is active (second parameter), then any chars after
858  * the last identifier are disallowed.
859  */
860 Datum
862 {
863  text *qualname = PG_GETARG_TEXT_PP(0);
864  bool strict = PG_GETARG_BOOL(1);
865  char *qualname_str = text_to_cstring(qualname);
866  ArrayBuildState *astate = NULL;
867  char *nextp;
868  bool after_dot = false;
869 
870  /*
871  * The code below scribbles on qualname_str in some cases, so we should
872  * reconvert qualname if we need to show the original string in error
873  * messages.
874  */
875  nextp = qualname_str;
876 
877  /* skip leading whitespace */
878  while (scanner_isspace(*nextp))
879  nextp++;
880 
881  for (;;)
882  {
883  char *curname;
884  bool missing_ident = true;
885 
886  if (*nextp == '"')
887  {
888  char *endp;
889 
890  curname = nextp + 1;
891  for (;;)
892  {
893  endp = strchr(nextp + 1, '"');
894  if (endp == NULL)
895  ereport(ERROR,
896  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
897  errmsg("string is not a valid identifier: \"%s\"",
898  text_to_cstring(qualname)),
899  errdetail("String has unclosed double quotes.")));
900  if (endp[1] != '"')
901  break;
902  memmove(endp, endp + 1, strlen(endp));
903  nextp = endp;
904  }
905  nextp = endp + 1;
906  *endp = '\0';
907 
908  if (endp - curname == 0)
909  ereport(ERROR,
910  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
911  errmsg("string is not a valid identifier: \"%s\"",
912  text_to_cstring(qualname)),
913  errdetail("Quoted identifier must not be empty.")));
914 
915  astate = accumArrayResult(astate, CStringGetTextDatum(curname),
916  false, TEXTOID, CurrentMemoryContext);
917  missing_ident = false;
918  }
919  else if (is_ident_start((unsigned char) *nextp))
920  {
921  char *downname;
922  int len;
923  text *part;
924 
925  curname = nextp++;
926  while (is_ident_cont((unsigned char) *nextp))
927  nextp++;
928 
929  len = nextp - curname;
930 
931  /*
932  * We don't implicitly truncate identifiers. This is useful for
933  * allowing the user to check for specific parts of the identifier
934  * being too long. It's easy enough for the user to get the
935  * truncated names by casting our output to name[].
936  */
937  downname = downcase_identifier(curname, len, false, false);
938  part = cstring_to_text_with_len(downname, len);
939  astate = accumArrayResult(astate, PointerGetDatum(part), false,
940  TEXTOID, CurrentMemoryContext);
941  missing_ident = false;
942  }
943 
944  if (missing_ident)
945  {
946  /* Different error messages based on where we failed. */
947  if (*nextp == '.')
948  ereport(ERROR,
949  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
950  errmsg("string is not a valid identifier: \"%s\"",
951  text_to_cstring(qualname)),
952  errdetail("No valid identifier before \".\".")));
953  else if (after_dot)
954  ereport(ERROR,
955  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
956  errmsg("string is not a valid identifier: \"%s\"",
957  text_to_cstring(qualname)),
958  errdetail("No valid identifier after \".\".")));
959  else
960  ereport(ERROR,
961  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
962  errmsg("string is not a valid identifier: \"%s\"",
963  text_to_cstring(qualname))));
964  }
965 
966  while (scanner_isspace(*nextp))
967  nextp++;
968 
969  if (*nextp == '.')
970  {
971  after_dot = true;
972  nextp++;
973  while (scanner_isspace(*nextp))
974  nextp++;
975  }
976  else if (*nextp == '\0')
977  {
978  break;
979  }
980  else
981  {
982  if (strict)
983  ereport(ERROR,
984  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
985  errmsg("string is not a valid identifier: \"%s\"",
986  text_to_cstring(qualname))));
987  break;
988  }
989  }
990 
992 }
993 
994 /*
995  * pg_current_logfile
996  *
997  * Report current log file used by log collector by scanning current_logfiles.
998  */
999 Datum
1001 {
1002  FILE *fd;
1003  char lbuffer[MAXPGPATH];
1004  char *logfmt;
1005 
1006  /* The log format parameter is optional */
1007  if (PG_NARGS() == 0 || PG_ARGISNULL(0))
1008  logfmt = NULL;
1009  else
1010  {
1011  logfmt = text_to_cstring(PG_GETARG_TEXT_PP(0));
1012 
1013  if (strcmp(logfmt, "stderr") != 0 &&
1014  strcmp(logfmt, "csvlog") != 0 &&
1015  strcmp(logfmt, "jsonlog") != 0)
1016  ereport(ERROR,
1017  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1018  errmsg("log format \"%s\" is not supported", logfmt),
1019  errhint("The supported log formats are \"stderr\", \"csvlog\", and \"jsonlog\".")));
1020  }
1021 
1023  if (fd == NULL)
1024  {
1025  if (errno != ENOENT)
1026  ereport(ERROR,
1028  errmsg("could not read file \"%s\": %m",
1030  PG_RETURN_NULL();
1031  }
1032 
1033 #ifdef WIN32
1034  /* syslogger.c writes CRLF line endings on Windows */
1035  _setmode(_fileno(fd), _O_TEXT);
1036 #endif
1037 
1038  /*
1039  * Read the file to gather current log filename(s) registered by the
1040  * syslogger.
1041  */
1042  while (fgets(lbuffer, sizeof(lbuffer), fd) != NULL)
1043  {
1044  char *log_format;
1045  char *log_filepath;
1046  char *nlpos;
1047 
1048  /* Extract log format and log file path from the line. */
1049  log_format = lbuffer;
1050  log_filepath = strchr(lbuffer, ' ');
1051  if (log_filepath == NULL)
1052  {
1053  /* Uh oh. No space found, so file content is corrupted. */
1054  elog(ERROR,
1055  "missing space character in \"%s\"", LOG_METAINFO_DATAFILE);
1056  break;
1057  }
1058 
1059  *log_filepath = '\0';
1060  log_filepath++;
1061  nlpos = strchr(log_filepath, '\n');
1062  if (nlpos == NULL)
1063  {
1064  /* Uh oh. No newline found, so file content is corrupted. */
1065  elog(ERROR,
1066  "missing newline character in \"%s\"", LOG_METAINFO_DATAFILE);
1067  break;
1068  }
1069  *nlpos = '\0';
1070 
1071  if (logfmt == NULL || strcmp(logfmt, log_format) == 0)
1072  {
1073  FreeFile(fd);
1074  PG_RETURN_TEXT_P(cstring_to_text(log_filepath));
1075  }
1076  }
1077 
1078  /* Close the current log filename file. */
1079  FreeFile(fd);
1080 
1081  PG_RETURN_NULL();
1082 }
1083 
1084 /*
1085  * Report current log file used by log collector (1 argument version)
1086  *
1087  * note: this wrapper is necessary to pass the sanity check in opr_sanity,
1088  * which checks that all built-in functions that share the implementing C
1089  * function take the same number of arguments
1090  */
1091 Datum
1093 {
1094  return pg_current_logfile(fcinfo);
1095 }
1096 
1097 /*
1098  * SQL wrapper around RelationGetReplicaIndex().
1099  */
1100 Datum
1102 {
1103  Oid reloid = PG_GETARG_OID(0);
1104  Oid idxoid;
1105  Relation rel;
1106 
1107  rel = table_open(reloid, AccessShareLock);
1108  idxoid = RelationGetReplicaIndex(rel);
1110 
1111  if (OidIsValid(idxoid))
1112  PG_RETURN_OID(idxoid);
1113  else
1114  PG_RETURN_NULL();
1115 }
1116 
1117 /*
1118  * Transition function for the ANY_VALUE aggregate
1119  */
1120 Datum
1122 {
1124 }
#define ARR_NDIM(a)
Definition: array.h:290
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:263
#define ARR_NULLBITMAP(a)
Definition: array.h:300
#define ARR_DIMS(a)
Definition: array.h:294
ArrayBuildState * accumArrayResult(ArrayBuildState *astate, Datum dvalue, bool disnull, Oid element_type, MemoryContext rcontext)
Definition: arrayfuncs.c:5331
Datum makeArrayResult(ArrayBuildState *astate, MemoryContext rcontext)
Definition: arrayfuncs.c:5401
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:57
int16 AttrNumber
Definition: attnum.h:21
bool directory_is_empty(const char *path)
Definition: tablespace.c:853
Datum pg_typeof(PG_FUNCTION_ARGS)
Definition: misc.c:564
struct ValidIOData ValidIOData
Datum parse_ident(PG_FUNCTION_ARGS)
Definition: misc.c:861
static bool count_nulls(FunctionCallInfo fcinfo, int32 *nargs, int32 *nulls)
Definition: misc.c:76
Datum pg_tablespace_databases(PG_FUNCTION_ARGS)
Definition: misc.c:224
#define GetNowFloat()
static bool is_ident_cont(unsigned char c)
Definition: misc.c:846
#define REQ_EVENTS
Datum current_query(PG_FUNCTION_ARGS)
Definition: misc.c:212
Datum pg_get_catalog_foreign_keys(PG_FUNCTION_ARGS)
Definition: misc.c:496
static bool pg_input_is_valid_common(FunctionCallInfo fcinfo, text *txt, text *typname, ErrorSaveContext *escontext)
Definition: misc.c:765
Datum pg_input_error_info(PG_FUNCTION_ARGS)
Definition: misc.c:716
Datum pg_input_is_valid(PG_FUNCTION_ARGS)
Definition: misc.c:696
Datum any_value_transfn(PG_FUNCTION_ARGS)
Definition: misc.c:1121
Datum pg_sleep(PG_FUNCTION_ARGS)
Definition: misc.c:370
Datum pg_get_replica_identity_index(PG_FUNCTION_ARGS)
Definition: misc.c:1101
Datum pg_current_logfile(PG_FUNCTION_ARGS)
Definition: misc.c:1000
Datum pg_get_keywords(PG_FUNCTION_ARGS)
Definition: misc.c:418
static bool is_ident_start(unsigned char c)
Definition: misc.c:828
Datum current_database(PG_FUNCTION_ARGS)
Definition: misc.c:195
Datum pg_column_is_updatable(PG_FUNCTION_ARGS)
Definition: misc.c:665
Datum pg_num_nulls(PG_FUNCTION_ARGS)
Definition: misc.c:162
Datum pg_basetype(PG_FUNCTION_ARGS)
Definition: misc.c:583
Datum pg_current_logfile_1arg(PG_FUNCTION_ARGS)
Definition: misc.c:1092
Datum pg_tablespace_location(PG_FUNCTION_ARGS)
Definition: misc.c:301
Datum pg_relation_is_updatable(PG_FUNCTION_ARGS)
Definition: misc.c:648
Datum pg_collation_for(PG_FUNCTION_ARGS)
Definition: misc.c:619
Datum pg_num_nonnulls(PG_FUNCTION_ARGS)
Definition: misc.c:178
Bitmapset * bms_make_singleton(int x)
Definition: bitmapset.c:216
static Datum values[MAXATTR]
Definition: bootstrap.c:152
#define CStringGetTextDatum(s)
Definition: builtins.h:97
#define unconstify(underlying_type, expr)
Definition: c.h:1245
NameData * Name
Definition: c.h:744
#define IS_HIGHBIT_SET(ch)
Definition: c.h:1155
signed int int32
Definition: c.h:494
#define Assert(condition)
Definition: c.h:858
double float8
Definition: c.h:630
uint8 bits8
Definition: c.h:513
#define lengthof(array)
Definition: c.h:788
#define OidIsValid(objectId)
Definition: c.h:775
Oid collid
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:3154
int errcode_for_file_access(void)
Definition: elog.c:880
int errdetail(const char *fmt,...)
Definition: elog.c:1203
int errhint(const char *fmt,...)
Definition: elog.c:1317
char * unpack_sql_state(int sql_state)
Definition: elog.c:3133
int errcode(int sqlerrcode)
Definition: elog.c:857
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define _(x)
Definition: elog.c:90
#define WARNING
Definition: elog.h:36
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:224
#define ereport(elevel,...)
Definition: elog.h:149
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:2158
HeapTuple BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values)
Definition: execTuples.c:2222
AttInMetadata * TupleDescGetAttInMetadata(TupleDesc tupdesc)
Definition: execTuples.c:2173
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2909
int FreeDir(DIR *dir)
Definition: fd.c:2961
FILE * AllocateFile(const char *name, const char *mode)
Definition: fd.c:2583
int FreeFile(FILE *file)
Definition: fd.c:2781
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2843
bool get_fn_expr_arg_stable(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:1975
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:127
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:137
bool InputFunctionCallSafe(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod, fmNodePtr escontext, Datum *result)
Definition: fmgr.c:1585
bool get_fn_expr_variadic(FmgrInfo *flinfo)
Definition: fmgr.c:2044
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:1910
#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_GETARG_DATUM(n)
Definition: fmgr.h:268
#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:664
#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 InitMaterializedSRF(FunctionCallInfo fcinfo, bits32 flags)
Definition: funcapi.c:76
TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo, Oid *resultTypeId, TupleDesc *resultTupleDesc)
Definition: funcapi.c:276
#define SRF_IS_FIRSTCALL()
Definition: funcapi.h:304
#define SRF_PERCALL_SETUP()
Definition: funcapi.h:308
@ TYPEFUNC_COMPOSITE
Definition: funcapi.h:149
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition: funcapi.h:310
#define SRF_FIRSTCALL_INIT()
Definition: funcapi.h:306
static Datum HeapTupleGetDatum(const HeapTupleData *tuple)
Definition: funcapi.h:230
#define SRF_RETURN_DONE(_funcctx)
Definition: funcapi.h:328
#define MAT_SRF_USE_EXPECTED_DESC
Definition: funcapi.h:296
Oid MyDatabaseTableSpace
Definition: globals.c:93
struct Latch * MyLatch
Definition: globals.c:60
Oid MyDatabaseId
Definition: globals.c:91
const char * str
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
Definition: heaptuple.c:1116
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define GETSTRUCT(TUP)
Definition: htup_details.h:653
#define nitems(x)
Definition: indent.h:31
int i
Definition: isn.c:73
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:77
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:724
int WaitLatch(Latch *latch, int wakeEvents, long timeout, uint32 wait_event_info)
Definition: latch.c:517
#define WL_TIMEOUT
Definition: latch.h:130
#define WL_EXIT_ON_PM_DEATH
Definition: latch.h:132
#define WL_LATCH_SET
Definition: latch.h:127
#define AccessShareLock
Definition: lockdefs.h:36
void getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
Definition: lsyscache.c:2874
bool type_is_collatable(Oid typid)
Definition: lsyscache.c:3081
Oid get_base_element_type(Oid typid)
Definition: lsyscache.c:2832
void pfree(void *pointer)
Definition: mcxt.c:1520
MemoryContext CurrentMemoryContext
Definition: mcxt.c:143
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1180
void * palloc(Size size)
Definition: mcxt.c:1316
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:122
void namestrcpy(Name name, const char *str)
Definition: name.c:233
bool parseTypeString(const char *str, Oid *typeid_p, int32 *typmod_p, Node *escontext)
Definition: parse_type.c:785
int16 attnum
Definition: pg_attribute.h:74
#define NAMEDATALEN
#define MAXPGPATH
const void size_t len
#define NIL
Definition: pg_list.h:68
FormData_pg_type * Form_pg_type
Definition: pg_type.h:261
NameData typname
Definition: pg_type.h:41
#define snprintf
Definition: port.h:238
const char * debug_query_string
Definition: postgres.c:87
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:322
uintptr_t Datum
Definition: postgres.h:64
static Datum BoolGetDatum(bool X)
Definition: postgres.h:102
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
static Datum CStringGetDatum(const char *X)
Definition: postgres.h:350
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:212
#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
MemoryContextSwitchTo(old_ctx)
Oid RelationGetReplicaIndex(Relation relation)
Definition: relcache.c:5012
#define TABLESPACE_VERSION_DIRECTORY
Definition: relpath.h:33
int relation_is_updatable(Oid reloid, List *outer_reloids, bool include_triggers, Bitmapset *include_cols)
char * generate_collation_name(Oid collid)
Definition: ruleutils.c:13108
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
int sqlerrcode
Definition: elog.h:438
char * detail
Definition: elog.h:440
char * message
Definition: elog.h:439
char * hint
Definition: elog.h:442
bool details_wanted
Definition: miscnodes.h:47
ErrorData * error_data
Definition: miscnodes.h:48
bool error_occurred
Definition: miscnodes.h:46
Definition: fmgr.h:57
void * fn_extra
Definition: fmgr.h:64
MemoryContext fn_mcxt
Definition: fmgr.h:65
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
Definition: nodes.h:129
TupleDesc setDesc
Definition: execnodes.h:340
Tuplestorestate * setResult
Definition: execnodes.h:339
int num_keywords
Definition: kwlookup.h:30
int32 typmod
Definition: misc.c:57
Oid typoid
Definition: misc.c:56
bool typname_constant
Definition: misc.c:58
FmgrInfo inputproc
Definition: misc.c:61
Oid typiofunc
Definition: misc.c:59
Oid typioparam
Definition: misc.c:60
Definition: dirent.h:10
Definition: c.h:741
unsigned short st_mode
Definition: win32_port.h:268
Definition: c.h:687
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:27
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:266
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:218
#define LOG_METAINFO_DATAFILE
Definition: syslogger.h:98
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:40
void tuplestore_putvalues(Tuplestorestate *state, TupleDesc tdesc, const Datum *values, const bool *isnull)
Definition: tuplestore.c:750
char * text_to_cstring(const text *t)
Definition: varlena.c:217
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:196
text * cstring_to_text(const char *s)
Definition: varlena.c:184
#define lstat(path, sb)
Definition: win32_port.h:285
#define S_ISLNK(m)
Definition: win32_port.h:344
#define readlink(path, buf, size)
Definition: win32_port.h:236