1 /*-------------------------------------------------------------------------
6 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * src/backend/utils/adt/misc.c
13 *-------------------------------------------------------------------------
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"
33 #include "miscadmin.h"
34 #include "nodes/miscnodes.h"
35 #include "parser/parse_type.h"
36 #include "parser/scansup.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"
52 * structure to cache metadata needed in pg_input_is_valid_common
54 typedef struct ValidIOData
58 bool typname_constant
;
64 static bool pg_input_is_valid_common(FunctionCallInfo fcinfo
,
65 text
*txt
, text
*typname
,
66 ErrorSaveContext
*escontext
);
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.
76 count_nulls(FunctionCallInfo fcinfo
,
77 int32
*nargs
, int32
*nulls
)
82 /* Did we get a VARIADIC array argument, or separate arguments? */
83 if (get_fn_expr_variadic(fcinfo
->flinfo
))
91 Assert(PG_NARGS() == 1);
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.
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.
108 Assert(OidIsValid(get_base_element_type(get_fn_expr_argtype(fcinfo
->flinfo
, 0))));
110 /* OK, safe to fetch the array value */
111 arr
= PG_GETARG_ARRAYTYPE_P(0);
113 /* Count the array elements */
114 ndims
= ARR_NDIM(arr
);
115 dims
= ARR_DIMS(arr
);
116 nitems
= ArrayGetNItems(ndims
, dims
);
118 /* Count those that are NULL */
119 bitmap
= ARR_NULLBITMAP(arr
);
124 for (i
= 0; i
< nitems
; i
++)
126 if ((*bitmap
& bitmask
) == 0)
130 if (bitmask
== 0x100)
143 /* Separate arguments, so just count 'em */
144 for (i
= 0; i
< PG_NARGS(); i
++)
159 * Count the number of NULL arguments
162 pg_num_nulls(PG_FUNCTION_ARGS
)
167 if (!count_nulls(fcinfo
, &nargs
, &nulls
))
170 PG_RETURN_INT32(nulls
);
175 * Count the number of non-NULL arguments
178 pg_num_nonnulls(PG_FUNCTION_ARGS
)
183 if (!count_nulls(fcinfo
, &nargs
, &nulls
))
186 PG_RETURN_INT32(nargs
- nulls
);
192 * Expose the current database to the user
195 current_database(PG_FUNCTION_ARGS
)
199 db
= (Name
) palloc(NAMEDATALEN
);
201 namestrcpy(db
, get_database_name(MyDatabaseId
));
208 * Expose the current query to the user (useful in stored procedures)
209 * We might want to use ActivePortal->sourceText someday.
212 current_query(PG_FUNCTION_ARGS
)
214 /* there is no easy way to access the more concise 'query_string' */
215 if (debug_query_string
)
216 PG_RETURN_TEXT_P(cstring_to_text(debug_query_string
));
221 /* Function to find out which databases make use of a tablespace */
224 pg_tablespace_databases(PG_FUNCTION_ARGS
)
226 Oid tablespaceOid
= PG_GETARG_OID(0);
227 ReturnSetInfo
*rsinfo
= (ReturnSetInfo
*) fcinfo
->resultinfo
;
232 InitMaterializedSRF(fcinfo
, MAT_SRF_USE_EXPECTED_DESC
);
234 if (tablespaceOid
== GLOBALTABLESPACE_OID
)
237 (errmsg("global tablespace never has databases")));
238 /* return empty tuplestore */
242 if (tablespaceOid
== DEFAULTTABLESPACE_OID
)
245 location
= psprintf("%s/%u/%s", PG_TBLSPC_DIR
, tablespaceOid
,
246 TABLESPACE_VERSION_DIRECTORY
);
248 dirdesc
= AllocateDir(location
);
252 /* the only expected error is ENOENT */
255 (errcode_for_file_access(),
256 errmsg("could not open directory \"%s\": %m",
259 (errmsg("%u is not a tablespace OID", tablespaceOid
)));
260 /* return empty tuplestore */
264 while ((de
= ReadDir(dirdesc
, location
)) != NULL
)
266 Oid datOid
= atooid(de
->d_name
);
272 /* this test skips . and .., but is awfully weak */
276 /* if database subdir is empty, don't report tablespace as used */
278 subdir
= psprintf("%s/%s", location
, de
->d_name
);
279 isempty
= directory_is_empty(subdir
);
283 continue; /* indeed, nothing in it */
285 values
[0] = ObjectIdGetDatum(datOid
);
288 tuplestore_putvalues(rsinfo
->setResult
, rsinfo
->setDesc
,
298 * pg_tablespace_location - get location for a tablespace
301 pg_tablespace_location(PG_FUNCTION_ARGS
)
303 Oid tablespaceOid
= PG_GETARG_OID(0);
304 char sourcepath
[MAXPGPATH
];
305 char targetpath
[MAXPGPATH
];
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.
314 if (tablespaceOid
== InvalidOid
)
315 tablespaceOid
= MyDatabaseTableSpace
;
318 * Return empty string for the cluster's default tablespaces
320 if (tablespaceOid
== DEFAULTTABLESPACE_OID
||
321 tablespaceOid
== GLOBALTABLESPACE_OID
)
322 PG_RETURN_TEXT_P(cstring_to_text(""));
325 * Find the location of the tablespace by reading the symbolic link that
326 * is in pg_tblspc/<oid>.
328 snprintf(sourcepath
, sizeof(sourcepath
), "%s/%u", PG_TBLSPC_DIR
, tablespaceOid
);
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.
336 if (lstat(sourcepath
, &st
) < 0)
339 (errcode_for_file_access(),
340 errmsg("could not stat file \"%s\": %m",
344 if (!S_ISLNK(st
.st_mode
))
345 PG_RETURN_TEXT_P(cstring_to_text(sourcepath
));
348 * In presence of a link or a junction point, return the path pointing to.
350 rllen
= readlink(sourcepath
, targetpath
, sizeof(targetpath
));
353 (errcode_for_file_access(),
354 errmsg("could not read symbolic link \"%s\": %m",
356 if (rllen
>= sizeof(targetpath
))
358 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED
),
359 errmsg("symbolic link \"%s\" target is too long",
361 targetpath
[rllen
] = '\0';
363 PG_RETURN_TEXT_P(cstring_to_text(targetpath
));
367 * pg_sleep - delay for N seconds
370 pg_sleep(PG_FUNCTION_ARGS
)
372 float8 secs
= PG_GETARG_FLOAT8(0);
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
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.
387 #define GetNowFloat() ((float8) GetCurrentTimestamp() / 1000000.0)
389 endtime
= GetNowFloat() + secs
;
396 CHECK_FOR_INTERRUPTS();
398 delay
= endtime
- GetNowFloat();
401 else if (delay
> 0.0)
402 delay_ms
= (long) ceil(delay
* 1000.0);
406 (void) WaitLatch(MyLatch
,
407 WL_LATCH_SET
| WL_TIMEOUT
| WL_EXIT_ON_PM_DEATH
,
409 WAIT_EVENT_PG_SLEEP
);
416 /* Function to return the list of grammar keywords */
418 pg_get_keywords(PG_FUNCTION_ARGS
)
420 FuncCallContext
*funcctx
;
422 if (SRF_IS_FIRSTCALL())
424 MemoryContext oldcontext
;
427 funcctx
= SRF_FIRSTCALL_INIT();
428 oldcontext
= MemoryContextSwitchTo(funcctx
->multi_call_memory_ctx
);
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
);
435 MemoryContextSwitchTo(oldcontext
);
438 funcctx
= SRF_PERCALL_SETUP();
440 if (funcctx
->call_cntr
< ScanKeywords
.num_keywords
)
445 /* cast-away-const is ugly but alternatives aren't much better */
446 values
[0] = unconstify(char *,
447 GetScanKeyword(funcctx
->call_cntr
,
450 switch (ScanKeywordCategories
[funcctx
->call_cntr
])
452 case UNRESERVED_KEYWORD
:
454 values
[3] = _("unreserved");
456 case COL_NAME_KEYWORD
:
458 values
[3] = _("unreserved (cannot be function or type name)");
460 case TYPE_FUNC_NAME_KEYWORD
:
462 values
[3] = _("reserved (can be function or type name)");
464 case RESERVED_KEYWORD
:
466 values
[3] = _("reserved");
468 default: /* shouldn't be possible */
474 if (ScanKeywordBareLabel
[funcctx
->call_cntr
])
477 values
[4] = _("can be bare label");
482 values
[4] = _("requires AS");
485 tuple
= BuildTupleFromCStrings(funcctx
->attinmeta
, values
);
487 SRF_RETURN_NEXT(funcctx
, HeapTupleGetDatum(tuple
));
490 SRF_RETURN_DONE(funcctx
);
494 /* Function to return the list of catalog foreign key relationships */
496 pg_get_catalog_foreign_keys(PG_FUNCTION_ARGS
)
498 FuncCallContext
*funcctx
;
501 if (SRF_IS_FIRSTCALL())
503 MemoryContext oldcontext
;
506 funcctx
= SRF_FIRSTCALL_INIT();
507 oldcontext
= MemoryContextSwitchTo(funcctx
->multi_call_memory_ctx
);
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
);
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.
519 arrayinp
= (FmgrInfo
*) palloc(sizeof(FmgrInfo
));
520 fmgr_info(F_ARRAY_IN
, arrayinp
);
521 funcctx
->user_fctx
= arrayinp
;
523 MemoryContextSwitchTo(oldcontext
);
526 funcctx
= SRF_PERCALL_SETUP();
527 arrayinp
= (FmgrInfo
*) funcctx
->user_fctx
;
529 if (funcctx
->call_cntr
< lengthof(sys_fk_relationships
))
531 const SysFKRelationship
*fkrel
= &sys_fk_relationships
[funcctx
->call_cntr
];
536 memset(nulls
, false, sizeof(nulls
));
538 values
[0] = ObjectIdGetDatum(fkrel
->fk_table
);
539 values
[1] = FunctionCall3(arrayinp
,
540 CStringGetDatum(fkrel
->fk_columns
),
541 ObjectIdGetDatum(TEXTOID
),
543 values
[2] = ObjectIdGetDatum(fkrel
->pk_table
);
544 values
[3] = FunctionCall3(arrayinp
,
545 CStringGetDatum(fkrel
->pk_columns
),
546 ObjectIdGetDatum(TEXTOID
),
548 values
[4] = BoolGetDatum(fkrel
->is_array
);
549 values
[5] = BoolGetDatum(fkrel
->is_opt
);
551 tuple
= heap_form_tuple(funcctx
->tuple_desc
, values
, nulls
);
553 SRF_RETURN_NEXT(funcctx
, HeapTupleGetDatum(tuple
));
556 SRF_RETURN_DONE(funcctx
);
561 * Return the type of the argument.
564 pg_typeof(PG_FUNCTION_ARGS
)
566 PG_RETURN_OID(get_fn_expr_argtype(fcinfo
->flinfo
, 0));
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.
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.
583 pg_basetype(PG_FUNCTION_ARGS
)
585 Oid typid
= PG_GETARG_OID(0);
588 * We loop to find the bottom base type in a stack of domains.
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
)
601 /* Not a domain, so done */
602 ReleaseSysCache(tup
);
606 typid
= typTup
->typbasetype
;
607 ReleaseSysCache(tup
);
610 PG_RETURN_OID(typid
);
615 * Implementation of the COLLATE FOR expression; returns the collation
619 pg_collation_for(PG_FUNCTION_ARGS
)
624 typeid = get_fn_expr_argtype(fcinfo
->flinfo
, 0);
627 if (!type_is_collatable(typeid) && typeid != UNKNOWNOID
)
629 (errcode(ERRCODE_DATATYPE_MISMATCH
),
630 errmsg("collations are not supported by type %s",
631 format_type_be(typeid))));
633 collid
= PG_GET_COLLATION();
636 PG_RETURN_TEXT_P(cstring_to_text(generate_collation_name(collid
)));
641 * pg_relation_is_updatable - determine which update events the specified
644 * This relies on relation_is_updatable() in rewriteHandler.c, which see
645 * for additional information.
648 pg_relation_is_updatable(PG_FUNCTION_ARGS
)
650 Oid reloid
= PG_GETARG_OID(0);
651 bool include_triggers
= PG_GETARG_BOOL(1);
653 PG_RETURN_INT32(relation_is_updatable(reloid
, NIL
, include_triggers
, NULL
));
657 * pg_column_is_updatable - determine whether a column is updatable
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.
665 pg_column_is_updatable(PG_FUNCTION_ARGS
)
667 Oid reloid
= PG_GETARG_OID(0);
668 AttrNumber attnum
= PG_GETARG_INT16(1);
669 AttrNumber col
= attnum
- FirstLowInvalidHeapAttributeNumber
;
670 bool include_triggers
= PG_GETARG_BOOL(2);
673 /* System columns are never updatable */
675 PG_RETURN_BOOL(false);
677 events
= relation_is_updatable(reloid
, NIL
, include_triggers
,
678 bms_make_singleton(col
));
680 /* We require both updatability and deletability of the relation */
681 #define REQ_EVENTS ((1 << CMD_UPDATE) | (1 << CMD_DELETE))
683 PG_RETURN_BOOL((events
& REQ_EVENTS
) == REQ_EVENTS
);
688 * pg_input_is_valid - test whether string is valid input for datatype.
690 * Returns true if OK, false if not.
692 * This will only work usefully if the datatype's input function has been
693 * updated to return "soft" errors via errsave/ereturn.
696 pg_input_is_valid(PG_FUNCTION_ARGS
)
698 text
*txt
= PG_GETARG_TEXT_PP(0);
699 text
*typname
= PG_GETARG_TEXT_PP(1);
700 ErrorSaveContext escontext
= {T_ErrorSaveContext
};
702 PG_RETURN_BOOL(pg_input_is_valid_common(fcinfo
, txt
, typname
,
707 * pg_input_error_info - test whether string is valid input for datatype.
709 * Returns NULL if OK, else the primary message, detail message, hint message
710 * and sql error code from the error.
712 * This will only work usefully if the datatype's input function has been
713 * updated to return "soft" errors via errsave/ereturn.
716 pg_input_error_info(PG_FUNCTION_ARGS
)
718 text
*txt
= PG_GETARG_TEXT_PP(0);
719 text
*typname
= PG_GETARG_TEXT_PP(1);
720 ErrorSaveContext escontext
= {T_ErrorSaveContext
};
725 if (get_call_result_type(fcinfo
, NULL
, &tupdesc
) != TYPEFUNC_COMPOSITE
)
726 elog(ERROR
, "return type must be a row type");
728 /* Enable details_wanted */
729 escontext
.details_wanted
= true;
731 if (pg_input_is_valid_common(fcinfo
, txt
, typname
,
733 memset(isnull
, true, sizeof(isnull
));
738 Assert(escontext
.error_occurred
);
739 Assert(escontext
.error_data
!= NULL
);
740 Assert(escontext
.error_data
->message
!= NULL
);
742 memset(isnull
, false, sizeof(isnull
));
744 values
[0] = CStringGetTextDatum(escontext
.error_data
->message
);
746 if (escontext
.error_data
->detail
!= NULL
)
747 values
[1] = CStringGetTextDatum(escontext
.error_data
->detail
);
751 if (escontext
.error_data
->hint
!= NULL
)
752 values
[2] = CStringGetTextDatum(escontext
.error_data
->hint
);
756 sqlstate
= unpack_sql_state(escontext
.error_data
->sqlerrcode
);
757 values
[3] = CStringGetTextDatum(sqlstate
);
760 return HeapTupleGetDatum(heap_form_tuple(tupdesc
, values
, isnull
));
763 /* Common subroutine for the above */
765 pg_input_is_valid_common(FunctionCallInfo fcinfo
,
766 text
*txt
, text
*typname
,
767 ErrorSaveContext
*escontext
)
769 char *str
= text_to_cstring(txt
);
770 ValidIOData
*my_extra
;
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.
777 my_extra
= (ValidIOData
*) fcinfo
->flinfo
->fn_extra
;
778 if (my_extra
== NULL
)
780 fcinfo
->flinfo
->fn_extra
=
781 MemoryContextAlloc(fcinfo
->flinfo
->fn_mcxt
,
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);
790 * If the typname argument is constant, we only need to parse it the first
793 if (my_extra
->typoid
== InvalidOid
|| !my_extra
->typname_constant
)
795 char *typnamestr
= text_to_cstring(typname
);
798 /* Parse type-name argument to obtain type OID and encoded typmod. */
799 (void) parseTypeString(typnamestr
, &typoid
, &my_extra
->typmod
, NULL
);
801 /* Update type-specific info if typoid changed. */
802 if (my_extra
->typoid
!= typoid
)
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
;
813 /* Now we can try to perform the conversion. */
814 return InputFunctionCallSafe(&my_extra
->inputproc
,
816 my_extra
->typioparam
,
824 * Is character a valid identifier start?
825 * Must match scan.l's {ident_start} character class.
828 is_ident_start(unsigned char c
)
830 /* Underscores and ASCII letters are OK */
833 if ((c
>= 'a' && c
<= 'z') || (c
>= 'A' && c
<= 'Z'))
835 /* Any high-bit-set character is OK (might be part of a multibyte char) */
836 if (IS_HIGHBIT_SET(c
))
842 * Is character a valid identifier continuation?
843 * Must match scan.l's {ident_cont} character class.
846 is_ident_cont(unsigned char c
)
848 /* Can be digit or dollar sign ... */
849 if ((c
>= '0' && c
<= '9') || c
== '$')
851 /* ... or an identifier start character */
852 return is_ident_start(c
);
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.
861 parse_ident(PG_FUNCTION_ARGS
)
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
;
868 bool after_dot
= false;
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
875 nextp
= qualname_str
;
877 /* skip leading whitespace */
878 while (scanner_isspace(*nextp
))
884 bool missing_ident
= true;
893 endp
= strchr(nextp
+ 1, '"');
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.")));
902 memmove(endp
, endp
+ 1, strlen(endp
));
908 if (endp
- curname
== 0)
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.")));
915 astate
= accumArrayResult(astate
, CStringGetTextDatum(curname
),
916 false, TEXTOID
, CurrentMemoryContext
);
917 missing_ident
= false;
919 else if (is_ident_start((unsigned char) *nextp
))
926 while (is_ident_cont((unsigned char) *nextp
))
929 len
= nextp
- curname
;
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[].
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;
946 /* Different error messages based on where we failed. */
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 \".\".")));
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 \".\".")));
961 (errcode(ERRCODE_INVALID_PARAMETER_VALUE
),
962 errmsg("string is not a valid identifier: \"%s\"",
963 text_to_cstring(qualname
))));
966 while (scanner_isspace(*nextp
))
973 while (scanner_isspace(*nextp
))
976 else if (*nextp
== '\0')
984 (errcode(ERRCODE_INVALID_PARAMETER_VALUE
),
985 errmsg("string is not a valid identifier: \"%s\"",
986 text_to_cstring(qualname
))));
991 PG_RETURN_DATUM(makeArrayResult(astate
, CurrentMemoryContext
));
997 * Report current log file used by log collector by scanning current_logfiles.
1000 pg_current_logfile(PG_FUNCTION_ARGS
)
1003 char lbuffer
[MAXPGPATH
];
1006 /* The log format parameter is optional */
1007 if (PG_NARGS() == 0 || PG_ARGISNULL(0))
1011 logfmt
= text_to_cstring(PG_GETARG_TEXT_PP(0));
1013 if (strcmp(logfmt
, "stderr") != 0 &&
1014 strcmp(logfmt
, "csvlog") != 0 &&
1015 strcmp(logfmt
, "jsonlog") != 0)
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\".")));
1022 fd
= AllocateFile(LOG_METAINFO_DATAFILE
, "r");
1025 if (errno
!= ENOENT
)
1027 (errcode_for_file_access(),
1028 errmsg("could not read file \"%s\": %m",
1029 LOG_METAINFO_DATAFILE
)));
1034 /* syslogger.c writes CRLF line endings on Windows */
1035 _setmode(_fileno(fd
), _O_TEXT
);
1039 * Read the file to gather current log filename(s) registered by the
1042 while (fgets(lbuffer
, sizeof(lbuffer
), fd
) != NULL
)
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
)
1053 /* Uh oh. No space found, so file content is corrupted. */
1055 "missing space character in \"%s\"", LOG_METAINFO_DATAFILE
);
1059 *log_filepath
= '\0';
1061 nlpos
= strchr(log_filepath
, '\n');
1064 /* Uh oh. No newline found, so file content is corrupted. */
1066 "missing newline character in \"%s\"", LOG_METAINFO_DATAFILE
);
1071 if (logfmt
== NULL
|| strcmp(logfmt
, log_format
) == 0)
1074 PG_RETURN_TEXT_P(cstring_to_text(log_filepath
));
1078 /* Close the current log filename file. */
1085 * Report current log file used by log collector (1 argument version)
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
1092 pg_current_logfile_1arg(PG_FUNCTION_ARGS
)
1094 return pg_current_logfile(fcinfo
);
1098 * SQL wrapper around RelationGetReplicaIndex().
1101 pg_get_replica_identity_index(PG_FUNCTION_ARGS
)
1103 Oid reloid
= PG_GETARG_OID(0);
1107 rel
= table_open(reloid
, AccessShareLock
);
1108 idxoid
= RelationGetReplicaIndex(rel
);
1109 table_close(rel
, AccessShareLock
);
1111 if (OidIsValid(idxoid
))
1112 PG_RETURN_OID(idxoid
);
1118 * Transition function for the ANY_VALUE aggregate
1121 any_value_transfn(PG_FUNCTION_ARGS
)
1123 PG_RETURN_DATUM(PG_GETARG_DATUM(0));