PostgreSQL Source Code  git master
misc.c File Reference
#include "postgres.h"
#include <sys/file.h>
#include <dirent.h>
#include <fcntl.h>
#include <math.h>
#include <unistd.h>
#include "access/sysattr.h"
#include "access/table.h"
#include "catalog/catalog.h"
#include "catalog/pg_tablespace.h"
#include "catalog/pg_type.h"
#include "catalog/system_fk_info.h"
#include "commands/dbcommands.h"
#include "commands/tablespace.h"
#include "common/keywords.h"
#include "funcapi.h"
#include "miscadmin.h"
#include "parser/scansup.h"
#include "pgstat.h"
#include "postmaster/syslogger.h"
#include "rewrite/rewriteHandler.h"
#include "storage/fd.h"
#include "storage/latch.h"
#include "tcop/tcopprot.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/lsyscache.h"
#include "utils/ruleutils.h"
#include "utils/timestamp.h"
Include dependency graph for misc.c:

Go to the source code of this file.

Macros

#define GetNowFloat()   ((float8) GetCurrentTimestamp() / 1000000.0)
 
#define REQ_EVENTS   ((1 << CMD_UPDATE) | (1 << CMD_DELETE))
 

Functions

static bool count_nulls (FunctionCallInfo fcinfo, int32 *nargs, int32 *nulls)
 
Datum pg_num_nulls (PG_FUNCTION_ARGS)
 
Datum pg_num_nonnulls (PG_FUNCTION_ARGS)
 
Datum current_database (PG_FUNCTION_ARGS)
 
Datum current_query (PG_FUNCTION_ARGS)
 
Datum pg_tablespace_databases (PG_FUNCTION_ARGS)
 
Datum pg_tablespace_location (PG_FUNCTION_ARGS)
 
Datum pg_sleep (PG_FUNCTION_ARGS)
 
Datum pg_get_keywords (PG_FUNCTION_ARGS)
 
Datum pg_get_catalog_foreign_keys (PG_FUNCTION_ARGS)
 
Datum pg_typeof (PG_FUNCTION_ARGS)
 
Datum pg_collation_for (PG_FUNCTION_ARGS)
 
Datum pg_relation_is_updatable (PG_FUNCTION_ARGS)
 
Datum pg_column_is_updatable (PG_FUNCTION_ARGS)
 
static bool is_ident_start (unsigned char c)
 
static bool is_ident_cont (unsigned char c)
 
Datum parse_ident (PG_FUNCTION_ARGS)
 
Datum pg_current_logfile (PG_FUNCTION_ARGS)
 
Datum pg_current_logfile_1arg (PG_FUNCTION_ARGS)
 
Datum pg_get_replica_identity_index (PG_FUNCTION_ARGS)
 

Macro Definition Documentation

◆ GetNowFloat

#define GetNowFloat ( )    ((float8) GetCurrentTimestamp() / 1000000.0)

Referenced by pg_sleep().

◆ REQ_EVENTS

#define REQ_EVENTS   ((1 << CMD_UPDATE) | (1 << CMD_DELETE))

Referenced by pg_column_is_updatable().

Function Documentation

◆ count_nulls()

static bool count_nulls ( FunctionCallInfo  fcinfo,
int32 nargs,
int32 nulls 
)
static

Definition at line 54 of file misc.c.

References ARR_DIMS, ARR_NDIM, ARR_NULLBITMAP, ArrayGetNItems(), Assert, FunctionCallInfoBaseData::flinfo, get_base_element_type(), get_fn_expr_argtype(), get_fn_expr_variadic(), i, OidIsValid, PG_ARGISNULL, PG_GETARG_ARRAYTYPE_P, and PG_NARGS.

Referenced by pg_num_nonnulls(), and pg_num_nulls().

56 {
57  int32 count = 0;
58  int i;
59 
60  /* Did we get a VARIADIC array argument, or separate arguments? */
61  if (get_fn_expr_variadic(fcinfo->flinfo))
62  {
63  ArrayType *arr;
64  int ndims,
65  nitems,
66  *dims;
67  bits8 *bitmap;
68 
69  Assert(PG_NARGS() == 1);
70 
71  /*
72  * If we get a null as VARIADIC array argument, we can't say anything
73  * useful about the number of elements, so return NULL. This behavior
74  * is consistent with other variadic functions - see concat_internal.
75  */
76  if (PG_ARGISNULL(0))
77  return false;
78 
79  /*
80  * Non-null argument had better be an array. We assume that any call
81  * context that could let get_fn_expr_variadic return true will have
82  * checked that a VARIADIC-labeled parameter actually is an array. So
83  * it should be okay to just Assert that it's an array rather than
84  * doing a full-fledged error check.
85  */
87 
88  /* OK, safe to fetch the array value */
89  arr = PG_GETARG_ARRAYTYPE_P(0);
90 
91  /* Count the array elements */
92  ndims = ARR_NDIM(arr);
93  dims = ARR_DIMS(arr);
94  nitems = ArrayGetNItems(ndims, dims);
95 
96  /* Count those that are NULL */
97  bitmap = ARR_NULLBITMAP(arr);
98  if (bitmap)
99  {
100  int bitmask = 1;
101 
102  for (i = 0; i < nitems; i++)
103  {
104  if ((*bitmap & bitmask) == 0)
105  count++;
106 
107  bitmask <<= 1;
108  if (bitmask == 0x100)
109  {
110  bitmap++;
111  bitmask = 1;
112  }
113  }
114  }
115 
116  *nargs = nitems;
117  *nulls = count;
118  }
119  else
120  {
121  /* Separate arguments, so just count 'em */
122  for (i = 0; i < PG_NARGS(); i++)
123  {
124  if (PG_ARGISNULL(i))
125  count++;
126  }
127 
128  *nargs = PG_NARGS();
129  *nulls = count;
130  }
131 
132  return true;
133 }
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
bool get_fn_expr_variadic(FmgrInfo *flinfo)
Definition: fmgr.c:1937
#define OidIsValid(objectId)
Definition: c.h:710
signed int int32
Definition: c.h:429
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:256
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:1803
#define ARR_DIMS(a)
Definition: array.h:287
uint8 bits8
Definition: c.h:448
FmgrInfo * flinfo
Definition: fmgr.h:87
#define PG_ARGISNULL(n)
Definition: fmgr.h:209
#define Assert(condition)
Definition: c.h:804
#define PG_NARGS()
Definition: fmgr.h:203
#define ARR_NDIM(a)
Definition: array.h:283
Oid get_base_element_type(Oid typid)
Definition: lsyscache.c:2779
int i
#define ARR_NULLBITMAP(a)
Definition: array.h:293

◆ current_database()

Datum current_database ( PG_FUNCTION_ARGS  )

Definition at line 173 of file misc.c.

References get_database_name(), MyDatabaseId, NAMEDATALEN, namestrcpy(), palloc(), and PG_RETURN_NAME.

Referenced by ExecEvalSQLValueFunction().

174 {
175  Name db;
176 
177  db = (Name) palloc(NAMEDATALEN);
178 
180  PG_RETURN_NAME(db);
181 }
void namestrcpy(Name name, const char *str)
Definition: name.c:233
#define NAMEDATALEN
char * get_database_name(Oid dbid)
Definition: dbcommands.c:2155
Definition: c.h:675
Oid MyDatabaseId
Definition: globals.c:88
void * palloc(Size size)
Definition: mcxt.c:1062
NameData * Name
Definition: c.h:679
#define PG_RETURN_NAME(x)
Definition: fmgr.h:363

◆ current_query()

Datum current_query ( PG_FUNCTION_ARGS  )

Definition at line 190 of file misc.c.

References cstring_to_text(), debug_query_string, PG_RETURN_NULL, and PG_RETURN_TEXT_P.

Referenced by dblink_current_query().

191 {
192  /* there is no easy way to access the more concise 'query_string' */
193  if (debug_query_string)
195  else
196  PG_RETURN_NULL();
197 }
const char * debug_query_string
Definition: postgres.c:89
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:372
text * cstring_to_text(const char *s)
Definition: varlena.c:190
#define PG_RETURN_NULL()
Definition: fmgr.h:345

◆ is_ident_cont()

static bool is_ident_cont ( unsigned char  c)
static

Definition at line 679 of file misc.c.

References is_ident_start().

Referenced by parse_ident().

680 {
681  /* Can be digit or dollar sign ... */
682  if ((c >= '0' && c <= '9') || c == '$')
683  return true;
684  /* ... or an identifier start character */
685  return is_ident_start(c);
686 }
static bool is_ident_start(unsigned char c)
Definition: misc.c:661
char * c

◆ is_ident_start()

static bool is_ident_start ( unsigned char  c)
static

Definition at line 661 of file misc.c.

References IS_HIGHBIT_SET.

Referenced by is_ident_cont(), and parse_ident().

662 {
663  /* Underscores and ASCII letters are OK */
664  if (c == '_')
665  return true;
666  if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
667  return true;
668  /* Any high-bit-set character is OK (might be part of a multibyte char) */
669  if (IS_HIGHBIT_SET(c))
670  return true;
671  return false;
672 }
#define IS_HIGHBIT_SET(ch)
Definition: c.h:1156
char * c

◆ parse_ident()

Datum parse_ident ( PG_FUNCTION_ARGS  )

Definition at line 694 of file misc.c.

References accumArrayResult(), cstring_to_text_with_len(), CStringGetTextDatum, CurrentMemoryContext, downcase_identifier(), ereport, errcode(), errdetail(), errmsg(), ERROR, is_ident_cont(), is_ident_start(), makeArrayResult(), PG_GETARG_BOOL, PG_GETARG_TEXT_PP, PG_RETURN_DATUM, PointerGetDatum, scanner_isspace(), and text_to_cstring().

695 {
696  text *qualname = PG_GETARG_TEXT_PP(0);
697  bool strict = PG_GETARG_BOOL(1);
698  char *qualname_str = text_to_cstring(qualname);
699  ArrayBuildState *astate = NULL;
700  char *nextp;
701  bool after_dot = false;
702 
703  /*
704  * The code below scribbles on qualname_str in some cases, so we should
705  * reconvert qualname if we need to show the original string in error
706  * messages.
707  */
708  nextp = qualname_str;
709 
710  /* skip leading whitespace */
711  while (scanner_isspace(*nextp))
712  nextp++;
713 
714  for (;;)
715  {
716  char *curname;
717  bool missing_ident = true;
718 
719  if (*nextp == '"')
720  {
721  char *endp;
722 
723  curname = nextp + 1;
724  for (;;)
725  {
726  endp = strchr(nextp + 1, '"');
727  if (endp == NULL)
728  ereport(ERROR,
729  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
730  errmsg("string is not a valid identifier: \"%s\"",
731  text_to_cstring(qualname)),
732  errdetail("String has unclosed double quotes.")));
733  if (endp[1] != '"')
734  break;
735  memmove(endp, endp + 1, strlen(endp));
736  nextp = endp;
737  }
738  nextp = endp + 1;
739  *endp = '\0';
740 
741  if (endp - curname == 0)
742  ereport(ERROR,
743  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
744  errmsg("string is not a valid identifier: \"%s\"",
745  text_to_cstring(qualname)),
746  errdetail("Quoted identifier must not be empty.")));
747 
748  astate = accumArrayResult(astate, CStringGetTextDatum(curname),
749  false, TEXTOID, CurrentMemoryContext);
750  missing_ident = false;
751  }
752  else if (is_ident_start((unsigned char) *nextp))
753  {
754  char *downname;
755  int len;
756  text *part;
757 
758  curname = nextp++;
759  while (is_ident_cont((unsigned char) *nextp))
760  nextp++;
761 
762  len = nextp - curname;
763 
764  /*
765  * We don't implicitly truncate identifiers. This is useful for
766  * allowing the user to check for specific parts of the identifier
767  * being too long. It's easy enough for the user to get the
768  * truncated names by casting our output to name[].
769  */
770  downname = downcase_identifier(curname, len, false, false);
771  part = cstring_to_text_with_len(downname, len);
772  astate = accumArrayResult(astate, PointerGetDatum(part), false,
773  TEXTOID, CurrentMemoryContext);
774  missing_ident = false;
775  }
776 
777  if (missing_ident)
778  {
779  /* Different error messages based on where we failed. */
780  if (*nextp == '.')
781  ereport(ERROR,
782  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
783  errmsg("string is not a valid identifier: \"%s\"",
784  text_to_cstring(qualname)),
785  errdetail("No valid identifier before \".\".")));
786  else if (after_dot)
787  ereport(ERROR,
788  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
789  errmsg("string is not a valid identifier: \"%s\"",
790  text_to_cstring(qualname)),
791  errdetail("No valid identifier after \".\".")));
792  else
793  ereport(ERROR,
794  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
795  errmsg("string is not a valid identifier: \"%s\"",
796  text_to_cstring(qualname))));
797  }
798 
799  while (scanner_isspace(*nextp))
800  nextp++;
801 
802  if (*nextp == '.')
803  {
804  after_dot = true;
805  nextp++;
806  while (scanner_isspace(*nextp))
807  nextp++;
808  }
809  else if (*nextp == '\0')
810  {
811  break;
812  }
813  else
814  {
815  if (strict)
816  ereport(ERROR,
817  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
818  errmsg("string is not a valid identifier: \"%s\"",
819  text_to_cstring(qualname))));
820  break;
821  }
822  }
823 
825 }
static bool is_ident_start(unsigned char c)
Definition: misc.c:661
#define PointerGetDatum(X)
Definition: postgres.h:600
int errcode(int sqlerrcode)
Definition: elog.c:698
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:274
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:309
#define ERROR
Definition: elog.h:46
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:202
int errdetail(const char *fmt,...)
Definition: elog.c:1042
MemoryContext CurrentMemoryContext
Definition: mcxt.c:42
Datum makeArrayResult(ArrayBuildState *astate, MemoryContext rcontext)
Definition: arrayfuncs.c:5149
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:353
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
#define ereport(elevel,...)
Definition: elog.h:157
static bool is_ident_cont(unsigned char c)
Definition: misc.c:679
char * text_to_cstring(const text *t)
Definition: varlena.c:223
ArrayBuildState * accumArrayResult(ArrayBuildState *astate, Datum dvalue, bool disnull, Oid element_type, MemoryContext rcontext)
Definition: arrayfuncs.c:5085
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define CStringGetTextDatum(s)
Definition: builtins.h:82
Definition: c.h:621

◆ pg_collation_for()

Datum pg_collation_for ( PG_FUNCTION_ARGS  )

Definition at line 588 of file misc.c.

References cstring_to_text(), ereport, errcode(), errmsg(), ERROR, format_type_be(), generate_collation_name(), get_fn_expr_argtype(), PG_GET_COLLATION, PG_RETURN_NULL, PG_RETURN_TEXT_P, and type_is_collatable().

589 {
590  Oid typeid;
591  Oid collid;
592 
593  typeid = get_fn_expr_argtype(fcinfo->flinfo, 0);
594  if (!typeid)
595  PG_RETURN_NULL();
596  if (!type_is_collatable(typeid) && typeid != UNKNOWNOID)
597  ereport(ERROR,
598  (errcode(ERRCODE_DATATYPE_MISMATCH),
599  errmsg("collations are not supported by type %s",
600  format_type_be(typeid))));
601 
602  collid = PG_GET_COLLATION();
603  if (!collid)
604  PG_RETURN_NULL();
606 }
int errcode(int sqlerrcode)
Definition: elog.c:698
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
unsigned int Oid
Definition: postgres_ext.h:31
#define PG_GET_COLLATION()
Definition: fmgr.h:198
char * generate_collation_name(Oid collid)
Definition: ruleutils.c:11835
#define ERROR
Definition: elog.h:46
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:1803
#define ereport(elevel,...)
Definition: elog.h:157
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:372
text * cstring_to_text(const char *s)
Definition: varlena.c:190
int errmsg(const char *fmt,...)
Definition: elog.c:909
bool type_is_collatable(Oid typid)
Definition: lsyscache.c:3028
#define PG_RETURN_NULL()
Definition: fmgr.h:345

◆ pg_column_is_updatable()

Datum pg_column_is_updatable ( PG_FUNCTION_ARGS  )

Definition at line 634 of file misc.c.

References attnum, bms_make_singleton(), FirstLowInvalidHeapAttributeNumber, NIL, PG_GETARG_BOOL, PG_GETARG_INT16, PG_GETARG_OID, PG_RETURN_BOOL, relation_is_updatable(), and REQ_EVENTS.

635 {
636  Oid reloid = PG_GETARG_OID(0);
639  bool include_triggers = PG_GETARG_BOOL(2);
640  int events;
641 
642  /* System columns are never updatable */
643  if (attnum <= 0)
644  PG_RETURN_BOOL(false);
645 
646  events = relation_is_updatable(reloid, NIL, include_triggers,
647  bms_make_singleton(col));
648 
649  /* We require both updatability and deletability of the relation */
650 #define REQ_EVENTS ((1 << CMD_UPDATE) | (1 << CMD_DELETE))
651 
652  PG_RETURN_BOOL((events & REQ_EVENTS) == REQ_EVENTS);
653 }
#define NIL
Definition: pg_list.h:65
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:27
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:274
unsigned int Oid
Definition: postgres_ext.h:31
Bitmapset * bms_make_singleton(int x)
Definition: bitmapset.c:186
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
int relation_is_updatable(Oid reloid, List *outer_reloids, bool include_triggers, Bitmapset *include_cols)
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359
#define PG_GETARG_INT16(n)
Definition: fmgr.h:271
#define REQ_EVENTS
int16 attnum
Definition: pg_attribute.h:83
int16 AttrNumber
Definition: attnum.h:21

◆ pg_current_logfile()

Datum pg_current_logfile ( PG_FUNCTION_ARGS  )

Definition at line 833 of file misc.c.

References AllocateFile(), cstring_to_text(), elog, ereport, errcode(), errcode_for_file_access(), errhint(), errmsg(), ERROR, fd(), FreeFile(), LOG_METAINFO_DATAFILE, MAXPGPATH, PG_ARGISNULL, PG_GETARG_TEXT_PP, PG_NARGS, PG_RETURN_NULL, PG_RETURN_TEXT_P, and text_to_cstring().

Referenced by pg_current_logfile_1arg().

834 {
835  FILE *fd;
836  char lbuffer[MAXPGPATH];
837  char *logfmt;
838 
839  /* The log format parameter is optional */
840  if (PG_NARGS() == 0 || PG_ARGISNULL(0))
841  logfmt = NULL;
842  else
843  {
844  logfmt = text_to_cstring(PG_GETARG_TEXT_PP(0));
845 
846  if (strcmp(logfmt, "stderr") != 0 && strcmp(logfmt, "csvlog") != 0)
847  ereport(ERROR,
848  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
849  errmsg("log format \"%s\" is not supported", logfmt),
850  errhint("The supported log formats are \"stderr\" and \"csvlog\".")));
851  }
852 
854  if (fd == NULL)
855  {
856  if (errno != ENOENT)
857  ereport(ERROR,
859  errmsg("could not read file \"%s\": %m",
861  PG_RETURN_NULL();
862  }
863 
864 #ifdef WIN32
865  /* syslogger.c writes CRLF line endings on Windows */
866  _setmode(_fileno(fd), _O_TEXT);
867 #endif
868 
869  /*
870  * Read the file to gather current log filename(s) registered by the
871  * syslogger.
872  */
873  while (fgets(lbuffer, sizeof(lbuffer), fd) != NULL)
874  {
875  char *log_format;
876  char *log_filepath;
877  char *nlpos;
878 
879  /* Extract log format and log file path from the line. */
880  log_format = lbuffer;
881  log_filepath = strchr(lbuffer, ' ');
882  if (log_filepath == NULL)
883  {
884  /* Uh oh. No space found, so file content is corrupted. */
885  elog(ERROR,
886  "missing space character in \"%s\"", LOG_METAINFO_DATAFILE);
887  break;
888  }
889 
890  *log_filepath = '\0';
891  log_filepath++;
892  nlpos = strchr(log_filepath, '\n');
893  if (nlpos == NULL)
894  {
895  /* Uh oh. No newline found, so file content is corrupted. */
896  elog(ERROR,
897  "missing newline character in \"%s\"", LOG_METAINFO_DATAFILE);
898  break;
899  }
900  *nlpos = '\0';
901 
902  if (logfmt == NULL || strcmp(logfmt, log_format) == 0)
903  {
904  FreeFile(fd);
905  PG_RETURN_TEXT_P(cstring_to_text(log_filepath));
906  }
907  }
908 
909  /* Close the current log filename file. */
910  FreeFile(fd);
911 
912  PG_RETURN_NULL();
913 }
int errhint(const char *fmt,...)
Definition: elog.c:1156
int errcode(int sqlerrcode)
Definition: elog.c:698
#define LOG_METAINFO_DATAFILE
Definition: syslogger.h:95
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:309
#define ERROR
Definition: elog.h:46
#define MAXPGPATH
int errcode_for_file_access(void)
Definition: elog.c:721
FILE * AllocateFile(const char *name, const char *mode)
Definition: fd.c:2373
#define ereport(elevel,...)
Definition: elog.h:157
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:372
text * cstring_to_text(const char *s)
Definition: varlena.c:190
#define PG_ARGISNULL(n)
Definition: fmgr.h:209
#define PG_NARGS()
Definition: fmgr.h:203
int FreeFile(FILE *file)
Definition: fd.c:2572
char * text_to_cstring(const text *t)
Definition: varlena.c:223
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define elog(elevel,...)
Definition: elog.h:232
#define PG_RETURN_NULL()
Definition: fmgr.h:345

◆ pg_current_logfile_1arg()

Datum pg_current_logfile_1arg ( PG_FUNCTION_ARGS  )

Definition at line 923 of file misc.c.

References pg_current_logfile().

924 {
925  return pg_current_logfile(fcinfo);
926 }
Datum pg_current_logfile(PG_FUNCTION_ARGS)
Definition: misc.c:833

◆ pg_get_catalog_foreign_keys()

Datum pg_get_catalog_foreign_keys ( PG_FUNCTION_ARGS  )

Definition at line 497 of file misc.c.

References BlessTupleDesc(), BoolGetDatum, FuncCallContext::call_cntr, CreateTemplateTupleDesc(), CStringGetDatum, fmgr_info(), FunctionCall3, heap_form_tuple(), HeapTupleGetDatum, Int32GetDatum, lengthof, MemoryContextSwitchTo(), FuncCallContext::multi_call_memory_ctx, ObjectIdGetDatum, palloc(), SRF_FIRSTCALL_INIT, SRF_IS_FIRSTCALL, SRF_PERCALL_SETUP, SRF_RETURN_DONE, SRF_RETURN_NEXT, FuncCallContext::tuple_desc, TupleDescInitEntry(), FuncCallContext::user_fctx, and values.

498 {
499  FuncCallContext *funcctx;
500  FmgrInfo *arrayinp;
501 
502  if (SRF_IS_FIRSTCALL())
503  {
504  MemoryContext oldcontext;
505  TupleDesc tupdesc;
506 
507  funcctx = SRF_FIRSTCALL_INIT();
508  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
509 
510  tupdesc = CreateTemplateTupleDesc(6);
511  TupleDescInitEntry(tupdesc, (AttrNumber) 1, "fktable",
512  REGCLASSOID, -1, 0);
513  TupleDescInitEntry(tupdesc, (AttrNumber) 2, "fkcols",
514  TEXTARRAYOID, -1, 0);
515  TupleDescInitEntry(tupdesc, (AttrNumber) 3, "pktable",
516  REGCLASSOID, -1, 0);
517  TupleDescInitEntry(tupdesc, (AttrNumber) 4, "pkcols",
518  TEXTARRAYOID, -1, 0);
519  TupleDescInitEntry(tupdesc, (AttrNumber) 5, "is_array",
520  BOOLOID, -1, 0);
521  TupleDescInitEntry(tupdesc, (AttrNumber) 6, "is_opt",
522  BOOLOID, -1, 0);
523 
524  funcctx->tuple_desc = BlessTupleDesc(tupdesc);
525 
526  /*
527  * We use array_in to convert the C strings in sys_fk_relationships[]
528  * to text arrays. But we cannot use DirectFunctionCallN to call
529  * array_in, and it wouldn't be very efficient if we could. Fill an
530  * FmgrInfo to use for the call.
531  */
532  arrayinp = (FmgrInfo *) palloc(sizeof(FmgrInfo));
533  fmgr_info(F_ARRAY_IN, arrayinp);
534  funcctx->user_fctx = arrayinp;
535 
536  MemoryContextSwitchTo(oldcontext);
537  }
538 
539  funcctx = SRF_PERCALL_SETUP();
540  arrayinp = (FmgrInfo *) funcctx->user_fctx;
541 
542  if (funcctx->call_cntr < lengthof(sys_fk_relationships))
543  {
544  const SysFKRelationship *fkrel = &sys_fk_relationships[funcctx->call_cntr];
545  Datum values[6];
546  bool nulls[6];
547  HeapTuple tuple;
548 
549  memset(nulls, false, sizeof(nulls));
550 
551  values[0] = ObjectIdGetDatum(fkrel->fk_table);
552  values[1] = FunctionCall3(arrayinp,
553  CStringGetDatum(fkrel->fk_columns),
554  ObjectIdGetDatum(TEXTOID),
555  Int32GetDatum(-1));
556  values[2] = ObjectIdGetDatum(fkrel->pk_table);
557  values[3] = FunctionCall3(arrayinp,
558  CStringGetDatum(fkrel->pk_columns),
559  ObjectIdGetDatum(TEXTOID),
560  Int32GetDatum(-1));
561  values[4] = BoolGetDatum(fkrel->is_array);
562  values[5] = BoolGetDatum(fkrel->is_opt);
563 
564  tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);
565 
566  SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tuple));
567  }
568 
569  SRF_RETURN_DONE(funcctx);
570 }
uint64 call_cntr
Definition: funcapi.h:65
Definition: fmgr.h:56
TupleDesc CreateTemplateTupleDesc(int natts)
Definition: tupdesc.c:45
#define SRF_IS_FIRSTCALL()
Definition: funcapi.h:294
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
#define lengthof(array)
Definition: c.h:734
#define SRF_PERCALL_SETUP()
Definition: funcapi.h:298
TupleDesc tuple_desc
Definition: funcapi.h:112
#define FunctionCall3(flinfo, arg1, arg2, arg3)
Definition: fmgr.h:648
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition: funcapi.h:300
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:126
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:2052
#define CStringGetDatum(X)
Definition: postgres.h:622
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition: tupdesc.c:580
uintptr_t Datum
Definition: postgres.h:411
#define BoolGetDatum(X)
Definition: postgres.h:446
MemoryContext multi_call_memory_ctx
Definition: funcapi.h:101
#define HeapTupleGetDatum(tuple)
Definition: funcapi.h:221
static Datum values[MAXATTR]
Definition: bootstrap.c:166
#define Int32GetDatum(X)
Definition: postgres.h:523
void * user_fctx
Definition: funcapi.h:82
void * palloc(Size size)
Definition: mcxt.c:1062
int16 AttrNumber
Definition: attnum.h:21
#define SRF_RETURN_DONE(_funcctx)
Definition: funcapi.h:318
#define SRF_FIRSTCALL_INIT()
Definition: funcapi.h:296

◆ pg_get_keywords()

Datum pg_get_keywords ( PG_FUNCTION_ARGS  )

Definition at line 410 of file misc.c.

References _, FuncCallContext::attinmeta, BuildTupleFromCStrings(), FuncCallContext::call_cntr, COL_NAME_KEYWORD, CreateTemplateTupleDesc(), GetScanKeyword(), HeapTupleGetDatum, MemoryContextSwitchTo(), FuncCallContext::multi_call_memory_ctx, ScanKeywordList::num_keywords, RESERVED_KEYWORD, ScanKeywordBareLabel, ScanKeywordCategories, ScanKeywords, SRF_FIRSTCALL_INIT, SRF_IS_FIRSTCALL, SRF_PERCALL_SETUP, SRF_RETURN_DONE, SRF_RETURN_NEXT, TupleDescGetAttInMetadata(), TupleDescInitEntry(), TYPE_FUNC_NAME_KEYWORD, unconstify, UNRESERVED_KEYWORD, and values.

411 {
412  FuncCallContext *funcctx;
413 
414  if (SRF_IS_FIRSTCALL())
415  {
416  MemoryContext oldcontext;
417  TupleDesc tupdesc;
418 
419  funcctx = SRF_FIRSTCALL_INIT();
420  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
421 
422  tupdesc = CreateTemplateTupleDesc(5);
423  TupleDescInitEntry(tupdesc, (AttrNumber) 1, "word",
424  TEXTOID, -1, 0);
425  TupleDescInitEntry(tupdesc, (AttrNumber) 2, "catcode",
426  CHAROID, -1, 0);
427  TupleDescInitEntry(tupdesc, (AttrNumber) 3, "barelabel",
428  BOOLOID, -1, 0);
429  TupleDescInitEntry(tupdesc, (AttrNumber) 4, "catdesc",
430  TEXTOID, -1, 0);
431  TupleDescInitEntry(tupdesc, (AttrNumber) 5, "baredesc",
432  TEXTOID, -1, 0);
433 
434  funcctx->attinmeta = TupleDescGetAttInMetadata(tupdesc);
435 
436  MemoryContextSwitchTo(oldcontext);
437  }
438 
439  funcctx = SRF_PERCALL_SETUP();
440 
441  if (funcctx->call_cntr < ScanKeywords.num_keywords)
442  {
443  char *values[5];
444  HeapTuple tuple;
445 
446  /* cast-away-const is ugly but alternatives aren't much better */
447  values[0] = unconstify(char *,
448  GetScanKeyword(funcctx->call_cntr,
449  &ScanKeywords));
450 
451  switch (ScanKeywordCategories[funcctx->call_cntr])
452  {
453  case UNRESERVED_KEYWORD:
454  values[1] = "U";
455  values[3] = _("unreserved");
456  break;
457  case COL_NAME_KEYWORD:
458  values[1] = "C";
459  values[3] = _("unreserved (cannot be function or type name)");
460  break;
462  values[1] = "T";
463  values[3] = _("reserved (can be function or type name)");
464  break;
465  case RESERVED_KEYWORD:
466  values[1] = "R";
467  values[3] = _("reserved");
468  break;
469  default: /* shouldn't be possible */
470  values[1] = NULL;
471  values[3] = NULL;
472  break;
473  }
474 
475  if (ScanKeywordBareLabel[funcctx->call_cntr])
476  {
477  values[2] = "true";
478  values[4] = _("can be bare label");
479  }
480  else
481  {
482  values[2] = "false";
483  values[4] = _("requires AS");
484  }
485 
486  tuple = BuildTupleFromCStrings(funcctx->attinmeta, values);
487 
488  SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tuple));
489  }
490 
491  SRF_RETURN_DONE(funcctx);
492 }
uint64 call_cntr
Definition: funcapi.h:65
TupleDesc CreateTemplateTupleDesc(int natts)
Definition: tupdesc.c:45
#define SRF_IS_FIRSTCALL()
Definition: funcapi.h:294
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
const uint8 ScanKeywordCategories[SCANKEYWORDS_NUM_KEYWORDS]
Definition: keywords.c:29
#define UNRESERVED_KEYWORD
Definition: keywords.h:20
#define SRF_PERCALL_SETUP()
Definition: funcapi.h:298
static const char * GetScanKeyword(int n, const ScanKeywordList *keywords)
Definition: kwlookup.h:39
HeapTuple BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values)
Definition: execTuples.c:2116
PGDLLIMPORT const ScanKeywordList ScanKeywords
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition: funcapi.h:300
#define TYPE_FUNC_NAME_KEYWORD
Definition: keywords.h:22
AttInMetadata * attinmeta
Definition: funcapi.h:91
const bool ScanKeywordBareLabel[SCANKEYWORDS_NUM_KEYWORDS]
Definition: keywords.c:42
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition: tupdesc.c:580
#define unconstify(underlying_type, expr)
Definition: c.h:1243
int num_keywords
Definition: kwlookup.h:30
AttInMetadata * TupleDescGetAttInMetadata(TupleDesc tupdesc)
Definition: execTuples.c:2067
#define RESERVED_KEYWORD
Definition: keywords.h:23
MemoryContext multi_call_memory_ctx
Definition: funcapi.h:101
#define HeapTupleGetDatum(tuple)
Definition: funcapi.h:221
#define COL_NAME_KEYWORD
Definition: keywords.h:21
static Datum values[MAXATTR]
Definition: bootstrap.c:166
int16 AttrNumber
Definition: attnum.h:21
#define _(x)
Definition: elog.c:89
#define SRF_RETURN_DONE(_funcctx)
Definition: funcapi.h:318
#define SRF_FIRSTCALL_INIT()
Definition: funcapi.h:296

◆ pg_get_replica_identity_index()

Datum pg_get_replica_identity_index ( PG_FUNCTION_ARGS  )

Definition at line 932 of file misc.c.

References AccessShareLock, OidIsValid, PG_GETARG_OID, PG_RETURN_NULL, PG_RETURN_OID, RelationGetReplicaIndex(), table_close(), and table_open().

933 {
934  Oid reloid = PG_GETARG_OID(0);
935  Oid idxoid;
936  Relation rel;
937 
938  rel = table_open(reloid, AccessShareLock);
939  idxoid = RelationGetReplicaIndex(rel);
941 
942  if (OidIsValid(idxoid))
943  PG_RETURN_OID(idxoid);
944  else
945  PG_RETURN_NULL();
946 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
Oid RelationGetReplicaIndex(Relation relation)
Definition: relcache.c:4760
#define AccessShareLock
Definition: lockdefs.h:36
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:710
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define PG_RETURN_OID(x)
Definition: fmgr.h:360
#define PG_RETURN_NULL()
Definition: fmgr.h:345

◆ pg_num_nonnulls()

Datum pg_num_nonnulls ( PG_FUNCTION_ARGS  )

Definition at line 156 of file misc.c.

References count_nulls(), PG_RETURN_INT32, and PG_RETURN_NULL.

157 {
158  int32 nargs,
159  nulls;
160 
161  if (!count_nulls(fcinfo, &nargs, &nulls))
162  PG_RETURN_NULL();
163 
164  PG_RETURN_INT32(nargs - nulls);
165 }
static bool count_nulls(FunctionCallInfo fcinfo, int32 *nargs, int32 *nulls)
Definition: misc.c:54
#define PG_RETURN_INT32(x)
Definition: fmgr.h:354
signed int int32
Definition: c.h:429
#define PG_RETURN_NULL()
Definition: fmgr.h:345

◆ pg_num_nulls()

Datum pg_num_nulls ( PG_FUNCTION_ARGS  )

Definition at line 140 of file misc.c.

References count_nulls(), PG_RETURN_INT32, and PG_RETURN_NULL.

141 {
142  int32 nargs,
143  nulls;
144 
145  if (!count_nulls(fcinfo, &nargs, &nulls))
146  PG_RETURN_NULL();
147 
148  PG_RETURN_INT32(nulls);
149 }
static bool count_nulls(FunctionCallInfo fcinfo, int32 *nargs, int32 *nulls)
Definition: misc.c:54
#define PG_RETURN_INT32(x)
Definition: fmgr.h:354
signed int int32
Definition: c.h:429
#define PG_RETURN_NULL()
Definition: fmgr.h:345

◆ pg_relation_is_updatable()

Datum pg_relation_is_updatable ( PG_FUNCTION_ARGS  )

Definition at line 617 of file misc.c.

References NIL, PG_GETARG_BOOL, PG_GETARG_OID, PG_RETURN_INT32, and relation_is_updatable().

618 {
619  Oid reloid = PG_GETARG_OID(0);
620  bool include_triggers = PG_GETARG_BOOL(1);
621 
622  PG_RETURN_INT32(relation_is_updatable(reloid, NIL, include_triggers, NULL));
623 }
#define NIL
Definition: pg_list.h:65
#define PG_RETURN_INT32(x)
Definition: fmgr.h:354
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:274
unsigned int Oid
Definition: postgres_ext.h:31
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
int relation_is_updatable(Oid reloid, List *outer_reloids, bool include_triggers, Bitmapset *include_cols)

◆ pg_sleep()

Datum pg_sleep ( PG_FUNCTION_ARGS  )

Definition at line 362 of file misc.c.

References CHECK_FOR_INTERRUPTS, GetNowFloat, MyLatch, PG_GETARG_FLOAT8, PG_RETURN_VOID, ResetLatch(), WAIT_EVENT_PG_SLEEP, WaitLatch(), WL_EXIT_ON_PM_DEATH, WL_LATCH_SET, and WL_TIMEOUT.

363 {
364  float8 secs = PG_GETARG_FLOAT8(0);
365  float8 endtime;
366 
367  /*
368  * We sleep using WaitLatch, to ensure that we'll wake up promptly if an
369  * important signal (such as SIGALRM or SIGINT) arrives. Because
370  * WaitLatch's upper limit of delay is INT_MAX milliseconds, and the user
371  * might ask for more than that, we sleep for at most 10 minutes and then
372  * loop.
373  *
374  * By computing the intended stop time initially, we avoid accumulation of
375  * extra delay across multiple sleeps. This also ensures we won't delay
376  * less than the specified time when WaitLatch is terminated early by a
377  * non-query-canceling signal such as SIGHUP.
378  */
379 #define GetNowFloat() ((float8) GetCurrentTimestamp() / 1000000.0)
380 
381  endtime = GetNowFloat() + secs;
382 
383  for (;;)
384  {
385  float8 delay;
386  long delay_ms;
387 
389 
390  delay = endtime - GetNowFloat();
391  if (delay >= 600.0)
392  delay_ms = 600000;
393  else if (delay > 0.0)
394  delay_ms = (long) ceil(delay * 1000.0);
395  else
396  break;
397 
398  (void) WaitLatch(MyLatch,
400  delay_ms,
403  }
404 
405  PG_RETURN_VOID();
406 }
#define PG_GETARG_FLOAT8(n)
Definition: fmgr.h:282
#define WL_TIMEOUT
Definition: latch.h:128
void ResetLatch(Latch *latch)
Definition: latch.c:660
int WaitLatch(Latch *latch, int wakeEvents, long timeout, uint32 wait_event_info)
Definition: latch.c:452
#define GetNowFloat()
double float8
Definition: c.h:565
#define PG_RETURN_VOID()
Definition: fmgr.h:349
struct Latch * MyLatch
Definition: globals.c:57
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:102
#define WL_LATCH_SET
Definition: latch.h:125
#define WL_EXIT_ON_PM_DEATH
Definition: latch.h:130

◆ pg_tablespace_databases()

Datum pg_tablespace_databases ( PG_FUNCTION_ARGS  )

Definition at line 202 of file misc.c.

References AllocateDir(), ReturnSetInfo::allowedModes, atooid, CreateTemplateTupleDesc(), directory_is_empty(), ReturnSetInfo::econtext, ExprContext::ecxt_per_query_memory, ereport, errcode(), errcode_for_file_access(), errmsg(), ERROR, FreeDir(), IsA, MemoryContextSwitchTo(), ObjectIdGetDatum, pfree(), PG_GETARG_OID, psprintf(), ReadDir(), ReturnSetInfo::returnMode, ReturnSetInfo::setDesc, ReturnSetInfo::setResult, SFRM_Materialize, SFRM_Materialize_Random, TABLESPACE_VERSION_DIRECTORY, TupleDescInitEntry(), tuplestore_begin_heap(), tuplestore_putvalues(), values, WARNING, and work_mem.

203 {
204  Oid tablespaceOid = PG_GETARG_OID(0);
205  ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
206  bool randomAccess;
207  TupleDesc tupdesc;
208  Tuplestorestate *tupstore;
209  char *location;
210  DIR *dirdesc;
211  struct dirent *de;
212  MemoryContext oldcontext;
213 
214  /* check to see if caller supports us returning a tuplestore */
215  if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
216  ereport(ERROR,
217  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
218  errmsg("set-valued function called in context that cannot accept a set")));
219  if (!(rsinfo->allowedModes & SFRM_Materialize))
220  ereport(ERROR,
221  (errcode(ERRCODE_SYNTAX_ERROR),
222  errmsg("materialize mode required, but it is not allowed in this context")));
223 
224  /* The tupdesc and tuplestore must be created in ecxt_per_query_memory */
226 
227  tupdesc = CreateTemplateTupleDesc(1);
228  TupleDescInitEntry(tupdesc, (AttrNumber) 1, "pg_tablespace_databases",
229  OIDOID, -1, 0);
230 
231  randomAccess = (rsinfo->allowedModes & SFRM_Materialize_Random) != 0;
232  tupstore = tuplestore_begin_heap(randomAccess, false, work_mem);
233 
234  rsinfo->returnMode = SFRM_Materialize;
235  rsinfo->setResult = tupstore;
236  rsinfo->setDesc = tupdesc;
237 
238  MemoryContextSwitchTo(oldcontext);
239 
240  if (tablespaceOid == GLOBALTABLESPACE_OID)
241  {
243  (errmsg("global tablespace never has databases")));
244  /* return empty tuplestore */
245  return (Datum) 0;
246  }
247 
248  if (tablespaceOid == DEFAULTTABLESPACE_OID)
249  location = psprintf("base");
250  else
251  location = psprintf("pg_tblspc/%u/%s", tablespaceOid,
253 
254  dirdesc = AllocateDir(location);
255 
256  if (!dirdesc)
257  {
258  /* the only expected error is ENOENT */
259  if (errno != ENOENT)
260  ereport(ERROR,
262  errmsg("could not open directory \"%s\": %m",
263  location)));
265  (errmsg("%u is not a tablespace OID", tablespaceOid)));
266  /* return empty tuplestore */
267  return (Datum) 0;
268  }
269 
270  while ((de = ReadDir(dirdesc, location)) != NULL)
271  {
272  Oid datOid = atooid(de->d_name);
273  char *subdir;
274  bool isempty;
275  Datum values[1];
276  bool nulls[1];
277 
278  /* this test skips . and .., but is awfully weak */
279  if (!datOid)
280  continue;
281 
282  /* if database subdir is empty, don't report tablespace as used */
283 
284  subdir = psprintf("%s/%s", location, de->d_name);
285  isempty = directory_is_empty(subdir);
286  pfree(subdir);
287 
288  if (isempty)
289  continue; /* indeed, nothing in it */
290 
291  values[0] = ObjectIdGetDatum(datOid);
292  nulls[0] = false;
293 
294  tuplestore_putvalues(tupstore, tupdesc, values, nulls);
295  }
296 
297  FreeDir(dirdesc);
298  return (Datum) 0;
299 }
void tuplestore_putvalues(Tuplestorestate *state, TupleDesc tdesc, Datum *values, bool *isnull)
Definition: tuplestore.c:750
#define IsA(nodeptr, _type_)
Definition: nodes.h:590
TupleDesc CreateTemplateTupleDesc(int natts)
Definition: tupdesc.c:45
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int errcode(int sqlerrcode)
Definition: elog.c:698
bool directory_is_empty(const char *path)
Definition: tablespace.c:858
unsigned int Oid
Definition: postgres_ext.h:31
Definition: dirent.h:9
void pfree(void *pointer)
Definition: mcxt.c:1169
Definition: dirent.c:25
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
#define TABLESPACE_VERSION_DIRECTORY
Definition: relpath.h:26
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
int errcode_for_file_access(void)
Definition: elog.c:721
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2634
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition: tupdesc.c:580
#define atooid(x)
Definition: postgres_ext.h:42
#define WARNING
Definition: elog.h:40
Tuplestorestate * tuplestore_begin_heap(bool randomAccess, bool interXact, int maxKBytes)
Definition: tuplestore.c:318
uintptr_t Datum
Definition: postgres.h:411
int work_mem
Definition: globals.c:124
#define ereport(elevel,...)
Definition: elog.h:157
int allowedModes
Definition: execnodes.h:305
SetFunctionReturnMode returnMode
Definition: execnodes.h:307
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2700
MemoryContext ecxt_per_query_memory
Definition: execnodes.h:233
Tuplestorestate * setResult
Definition: execnodes.h:310
static Datum values[MAXATTR]
Definition: bootstrap.c:166
ExprContext * econtext
Definition: execnodes.h:303
TupleDesc setDesc
Definition: execnodes.h:311
int errmsg(const char *fmt,...)
Definition: elog.c:909
int16 AttrNumber
Definition: attnum.h:21
int FreeDir(DIR *dir)
Definition: fd.c:2752

◆ pg_tablespace_location()

Datum pg_tablespace_location ( PG_FUNCTION_ARGS  )

Definition at line 306 of file misc.c.

References cstring_to_text(), ereport, errcode(), errcode_for_file_access(), errmsg(), ERROR, InvalidOid, MAXPGPATH, MyDatabaseTableSpace, PG_GETARG_OID, PG_RETURN_NULL, PG_RETURN_TEXT_P, readlink, and snprintf.

307 {
308  Oid tablespaceOid = PG_GETARG_OID(0);
309  char sourcepath[MAXPGPATH];
310  char targetpath[MAXPGPATH];
311  int rllen;
312 
313  /*
314  * It's useful to apply this function to pg_class.reltablespace, wherein
315  * zero means "the database's default tablespace". So, rather than
316  * throwing an error for zero, we choose to assume that's what is meant.
317  */
318  if (tablespaceOid == InvalidOid)
319  tablespaceOid = MyDatabaseTableSpace;
320 
321  /*
322  * Return empty string for the cluster's default tablespaces
323  */
324  if (tablespaceOid == DEFAULTTABLESPACE_OID ||
325  tablespaceOid == GLOBALTABLESPACE_OID)
327 
328 #if defined(HAVE_READLINK) || defined(WIN32)
329 
330  /*
331  * Find the location of the tablespace by reading the symbolic link that
332  * is in pg_tblspc/<oid>.
333  */
334  snprintf(sourcepath, sizeof(sourcepath), "pg_tblspc/%u", tablespaceOid);
335 
336  rllen = readlink(sourcepath, targetpath, sizeof(targetpath));
337  if (rllen < 0)
338  ereport(ERROR,
340  errmsg("could not read symbolic link \"%s\": %m",
341  sourcepath)));
342  if (rllen >= sizeof(targetpath))
343  ereport(ERROR,
344  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
345  errmsg("symbolic link \"%s\" target is too long",
346  sourcepath)));
347  targetpath[rllen] = '\0';
348 
349  PG_RETURN_TEXT_P(cstring_to_text(targetpath));
350 #else
351  ereport(ERROR,
352  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
353  errmsg("tablespaces are not supported on this platform")));
354  PG_RETURN_NULL();
355 #endif
356 }
int errcode(int sqlerrcode)
Definition: elog.c:698
unsigned int Oid
Definition: postgres_ext.h:31
Oid MyDatabaseTableSpace
Definition: globals.c:90
#define ERROR
Definition: elog.h:46
#define MAXPGPATH
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
#define readlink(path, buf, size)
Definition: win32_port.h:228
int errcode_for_file_access(void)
Definition: elog.c:721
#define InvalidOid
Definition: postgres_ext.h:36
#define ereport(elevel,...)
Definition: elog.h:157
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:372
text * cstring_to_text(const char *s)
Definition: varlena.c:190
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define snprintf
Definition: port.h:216
#define PG_RETURN_NULL()
Definition: fmgr.h:345

◆ pg_typeof()

Datum pg_typeof ( PG_FUNCTION_ARGS  )

Definition at line 577 of file misc.c.

References get_fn_expr_argtype(), and PG_RETURN_OID.

578 {
579  PG_RETURN_OID(get_fn_expr_argtype(fcinfo->flinfo, 0));
580 }
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:1803
#define PG_RETURN_OID(x)
Definition: fmgr.h:360