/* * Binary receive. */ Datum json_recv(PG_FUNCTION_ARGS) { StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); text *result; char *str; int nbytes; JsonLexContext *lex; str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes); result = palloc(nbytes + VARHDRSZ); SET_VARSIZE(result, nbytes + VARHDRSZ); memcpy(VARDATA(result), str, nbytes); /* Validate it. */ lex = makeJsonLexContext(result, false); pg_parse_json(lex, NullSemAction); PG_RETURN_TEXT_P(result); }
Datum utl_file_tmpdir(PG_FUNCTION_ARGS) { #ifndef WIN32 const char *tmpdir = getenv("TMPDIR"); if (!tmpdir) tmpdir = "/tmp"; #else char tmpdir[MAXPGPATH]; int ret; ret = GetTempPath(MAXPGPATH, tmpdir); if (ret == 0 || ret > MAXPGPATH) CUSTOM_EXCEPTION(INVALID_PATH, strerror(errno)); canonicalize_path(tmpdir); #endif PG_RETURN_TEXT_P(cstring_to_text(tmpdir)); }
Datum EnableXform(PG_FUNCTION_ARGS) { char *szXform = textToString(PG_GETARG_TEXT_P(0)); bool fResult = COptTasks::FSetXform(szXform, false /*fDisable*/); StringInfoData str; initStringInfo(&str); if (fResult) { appendStringInfo(&str, "%s is enabled", szXform); } else { appendStringInfo(&str, "%s is not recognized", szXform); } text *result = stringToText(str.data); PG_RETURN_TEXT_P(result); }
Datum ExecuteMinidumpFromFile(PG_FUNCTION_ARGS) { char *szFileName = textToString(PG_GETARG_TEXT_P(0)); char *szResultDXL = COptTasks::SzOptimizeMinidumpFromFile(szFileName); if (NULL == szResultDXL) { elog(NOTICE, "Execution of UDF 'ExecuteMinidumpFromFile' failed. Consult the LOG for more information."); // return a dummy value PG_RETURN_NULL(); } int iProcessed = executeXMLPlan(szResultDXL); gpdb::GPDBFree(szResultDXL); StringInfoData str; initStringInfo(&str); appendStringInfo(&str, "processed %d rows", iProcessed); text *ptResult = stringToText(str.data); PG_RETURN_TEXT_P(ptResult); }
Datum LWGEOM_to_text(PG_FUNCTION_ARGS) { GSERIALIZED *geom = (GSERIALIZED*)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); LWGEOM *lwgeom; char *hexwkb; size_t hexwkb_size; text *result; /* Generate WKB hex text */ lwgeom = lwgeom_from_gserialized(geom); hexwkb = lwgeom_to_hexwkb(lwgeom, WKB_EXTENDED, &hexwkb_size); lwgeom_free(lwgeom); /* Copy into text obect */ result = cstring2text(hexwkb); pfree(hexwkb); /* Clean up and return */ PG_FREE_IF_COPY(geom, 0); PG_RETURN_TEXT_P(result); }
Datum pgp_sym_encrypt_text(PG_FUNCTION_ARGS) { bytea *data, *key; text *arg = NULL; text *res; data = PG_GETARG_BYTEA_P(0); key = PG_GETARG_BYTEA_P(1); if (PG_NARGS() > 2) arg = PG_GETARG_BYTEA_P(2); res = encrypt_internal(0, 1, data, key, arg); PG_FREE_IF_COPY(data, 0); PG_FREE_IF_COPY(key, 1); if (PG_NARGS() > 2) PG_FREE_IF_COPY(arg, 2); PG_RETURN_TEXT_P(res); }
Datum get_group_name(PG_FUNCTION_ARGS) { int group_id = PG_GETARG_INT32(0); int ret = SPI_connect(); if (ret < 0) elog(ERROR, "get_group_name: SPI_connect returned %d", ret); char buf[1024]; sprintf(buf, "SELECT get_group_name_by_id(%d)", group_id); elog (INFO, "get_group_name: %s", buf); ret = SPI_exec(buf, 10); if (ret < 0) elog(ERROR, "get_group_name: SPI_exec returned %d", ret); else elog(INFO, "get_group_name: SPI_exec succeeded"); char *group_name = SPI_getvalue(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1); SPI_finish(); elog (INFO, "get_group_name: %s", group_name); text *result = 0; if (0 == group_name) { elog(ERROR, "get_group_name: SPI_getvalue returned null"); result = (text *)palloc(VARHDRSZ); SET_VARSIZE(result, VARHDRSZ); } else { int len = strlen(group_name); result = (text *)palloc(VARHDRSZ + len); SET_VARSIZE(result, VARHDRSZ + len); memcpy(VARDATA(result), group_name, len); } PG_RETURN_TEXT_P(result); }
Datum brin_page_type(PG_FUNCTION_ARGS) { bytea *raw_page = PG_GETARG_BYTEA_P(0); Page page = VARDATA(raw_page); int raw_page_size; char *type; if (!superuser()) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errmsg("must be superuser to use raw page functions")))); raw_page_size = VARSIZE(raw_page) - VARHDRSZ; if (raw_page_size != BLCKSZ) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("input page too small"), errdetail("Expected size %d, got %d", BLCKSZ, raw_page_size))); switch (BrinPageType(page)) { case BRIN_PAGETYPE_META: type = "meta"; break; case BRIN_PAGETYPE_REVMAP: type = "revmap"; break; case BRIN_PAGETYPE_REGULAR: type = "regular"; break; default: type = psprintf("unknown (%02x)", BrinPageType(page)); break; } PG_RETURN_TEXT_P(cstring_to_text(type)); }
Datum plvstr_rstrip (PG_FUNCTION_ARGS) { text *str = PG_GETARG_TEXT_PP(0); text *pat = PG_GETARG_TEXT_PP(1); int num = PG_GETARG_INT32(2); int count = 0; int len_p, len_s, i; char *str_p, *aux_str_p, *pat_p; len_p = VARSIZE_ANY_EXHDR(pat); len_s = VARSIZE_ANY_EXHDR(str); str_p = VARDATA_ANY(str) + len_s - 1; while (count < num) { pat_p = VARDATA_ANY(pat) + len_p - 1; aux_str_p = str_p; if (len_s < len_p) break; for (i = 0; i < len_p; i++) if (*aux_str_p-- != *pat_p--) break; if (i >= len_p) { count++; /* found */ str_p = aux_str_p; len_s -= len_p; continue; } break; } PG_RETURN_TEXT_P(cstring_to_text_with_len(VARDATA_ANY(str),len_s)); }
Datum dmetaphone(PG_FUNCTION_ARGS) { text *arg, *result; int alen, rsize; char *aptr, *codes[2], *code, *rptr; #ifdef DMETAPHONE_NOSTRICT if (PG_ARGISNULL(0)) PG_RETURNNULL(); #endif arg = PG_GETARG_TEXT_P(0); alen = VARSIZE(arg) - VARHDRSZ; /* * Postgres' string values might not have trailing nuls. The VARSIZE will * not include the nul in any case so we copy things out and add a * trailing nul. When we copy back we ignore the nul (and we don't make * space for it). */ aptr = palloc(alen + 1); memcpy(aptr, VARDATA(arg), alen); aptr[alen] = 0; DoubleMetaphone(aptr, codes); code = codes[0]; if (!code) code = ""; rsize = VARHDRSZ + strlen(code); result = (text *) palloc(rsize); rptr = VARDATA(result); memcpy(rptr, code, rsize - VARHDRSZ); SET_VARSIZE(result, rsize); PG_RETURN_TEXT_P(result); }
/** * @fn Datum repack_indexdef(PG_FUNCTION_ARGS) * @brief Reproduce DDL that create index at the temp table. * * repack_indexdef(index, table) * * @param index Oid of target index. * @param table Oid of table of the index. * @param tablespace Namespace for the index. If NULL keep the original. * @param boolean Whether to use CONCURRENTLY when creating the index. * @retval Create index DDL for temp table. */ Datum repack_indexdef(PG_FUNCTION_ARGS) { Oid index; Oid table; Name tablespace = NULL; IndexDef stmt; StringInfoData str; bool concurrent_index = PG_GETARG_BOOL(3); if (PG_ARGISNULL(0) || PG_ARGISNULL(1)) PG_RETURN_NULL(); index = PG_GETARG_OID(0); table = PG_GETARG_OID(1); if (!PG_ARGISNULL(2)) tablespace = PG_GETARG_NAME(2); parse_indexdef(&stmt, index, table); initStringInfo(&str); if (concurrent_index) appendStringInfo(&str, "%s CONCURRENTLY index_%u ON %s USING %s (%s)%s", stmt.create, index, stmt.table, stmt.type, stmt.columns, stmt.options); else appendStringInfo(&str, "%s index_%u ON repack.table_%u USING %s (%s)%s", stmt.create, index, table, stmt.type, stmt.columns, stmt.options); /* specify the new tablespace or the original one if any */ if (tablespace || stmt.tablespace) appendStringInfo(&str, " TABLESPACE %s", (tablespace ? NameStr(*tablespace) : stmt.tablespace)); if (stmt.where) appendStringInfo(&str, " WHERE %s", stmt.where); PG_RETURN_TEXT_P(cstring_to_text(str.data)); }
Datum geometry_geometrytype(PG_FUNCTION_ARGS) { GSERIALIZED *lwgeom; text *type_text; char *type_str = palloc(32); lwgeom = (GSERIALIZED*)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); /* Make it empty string to start */ *type_str = 0; /* Build up the output string */ strncat(type_str, "ST_", 32); strncat(type_str, lwtype_name(gserialized_get_type(lwgeom)), 32); /* Build a text type to store things in */ type_text = cstring2text(type_str); pfree(type_str); PG_FREE_IF_COPY(lwgeom, 0); PG_RETURN_TEXT_P(type_text); }
Datum plr_set_display(PG_FUNCTION_ARGS) { char *display = PG_TEXT_GET_STR(PG_GETARG_TEXT_P(0)); size_t d_len = strlen(display); if (d_len) { char *denv; MemoryContext oldcontext; /* Needs to live until/unless we explicitly delete it */ oldcontext = MemoryContextSwitchTo(TopMemoryContext); denv = palloc(9 + d_len); MemoryContextSwitchTo(oldcontext); sprintf(denv, "DISPLAY=%s", display); putenv(denv); } PG_RETURN_TEXT_P(PG_STR_GET_TEXT("OK")); }
/* * oidvectortypes - converts a vector of type OIDs to "typname" list */ Datum oidvectortypes(PG_FUNCTION_ARGS) { oidvector *oidArray = (oidvector *) PG_GETARG_POINTER(0); char *result; int numargs = oidArray->dim1; int num; size_t total; size_t left; total = 20 * numargs + 1; result = palloc(total); result[0] = '\0'; left = total - 1; for (num = 0; num < numargs; num++) { char *typename = format_type_internal(oidArray->values[num], -1, false, true); size_t slen = strlen(typename); if (left < (slen + 2)) { total += slen + 2; result = repalloc(result, total); left += slen + 2; } if (num > 0) { strcat(result, ", "); left -= 2; } strcat(result, typename); left -= slen; } PG_RETURN_TEXT_P(cstring_to_text(result)); }
Datum macaddr_text(PG_FUNCTION_ARGS) { /* Input is a macaddr, but may as well leave it in Datum form */ Datum addr = PG_GETARG_DATUM(0); text *result; char *str; int len; str = DatumGetCString(DirectFunctionCall1(macaddr_out, addr)); len = (strlen(str) + VARHDRSZ); result = palloc(len); SET_VARSIZE(result, len); memcpy(VARDATA(result), str, (len - VARHDRSZ)); pfree(str); PG_RETURN_TEXT_P(result); }
/* * Read a section of a file, returning it as text */ Datum pg_read_file(PG_FUNCTION_ARGS) { text *filename_t = PG_GETARG_TEXT_P(0); int64 seek_offset = PG_GETARG_INT64(1); int64 bytes_to_read = PG_GETARG_INT64(2); char *filename; if (!superuser()) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errmsg("must be superuser to read files")))); filename = convert_and_check_filename(filename_t); if (bytes_to_read < 0) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("requested length cannot be negative"))); PG_RETURN_TEXT_P(read_text_file(filename, seek_offset, bytes_to_read)); }
Datum ipaddr_cast_to_text(PG_FUNCTION_ARGS) { IP_P ipp = PG_GETARG_IP_P(0); IP ip; int af = ip_unpack(ipp, &ip); text *out = NULL; switch (af) { case PGSQL_AF_INET: out = make_text(NULL, IP4_STRING_MAX); set_text_len(out, ip4_raw_output(ip.ip4, VARDATA(out), IP4_STRING_MAX)); break; case PGSQL_AF_INET6: out = make_text(NULL, IP6_STRING_MAX); set_text_len(out, ip6_raw_output(ip.ip6.bits, VARDATA(out), IP6_STRING_MAX)); break; } PG_RETURN_TEXT_P(out); }
/* * float4_text - converts a float4 number to a text string */ Datum float4_text(PG_FUNCTION_ARGS) { float4 num = PG_GETARG_FLOAT4(0); text *result; int len; char *str; str = DatumGetCString(DirectFunctionCall1(float4out, Float4GetDatum(num))); len = strlen(str) + VARHDRSZ; result = (text *) palloc(len); VARATT_SIZEP(result) = len; memcpy(VARDATA(result), str, (len - VARHDRSZ)); pfree(str); PG_RETURN_TEXT_P(result); }
Datum dmetaphone_alt(PG_FUNCTION_ARGS) { text *arg; char *aptr, *codes[2], *code; #ifdef DMETAPHONE_NOSTRICT if (PG_ARGISNULL(0)) PG_RETURN_NULL(); #endif arg = PG_GETARG_TEXT_P(0); aptr = text_to_cstring(arg); DoubleMetaphone(aptr, codes); code = codes[1]; if (!code) code = ""; PG_RETURN_TEXT_P(cstring_to_text(code)); }
/* * SQL function json_typeof(json) -> text * * Returns the type of the outermost JSON value as TEXT. Possible types are * "object", "array", "string", "number", "boolean", and "null". * * Performs a single call to json_lex() to get the first token of the supplied * value. This initial token uniquely determines the value's type. As our * input must already have been validated by json_in() or json_recv(), the * initial token should never be JSON_TOKEN_OBJECT_END, JSON_TOKEN_ARRAY_END, * JSON_TOKEN_COLON, JSON_TOKEN_COMMA, or JSON_TOKEN_END. */ Datum json_typeof(PG_FUNCTION_ARGS) { text *json = PG_GETARG_TEXT_P(0); JsonLexContext *lex = makeJsonLexContext(json, false); JsonTokenType tok; char *type; /* Lex exactly one token from the input and check its type. */ json_lex(lex); tok = lex_peek(lex); switch (tok) { case JSON_TOKEN_OBJECT_START: type = "object"; break; case JSON_TOKEN_ARRAY_START: type = "array"; break; case JSON_TOKEN_STRING: type = "string"; break; case JSON_TOKEN_NUMBER: type = "number"; break; case JSON_TOKEN_TRUE: case JSON_TOKEN_FALSE: type = "boolean"; break; case JSON_TOKEN_NULL: type = "null"; break; default: elog(ERROR, "unexpected json token: %d", tok); } PG_RETURN_TEXT_P(cstring_to_text(type)); }
Datum dbms_assert_simple_sql_name(PG_FUNCTION_ARGS) { text *sname; int len; char *cp; if (PG_ARGISNULL(0)) ISNOT_SIMPLE_SQL_NAME_EXCEPTION(); sname = PG_GETARG_TEXT_P(0); if (EMPTY_STR(sname)) ISNOT_SIMPLE_SQL_NAME_EXCEPTION(); len = VARSIZE(sname) - VARHDRSZ; cp = VARDATA(sname); if (!check_sql_name(cp, len)) ISNOT_SIMPLE_SQL_NAME_EXCEPTION(); PG_RETURN_TEXT_P(sname); }
Datum plr_set_rhome(PG_FUNCTION_ARGS) { char *rhome = PG_TEXT_GET_STR(PG_GETARG_TEXT_P(0)); size_t rh_len = strlen(rhome); if (rh_len) { char *rhenv; MemoryContext oldcontext; /* Needs to live until/unless we explicitly delete it */ oldcontext = MemoryContextSwitchTo(TopMemoryContext); rhenv = palloc(8 + rh_len); MemoryContextSwitchTo(oldcontext); sprintf(rhenv, "R_HOME=%s", rhome); putenv(rhenv); } PG_RETURN_TEXT_P(PG_STR_GET_TEXT("OK")); }
Datum geography_as_svg(PG_FUNCTION_ARGS) { GSERIALIZED *g = NULL; LWGEOM *lwgeom = NULL; char *svg; text *result; int relative = 0; int precision=DBL_DIG; if ( PG_ARGISNULL(0) ) PG_RETURN_NULL(); g = (GSERIALIZED*)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); /* Convert to lwgeom so we can run the old functions */ lwgeom = lwgeom_from_gserialized(g); /* check for relative path notation */ if ( PG_NARGS() > 1 && ! PG_ARGISNULL(1) ) relative = PG_GETARG_INT32(1) ? 1:0; if ( PG_NARGS() > 2 && ! PG_ARGISNULL(2) ) { precision = PG_GETARG_INT32(2); /* TODO: leave this to liblwgeom */ if ( precision > DBL_DIG ) precision = DBL_DIG; else if ( precision < 0 ) precision = 0; } svg = lwgeom_to_svg(lwgeom, precision, relative); lwgeom_free(lwgeom); PG_FREE_IF_COPY(g, 0); result = cstring2text(svg); lwfree(svg); PG_RETURN_TEXT_P(result); }
/* * Read a section of a file, returning it as text * * This function is kept to support adminpack 1.0. */ Datum pg_read_file(PG_FUNCTION_ARGS) { text *filename_t = PG_GETARG_TEXT_PP(0); int64 seek_offset = 0; int64 bytes_to_read = -1; bool missing_ok = false; char *filename; text *result; if (!superuser()) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errmsg("must be superuser to read files with adminpack 1.0"), errhint("Consider using pg_file_read(), which is part of core, instead.")))); /* handle optional arguments */ if (PG_NARGS() >= 3) { seek_offset = PG_GETARG_INT64(1); bytes_to_read = PG_GETARG_INT64(2); if (bytes_to_read < 0) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("requested length cannot be negative"))); } if (PG_NARGS() >= 4) missing_ok = PG_GETARG_BOOL(3); filename = convert_and_check_filename(filename_t); result = read_text_file(filename, seek_offset, bytes_to_read, missing_ok); if (result) PG_RETURN_TEXT_P(result); else PG_RETURN_NULL(); }
/* --------------------------------------------------- * hash_page_type() * * Usage: SELECT hash_page_type(get_raw_page('con_hash_index', 1)); * --------------------------------------------------- */ Datum hash_page_type(PG_FUNCTION_ARGS) { bytea *raw_page = PG_GETARG_BYTEA_P(0); Page page; HashPageOpaque opaque; int pagetype; const char *type; if (!superuser()) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errmsg("must be superuser to use raw page functions")))); page = verify_hash_page(raw_page, 0); if (PageIsNew(page)) type = "unused"; else { opaque = (HashPageOpaque) PageGetSpecialPointer(page); /* page type (flags) */ pagetype = opaque->hasho_flag & LH_PAGE_TYPE; if (pagetype == LH_META_PAGE) type = "metapage"; else if (pagetype == LH_OVERFLOW_PAGE) type = "overflow"; else if (pagetype == LH_BUCKET_PAGE) type = "bucket"; else if (pagetype == LH_BITMAP_PAGE) type = "bitmap"; else type = "unused"; } PG_RETURN_TEXT_P(cstring_to_text(type)); }
Datum pgp_key_id_w(PG_FUNCTION_ARGS) { bytea *data; text *res; int res_len; MBuf *buf; data = PG_GETARG_BYTEA_P(0); buf = create_mbuf_from_vardata(data); res = palloc(VARHDRSZ + 17); res_len = pgp_get_keyid(buf, VARDATA(res)); mbuf_free(buf); if (res_len < 0) ereport(ERROR, (errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION), errmsg("%s", px_strerror(res_len)))); SET_VARSIZE(res, VARHDRSZ + res_len); PG_FREE_IF_COPY(data, 0); PG_RETURN_TEXT_P(res); }
Datum geometry_geometrytype(PG_FUNCTION_ARGS) { GSERIALIZED *gser; text *type_text; static int type_str_len = 32; char type_str[type_str_len]; /* Read just the header from the toasted tuple */ gser = PG_GETARG_GSERIALIZED_P_SLICE(0, 0, gserialized_max_header_size()); /* Make it empty string to start */ type_str[0] = 0; /* Build up the output string */ strncat(type_str, "ST_", type_str_len); strncat(type_str, lwtype_name(gserialized_get_type(gser)), type_str_len - 3); /* Build a text type to store things in */ type_text = cstring2text(type_str); PG_FREE_IF_COPY(gser, 0); PG_RETURN_TEXT_P(type_text); }
Datum acl_check_access_text_oid(PG_FUNCTION_ARGS) { ArrayType *acl; text *mask; Oid who; bool implicit_allow; if (!check_access_text_mask_extract_args(fcinfo, &acl, &mask, NULL, &implicit_allow, false, true)) PG_RETURN_NULL(); if (PG_ARGISNULL(2)) PG_RETURN_NULL(); who = PG_GETARG_OID(2); PG_RETURN_TEXT_P(check_access_text_mask(acl, ACL_TYPE_LENGTH, ACL_TYPE_ALIGNMENT, extract_acl_entry_base, mask, (intptr_t) who, who_matches, implicit_allow)); }
/* * SQL function: format_type(type_oid, typemod) * * `type_oid' is from pg_type.oid, `typemod' is from * pg_attribute.atttypmod. This function will get the type name and * format it and the modifier to canonical SQL format, if the type is * a standard type. Otherwise you just get pg_type.typname back, * double quoted if it contains funny characters or matches a keyword. * * If typemod is NULL then we are formatting a type name in a context where * no typemod is available, eg a function argument or result type. This * yields a slightly different result from specifying typemod = -1 in some * cases. Given typemod = -1 we feel compelled to produce an output that * the parser will interpret as having typemod -1, so that pg_dump will * produce CREATE TABLE commands that recreate the original state. But * given NULL typemod, we assume that the parser's interpretation of * typemod doesn't matter, and so we are willing to output a slightly * "prettier" representation of the same type. For example, type = bpchar * and typemod = NULL gets you "character", whereas typemod = -1 gets you * "bpchar" --- the former will be interpreted as character(1) by the * parser, which does not yield typemod -1. * * XXX encoding a meaning in typemod = NULL is ugly; it'd have been * cleaner to make two functions of one and two arguments respectively. * Not worth changing it now, however. */ Datum format_type(PG_FUNCTION_ARGS) { Oid type_oid; int32 typemod; char *result; /* Since this function is not strict, we must test for null args */ if (PG_ARGISNULL(0)) PG_RETURN_NULL(); type_oid = PG_GETARG_OID(0); if (PG_ARGISNULL(1)) result = format_type_internal(type_oid, -1, false, true); else { typemod = PG_GETARG_INT32(1); result = format_type_internal(type_oid, typemod, true, true); } PG_RETURN_TEXT_P(cstring_to_text(result)); }
Datum pg_stat_get_backend_wait_event_type(PG_FUNCTION_ARGS) { int32 beid = PG_GETARG_INT32(0); PgBackendStatus *beentry; PGPROC *proc; const char *wait_event_type; if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL) wait_event_type = "<backend information not available>"; else if (!has_privs_of_role(GetUserId(), beentry->st_userid)) wait_event_type = "<insufficient privilege>"; else { proc = BackendPidGetProc(beentry->st_procpid); wait_event_type = pgstat_get_wait_event_type(proc->wait_event_info); } if (!wait_event_type) PG_RETURN_NULL(); PG_RETURN_TEXT_P(cstring_to_text(wait_event_type)); }