1 /*------------------------------------------------------------------------- 2 * 3 * pgstatfuncs.c 4 * Functions for accessing the statistics collector data 5 * 6 * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group 7 * Portions Copyright (c) 1994, Regents of the University of California 8 * 9 * 10 * IDENTIFICATION 11 * src/backend/utils/adt/pgstatfuncs.c 12 * 13 *------------------------------------------------------------------------- 14 */ 15 #include "postgres.h" 16 17 #include "access/htup_details.h" 18 #include "access/xlog.h" 19 #include "catalog/pg_authid.h" 20 #include "catalog/pg_type.h" 21 #include "common/ip.h" 22 #include "funcapi.h" 23 #include "miscadmin.h" 24 #include "pgstat.h" 25 #include "postmaster/bgworker_internals.h" 26 #include "postmaster/postmaster.h" 27 #include "storage/proc.h" 28 #include "storage/procarray.h" 29 #include "utils/acl.h" 30 #include "utils/builtins.h" 31 #include "utils/inet.h" 32 #include "utils/timestamp.h" 33 34 #define UINT32_ACCESS_ONCE(var) ((uint32)(*((volatile uint32 *)&(var)))) 35 36 #define HAS_PGSTAT_PERMISSIONS(role) (is_member_of_role(GetUserId(), DEFAULT_ROLE_READ_ALL_STATS) || has_privs_of_role(GetUserId(), role)) 37 38 /* Global bgwriter statistics, from bgwriter.c */ 39 extern PgStat_MsgBgWriter bgwriterStats; 40 41 Datum 42 pg_stat_get_numscans(PG_FUNCTION_ARGS) 43 { 44 Oid relid = PG_GETARG_OID(0); 45 int64 result; 46 PgStat_StatTabEntry *tabentry; 47 48 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL) 49 result = 0; 50 else 51 result = (int64) (tabentry->numscans); 52 53 PG_RETURN_INT64(result); 54 } 55 56 57 Datum 58 pg_stat_get_tuples_returned(PG_FUNCTION_ARGS) 59 { 60 Oid relid = PG_GETARG_OID(0); 61 int64 result; 62 PgStat_StatTabEntry *tabentry; 63 64 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL) 65 result = 0; 66 else 67 result = (int64) (tabentry->tuples_returned); 68 69 PG_RETURN_INT64(result); 70 } 71 72 73 Datum 74 pg_stat_get_tuples_fetched(PG_FUNCTION_ARGS) 75 { 76 Oid relid = PG_GETARG_OID(0); 77 int64 result; 78 PgStat_StatTabEntry *tabentry; 79 80 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL) 81 result = 0; 82 else 83 result = (int64) (tabentry->tuples_fetched); 84 85 PG_RETURN_INT64(result); 86 } 87 88 89 Datum 90 pg_stat_get_tuples_inserted(PG_FUNCTION_ARGS) 91 { 92 Oid relid = PG_GETARG_OID(0); 93 int64 result; 94 PgStat_StatTabEntry *tabentry; 95 96 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL) 97 result = 0; 98 else 99 result = (int64) (tabentry->tuples_inserted); 100 101 PG_RETURN_INT64(result); 102 } 103 104 105 Datum 106 pg_stat_get_tuples_updated(PG_FUNCTION_ARGS) 107 { 108 Oid relid = PG_GETARG_OID(0); 109 int64 result; 110 PgStat_StatTabEntry *tabentry; 111 112 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL) 113 result = 0; 114 else 115 result = (int64) (tabentry->tuples_updated); 116 117 PG_RETURN_INT64(result); 118 } 119 120 121 Datum 122 pg_stat_get_tuples_deleted(PG_FUNCTION_ARGS) 123 { 124 Oid relid = PG_GETARG_OID(0); 125 int64 result; 126 PgStat_StatTabEntry *tabentry; 127 128 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL) 129 result = 0; 130 else 131 result = (int64) (tabentry->tuples_deleted); 132 133 PG_RETURN_INT64(result); 134 } 135 136 137 Datum 138 pg_stat_get_tuples_hot_updated(PG_FUNCTION_ARGS) 139 { 140 Oid relid = PG_GETARG_OID(0); 141 int64 result; 142 PgStat_StatTabEntry *tabentry; 143 144 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL) 145 result = 0; 146 else 147 result = (int64) (tabentry->tuples_hot_updated); 148 149 PG_RETURN_INT64(result); 150 } 151 152 153 Datum 154 pg_stat_get_live_tuples(PG_FUNCTION_ARGS) 155 { 156 Oid relid = PG_GETARG_OID(0); 157 int64 result; 158 PgStat_StatTabEntry *tabentry; 159 160 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL) 161 result = 0; 162 else 163 result = (int64) (tabentry->n_live_tuples); 164 165 PG_RETURN_INT64(result); 166 } 167 168 169 Datum 170 pg_stat_get_dead_tuples(PG_FUNCTION_ARGS) 171 { 172 Oid relid = PG_GETARG_OID(0); 173 int64 result; 174 PgStat_StatTabEntry *tabentry; 175 176 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL) 177 result = 0; 178 else 179 result = (int64) (tabentry->n_dead_tuples); 180 181 PG_RETURN_INT64(result); 182 } 183 184 185 Datum 186 pg_stat_get_mod_since_analyze(PG_FUNCTION_ARGS) 187 { 188 Oid relid = PG_GETARG_OID(0); 189 int64 result; 190 PgStat_StatTabEntry *tabentry; 191 192 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL) 193 result = 0; 194 else 195 result = (int64) (tabentry->changes_since_analyze); 196 197 PG_RETURN_INT64(result); 198 } 199 200 201 Datum 202 pg_stat_get_blocks_fetched(PG_FUNCTION_ARGS) 203 { 204 Oid relid = PG_GETARG_OID(0); 205 int64 result; 206 PgStat_StatTabEntry *tabentry; 207 208 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL) 209 result = 0; 210 else 211 result = (int64) (tabentry->blocks_fetched); 212 213 PG_RETURN_INT64(result); 214 } 215 216 217 Datum 218 pg_stat_get_blocks_hit(PG_FUNCTION_ARGS) 219 { 220 Oid relid = PG_GETARG_OID(0); 221 int64 result; 222 PgStat_StatTabEntry *tabentry; 223 224 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL) 225 result = 0; 226 else 227 result = (int64) (tabentry->blocks_hit); 228 229 PG_RETURN_INT64(result); 230 } 231 232 Datum 233 pg_stat_get_last_vacuum_time(PG_FUNCTION_ARGS) 234 { 235 Oid relid = PG_GETARG_OID(0); 236 TimestampTz result; 237 PgStat_StatTabEntry *tabentry; 238 239 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL) 240 result = 0; 241 else 242 result = tabentry->vacuum_timestamp; 243 244 if (result == 0) 245 PG_RETURN_NULL(); 246 else 247 PG_RETURN_TIMESTAMPTZ(result); 248 } 249 250 Datum 251 pg_stat_get_last_autovacuum_time(PG_FUNCTION_ARGS) 252 { 253 Oid relid = PG_GETARG_OID(0); 254 TimestampTz result; 255 PgStat_StatTabEntry *tabentry; 256 257 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL) 258 result = 0; 259 else 260 result = tabentry->autovac_vacuum_timestamp; 261 262 if (result == 0) 263 PG_RETURN_NULL(); 264 else 265 PG_RETURN_TIMESTAMPTZ(result); 266 } 267 268 Datum 269 pg_stat_get_last_analyze_time(PG_FUNCTION_ARGS) 270 { 271 Oid relid = PG_GETARG_OID(0); 272 TimestampTz result; 273 PgStat_StatTabEntry *tabentry; 274 275 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL) 276 result = 0; 277 else 278 result = tabentry->analyze_timestamp; 279 280 if (result == 0) 281 PG_RETURN_NULL(); 282 else 283 PG_RETURN_TIMESTAMPTZ(result); 284 } 285 286 Datum 287 pg_stat_get_last_autoanalyze_time(PG_FUNCTION_ARGS) 288 { 289 Oid relid = PG_GETARG_OID(0); 290 TimestampTz result; 291 PgStat_StatTabEntry *tabentry; 292 293 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL) 294 result = 0; 295 else 296 result = tabentry->autovac_analyze_timestamp; 297 298 if (result == 0) 299 PG_RETURN_NULL(); 300 else 301 PG_RETURN_TIMESTAMPTZ(result); 302 } 303 304 Datum 305 pg_stat_get_vacuum_count(PG_FUNCTION_ARGS) 306 { 307 Oid relid = PG_GETARG_OID(0); 308 int64 result; 309 PgStat_StatTabEntry *tabentry; 310 311 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL) 312 result = 0; 313 else 314 result = (int64) (tabentry->vacuum_count); 315 316 PG_RETURN_INT64(result); 317 } 318 319 Datum 320 pg_stat_get_autovacuum_count(PG_FUNCTION_ARGS) 321 { 322 Oid relid = PG_GETARG_OID(0); 323 int64 result; 324 PgStat_StatTabEntry *tabentry; 325 326 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL) 327 result = 0; 328 else 329 result = (int64) (tabentry->autovac_vacuum_count); 330 331 PG_RETURN_INT64(result); 332 } 333 334 Datum 335 pg_stat_get_analyze_count(PG_FUNCTION_ARGS) 336 { 337 Oid relid = PG_GETARG_OID(0); 338 int64 result; 339 PgStat_StatTabEntry *tabentry; 340 341 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL) 342 result = 0; 343 else 344 result = (int64) (tabentry->analyze_count); 345 346 PG_RETURN_INT64(result); 347 } 348 349 Datum 350 pg_stat_get_autoanalyze_count(PG_FUNCTION_ARGS) 351 { 352 Oid relid = PG_GETARG_OID(0); 353 int64 result; 354 PgStat_StatTabEntry *tabentry; 355 356 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL) 357 result = 0; 358 else 359 result = (int64) (tabentry->autovac_analyze_count); 360 361 PG_RETURN_INT64(result); 362 } 363 364 Datum 365 pg_stat_get_function_calls(PG_FUNCTION_ARGS) 366 { 367 Oid funcid = PG_GETARG_OID(0); 368 PgStat_StatFuncEntry *funcentry; 369 370 if ((funcentry = pgstat_fetch_stat_funcentry(funcid)) == NULL) 371 PG_RETURN_NULL(); 372 PG_RETURN_INT64(funcentry->f_numcalls); 373 } 374 375 Datum 376 pg_stat_get_function_total_time(PG_FUNCTION_ARGS) 377 { 378 Oid funcid = PG_GETARG_OID(0); 379 PgStat_StatFuncEntry *funcentry; 380 381 if ((funcentry = pgstat_fetch_stat_funcentry(funcid)) == NULL) 382 PG_RETURN_NULL(); 383 /* convert counter from microsec to millisec for display */ 384 PG_RETURN_FLOAT8(((double) funcentry->f_total_time) / 1000.0); 385 } 386 387 Datum 388 pg_stat_get_function_self_time(PG_FUNCTION_ARGS) 389 { 390 Oid funcid = PG_GETARG_OID(0); 391 PgStat_StatFuncEntry *funcentry; 392 393 if ((funcentry = pgstat_fetch_stat_funcentry(funcid)) == NULL) 394 PG_RETURN_NULL(); 395 /* convert counter from microsec to millisec for display */ 396 PG_RETURN_FLOAT8(((double) funcentry->f_self_time) / 1000.0); 397 } 398 399 Datum 400 pg_stat_get_backend_idset(PG_FUNCTION_ARGS) 401 { 402 FuncCallContext *funcctx; 403 int *fctx; 404 int32 result; 405 406 /* stuff done only on the first call of the function */ 407 if (SRF_IS_FIRSTCALL()) 408 { 409 /* create a function context for cross-call persistence */ 410 funcctx = SRF_FIRSTCALL_INIT(); 411 412 fctx = MemoryContextAlloc(funcctx->multi_call_memory_ctx, 413 2 * sizeof(int)); 414 funcctx->user_fctx = fctx; 415 416 fctx[0] = 0; 417 fctx[1] = pgstat_fetch_stat_numbackends(); 418 } 419 420 /* stuff done on every call of the function */ 421 funcctx = SRF_PERCALL_SETUP(); 422 fctx = funcctx->user_fctx; 423 424 fctx[0] += 1; 425 result = fctx[0]; 426 427 if (result <= fctx[1]) 428 { 429 /* do when there is more left to send */ 430 SRF_RETURN_NEXT(funcctx, Int32GetDatum(result)); 431 } 432 else 433 { 434 /* do when there is no more left */ 435 SRF_RETURN_DONE(funcctx); 436 } 437 } 438 439 /* 440 * Returns command progress information for the named command. 441 */ 442 Datum 443 pg_stat_get_progress_info(PG_FUNCTION_ARGS) 444 { 445 #define PG_STAT_GET_PROGRESS_COLS PGSTAT_NUM_PROGRESS_PARAM + 3 446 int num_backends = pgstat_fetch_stat_numbackends(); 447 int curr_backend; 448 char *cmd = text_to_cstring(PG_GETARG_TEXT_PP(0)); 449 ProgressCommandType cmdtype; 450 TupleDesc tupdesc; 451 Tuplestorestate *tupstore; 452 ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo; 453 MemoryContext per_query_ctx; 454 MemoryContext oldcontext; 455 456 /* check to see if caller supports us returning a tuplestore */ 457 if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo)) 458 ereport(ERROR, 459 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), 460 errmsg("set-valued function called in context that cannot accept a set"))); 461 if (!(rsinfo->allowedModes & SFRM_Materialize)) 462 ereport(ERROR, 463 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), 464 errmsg("materialize mode required, but it is not " \ 465 "allowed in this context"))); 466 467 /* Build a tuple descriptor for our result type */ 468 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) 469 elog(ERROR, "return type must be a row type"); 470 471 /* Translate command name into command type code. */ 472 if (pg_strcasecmp(cmd, "VACUUM") == 0) 473 cmdtype = PROGRESS_COMMAND_VACUUM; 474 else if (pg_strcasecmp(cmd, "CLUSTER") == 0) 475 cmdtype = PROGRESS_COMMAND_CLUSTER; 476 else if (pg_strcasecmp(cmd, "CREATE INDEX") == 0) 477 cmdtype = PROGRESS_COMMAND_CREATE_INDEX; 478 else 479 ereport(ERROR, 480 (errcode(ERRCODE_INVALID_PARAMETER_VALUE), 481 errmsg("invalid command name: \"%s\"", cmd))); 482 483 per_query_ctx = rsinfo->econtext->ecxt_per_query_memory; 484 oldcontext = MemoryContextSwitchTo(per_query_ctx); 485 486 tupstore = tuplestore_begin_heap(true, false, work_mem); 487 rsinfo->returnMode = SFRM_Materialize; 488 rsinfo->setResult = tupstore; 489 rsinfo->setDesc = tupdesc; 490 MemoryContextSwitchTo(oldcontext); 491 492 /* 1-based index */ 493 for (curr_backend = 1; curr_backend <= num_backends; curr_backend++) 494 { 495 LocalPgBackendStatus *local_beentry; 496 PgBackendStatus *beentry; 497 Datum values[PG_STAT_GET_PROGRESS_COLS]; 498 bool nulls[PG_STAT_GET_PROGRESS_COLS]; 499 int i; 500 501 MemSet(values, 0, sizeof(values)); 502 MemSet(nulls, 0, sizeof(nulls)); 503 504 local_beentry = pgstat_fetch_stat_local_beentry(curr_backend); 505 506 if (!local_beentry) 507 continue; 508 509 beentry = &local_beentry->backendStatus; 510 511 /* 512 * Report values for only those backends which are running the given 513 * command. 514 */ 515 if (!beentry || beentry->st_progress_command != cmdtype) 516 continue; 517 518 /* Value available to all callers */ 519 values[0] = Int32GetDatum(beentry->st_procpid); 520 values[1] = ObjectIdGetDatum(beentry->st_databaseid); 521 522 /* show rest of the values including relid only to role members */ 523 if (HAS_PGSTAT_PERMISSIONS(beentry->st_userid)) 524 { 525 values[2] = ObjectIdGetDatum(beentry->st_progress_command_target); 526 for (i = 0; i < PGSTAT_NUM_PROGRESS_PARAM; i++) 527 values[i + 3] = Int64GetDatum(beentry->st_progress_param[i]); 528 } 529 else 530 { 531 nulls[2] = true; 532 for (i = 0; i < PGSTAT_NUM_PROGRESS_PARAM; i++) 533 nulls[i + 3] = true; 534 } 535 536 tuplestore_putvalues(tupstore, tupdesc, values, nulls); 537 } 538 539 /* clean up and return the tuplestore */ 540 tuplestore_donestoring(tupstore); 541 542 return (Datum) 0; 543 } 544 545 /* 546 * Returns activity of PG backends. 547 */ 548 Datum 549 pg_stat_get_activity(PG_FUNCTION_ARGS) 550 { 551 #define PG_STAT_GET_ACTIVITY_COLS 29 552 int num_backends = pgstat_fetch_stat_numbackends(); 553 int curr_backend; 554 int pid = PG_ARGISNULL(0) ? -1 : PG_GETARG_INT32(0); 555 ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo; 556 TupleDesc tupdesc; 557 Tuplestorestate *tupstore; 558 MemoryContext per_query_ctx; 559 MemoryContext oldcontext; 560 561 /* check to see if caller supports us returning a tuplestore */ 562 if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo)) 563 ereport(ERROR, 564 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), 565 errmsg("set-valued function called in context that cannot accept a set"))); 566 if (!(rsinfo->allowedModes & SFRM_Materialize)) 567 ereport(ERROR, 568 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), 569 errmsg("materialize mode required, but it is not " \ 570 "allowed in this context"))); 571 572 /* Build a tuple descriptor for our result type */ 573 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) 574 elog(ERROR, "return type must be a row type"); 575 576 per_query_ctx = rsinfo->econtext->ecxt_per_query_memory; 577 oldcontext = MemoryContextSwitchTo(per_query_ctx); 578 579 tupstore = tuplestore_begin_heap(true, false, work_mem); 580 rsinfo->returnMode = SFRM_Materialize; 581 rsinfo->setResult = tupstore; 582 rsinfo->setDesc = tupdesc; 583 584 MemoryContextSwitchTo(oldcontext); 585 586 /* 1-based index */ 587 for (curr_backend = 1; curr_backend <= num_backends; curr_backend++) 588 { 589 /* for each row */ 590 Datum values[PG_STAT_GET_ACTIVITY_COLS]; 591 bool nulls[PG_STAT_GET_ACTIVITY_COLS]; 592 LocalPgBackendStatus *local_beentry; 593 PgBackendStatus *beentry; 594 PGPROC *proc; 595 const char *wait_event_type = NULL; 596 const char *wait_event = NULL; 597 598 MemSet(values, 0, sizeof(values)); 599 MemSet(nulls, 0, sizeof(nulls)); 600 601 /* Get the next one in the list */ 602 local_beentry = pgstat_fetch_stat_local_beentry(curr_backend); 603 if (!local_beentry) 604 { 605 int i; 606 607 /* Ignore missing entries if looking for specific PID */ 608 if (pid != -1) 609 continue; 610 611 for (i = 0; i < lengthof(nulls); i++) 612 nulls[i] = true; 613 614 nulls[5] = false; 615 values[5] = CStringGetTextDatum("<backend information not available>"); 616 617 tuplestore_putvalues(tupstore, tupdesc, values, nulls); 618 continue; 619 } 620 621 beentry = &local_beentry->backendStatus; 622 623 /* If looking for specific PID, ignore all the others */ 624 if (pid != -1 && beentry->st_procpid != pid) 625 continue; 626 627 /* Values available to all callers */ 628 if (beentry->st_databaseid != InvalidOid) 629 values[0] = ObjectIdGetDatum(beentry->st_databaseid); 630 else 631 nulls[0] = true; 632 633 values[1] = Int32GetDatum(beentry->st_procpid); 634 635 if (beentry->st_userid != InvalidOid) 636 values[2] = ObjectIdGetDatum(beentry->st_userid); 637 else 638 nulls[2] = true; 639 640 if (beentry->st_appname) 641 values[3] = CStringGetTextDatum(beentry->st_appname); 642 else 643 nulls[3] = true; 644 645 if (TransactionIdIsValid(local_beentry->backend_xid)) 646 values[15] = TransactionIdGetDatum(local_beentry->backend_xid); 647 else 648 nulls[15] = true; 649 650 if (TransactionIdIsValid(local_beentry->backend_xmin)) 651 values[16] = TransactionIdGetDatum(local_beentry->backend_xmin); 652 else 653 nulls[16] = true; 654 655 /* Values only available to role member or pg_read_all_stats */ 656 if (HAS_PGSTAT_PERMISSIONS(beentry->st_userid)) 657 { 658 SockAddr zero_clientaddr; 659 char *clipped_activity; 660 661 switch (beentry->st_state) 662 { 663 case STATE_IDLE: 664 values[4] = CStringGetTextDatum("idle"); 665 break; 666 case STATE_RUNNING: 667 values[4] = CStringGetTextDatum("active"); 668 break; 669 case STATE_IDLEINTRANSACTION: 670 values[4] = CStringGetTextDatum("idle in transaction"); 671 break; 672 case STATE_FASTPATH: 673 values[4] = CStringGetTextDatum("fastpath function call"); 674 break; 675 case STATE_IDLEINTRANSACTION_ABORTED: 676 values[4] = CStringGetTextDatum("idle in transaction (aborted)"); 677 break; 678 case STATE_DISABLED: 679 values[4] = CStringGetTextDatum("disabled"); 680 break; 681 case STATE_UNDEFINED: 682 nulls[4] = true; 683 break; 684 } 685 686 clipped_activity = pgstat_clip_activity(beentry->st_activity_raw); 687 values[5] = CStringGetTextDatum(clipped_activity); 688 pfree(clipped_activity); 689 690 proc = BackendPidGetProc(beentry->st_procpid); 691 if (proc != NULL) 692 { 693 uint32 raw_wait_event; 694 695 raw_wait_event = UINT32_ACCESS_ONCE(proc->wait_event_info); 696 wait_event_type = pgstat_get_wait_event_type(raw_wait_event); 697 wait_event = pgstat_get_wait_event(raw_wait_event); 698 699 } 700 else if (beentry->st_backendType != B_BACKEND) 701 { 702 /* 703 * For an auxiliary process, retrieve process info from 704 * AuxiliaryProcs stored in shared-memory. 705 */ 706 proc = AuxiliaryPidGetProc(beentry->st_procpid); 707 708 if (proc != NULL) 709 { 710 uint32 raw_wait_event; 711 712 raw_wait_event = 713 UINT32_ACCESS_ONCE(proc->wait_event_info); 714 wait_event_type = 715 pgstat_get_wait_event_type(raw_wait_event); 716 wait_event = pgstat_get_wait_event(raw_wait_event); 717 } 718 } 719 720 if (wait_event_type) 721 values[6] = CStringGetTextDatum(wait_event_type); 722 else 723 nulls[6] = true; 724 725 if (wait_event) 726 values[7] = CStringGetTextDatum(wait_event); 727 else 728 nulls[7] = true; 729 730 /* 731 * Don't expose transaction time for walsenders; it confuses 732 * monitoring, particularly because we don't keep the time up-to- 733 * date. 734 */ 735 if (beentry->st_xact_start_timestamp != 0 && 736 beentry->st_backendType != B_WAL_SENDER) 737 values[8] = TimestampTzGetDatum(beentry->st_xact_start_timestamp); 738 else 739 nulls[8] = true; 740 741 if (beentry->st_activity_start_timestamp != 0) 742 values[9] = TimestampTzGetDatum(beentry->st_activity_start_timestamp); 743 else 744 nulls[9] = true; 745 746 if (beentry->st_proc_start_timestamp != 0) 747 values[10] = TimestampTzGetDatum(beentry->st_proc_start_timestamp); 748 else 749 nulls[10] = true; 750 751 if (beentry->st_state_start_timestamp != 0) 752 values[11] = TimestampTzGetDatum(beentry->st_state_start_timestamp); 753 else 754 nulls[11] = true; 755 756 /* A zeroed client addr means we don't know */ 757 memset(&zero_clientaddr, 0, sizeof(zero_clientaddr)); 758 if (memcmp(&(beentry->st_clientaddr), &zero_clientaddr, 759 sizeof(zero_clientaddr)) == 0) 760 { 761 nulls[12] = true; 762 nulls[13] = true; 763 nulls[14] = true; 764 } 765 else 766 { 767 if (beentry->st_clientaddr.addr.ss_family == AF_INET 768 #ifdef HAVE_IPV6 769 || beentry->st_clientaddr.addr.ss_family == AF_INET6 770 #endif 771 ) 772 { 773 char remote_host[NI_MAXHOST]; 774 char remote_port[NI_MAXSERV]; 775 int ret; 776 777 remote_host[0] = '\0'; 778 remote_port[0] = '\0'; 779 ret = pg_getnameinfo_all(&beentry->st_clientaddr.addr, 780 beentry->st_clientaddr.salen, 781 remote_host, sizeof(remote_host), 782 remote_port, sizeof(remote_port), 783 NI_NUMERICHOST | NI_NUMERICSERV); 784 if (ret == 0) 785 { 786 clean_ipv6_addr(beentry->st_clientaddr.addr.ss_family, remote_host); 787 values[12] = DirectFunctionCall1(inet_in, 788 CStringGetDatum(remote_host)); 789 if (beentry->st_clienthostname && 790 beentry->st_clienthostname[0]) 791 values[13] = CStringGetTextDatum(beentry->st_clienthostname); 792 else 793 nulls[13] = true; 794 values[14] = Int32GetDatum(atoi(remote_port)); 795 } 796 else 797 { 798 nulls[12] = true; 799 nulls[13] = true; 800 nulls[14] = true; 801 } 802 } 803 else if (beentry->st_clientaddr.addr.ss_family == AF_UNIX) 804 { 805 /* 806 * Unix sockets always reports NULL for host and -1 for 807 * port, so it's possible to tell the difference to 808 * connections we have no permissions to view, or with 809 * errors. 810 */ 811 nulls[12] = true; 812 nulls[13] = true; 813 values[14] = Int32GetDatum(-1); 814 } 815 else 816 { 817 /* Unknown address type, should never happen */ 818 nulls[12] = true; 819 nulls[13] = true; 820 nulls[14] = true; 821 } 822 } 823 /* Add backend type */ 824 if (beentry->st_backendType == B_BG_WORKER) 825 { 826 const char *bgw_type; 827 828 bgw_type = GetBackgroundWorkerTypeByPid(beentry->st_procpid); 829 if (bgw_type) 830 values[17] = CStringGetTextDatum(bgw_type); 831 else 832 nulls[17] = true; 833 } 834 else 835 values[17] = 836 CStringGetTextDatum(pgstat_get_backend_desc(beentry->st_backendType)); 837 838 /* SSL information */ 839 if (beentry->st_ssl) 840 { 841 values[18] = BoolGetDatum(true); /* ssl */ 842 values[19] = CStringGetTextDatum(beentry->st_sslstatus->ssl_version); 843 values[20] = CStringGetTextDatum(beentry->st_sslstatus->ssl_cipher); 844 values[21] = Int32GetDatum(beentry->st_sslstatus->ssl_bits); 845 values[22] = BoolGetDatum(beentry->st_sslstatus->ssl_compression); 846 847 if (beentry->st_sslstatus->ssl_client_dn[0]) 848 values[23] = CStringGetTextDatum(beentry->st_sslstatus->ssl_client_dn); 849 else 850 nulls[23] = true; 851 852 if (beentry->st_sslstatus->ssl_client_serial[0]) 853 values[24] = DirectFunctionCall3(numeric_in, 854 CStringGetDatum(beentry->st_sslstatus->ssl_client_serial), 855 ObjectIdGetDatum(InvalidOid), 856 Int32GetDatum(-1)); 857 else 858 nulls[24] = true; 859 860 if (beentry->st_sslstatus->ssl_issuer_dn[0]) 861 values[25] = CStringGetTextDatum(beentry->st_sslstatus->ssl_issuer_dn); 862 else 863 nulls[25] = true; 864 } 865 else 866 { 867 values[18] = BoolGetDatum(false); /* ssl */ 868 nulls[19] = nulls[20] = nulls[21] = nulls[22] = nulls[23] = nulls[24] = nulls[25] = true; 869 } 870 871 /* GSSAPI information */ 872 if (beentry->st_gss) 873 { 874 values[26] = BoolGetDatum(beentry->st_gssstatus->gss_auth); /* gss_auth */ 875 values[27] = CStringGetTextDatum(beentry->st_gssstatus->gss_princ); 876 values[28] = BoolGetDatum(beentry->st_gssstatus->gss_enc); /* GSS Encryption in use */ 877 } 878 else 879 { 880 values[26] = BoolGetDatum(false); /* gss_auth */ 881 nulls[27] = true; /* No GSS principal */ 882 values[28] = BoolGetDatum(false); /* GSS Encryption not in 883 * use */ 884 } 885 } 886 else 887 { 888 /* No permissions to view data about this session */ 889 values[5] = CStringGetTextDatum("<insufficient privilege>"); 890 nulls[4] = true; 891 nulls[6] = true; 892 nulls[7] = true; 893 nulls[8] = true; 894 nulls[9] = true; 895 nulls[10] = true; 896 nulls[11] = true; 897 nulls[12] = true; 898 nulls[13] = true; 899 nulls[14] = true; 900 nulls[17] = true; 901 nulls[18] = true; 902 nulls[19] = true; 903 nulls[20] = true; 904 nulls[21] = true; 905 nulls[22] = true; 906 nulls[23] = true; 907 nulls[24] = true; 908 nulls[25] = true; 909 nulls[26] = true; 910 nulls[27] = true; 911 nulls[28] = true; 912 } 913 914 tuplestore_putvalues(tupstore, tupdesc, values, nulls); 915 916 /* If only a single backend was requested, and we found it, break. */ 917 if (pid != -1) 918 break; 919 } 920 921 /* clean up and return the tuplestore */ 922 tuplestore_donestoring(tupstore); 923 924 return (Datum) 0; 925 } 926 927 928 Datum 929 pg_backend_pid(PG_FUNCTION_ARGS) 930 { 931 PG_RETURN_INT32(MyProcPid); 932 } 933 934 935 Datum 936 pg_stat_get_backend_pid(PG_FUNCTION_ARGS) 937 { 938 int32 beid = PG_GETARG_INT32(0); 939 PgBackendStatus *beentry; 940 941 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL) 942 PG_RETURN_NULL(); 943 944 PG_RETURN_INT32(beentry->st_procpid); 945 } 946 947 948 Datum 949 pg_stat_get_backend_dbid(PG_FUNCTION_ARGS) 950 { 951 int32 beid = PG_GETARG_INT32(0); 952 PgBackendStatus *beentry; 953 954 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL) 955 PG_RETURN_NULL(); 956 957 PG_RETURN_OID(beentry->st_databaseid); 958 } 959 960 961 Datum 962 pg_stat_get_backend_userid(PG_FUNCTION_ARGS) 963 { 964 int32 beid = PG_GETARG_INT32(0); 965 PgBackendStatus *beentry; 966 967 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL) 968 PG_RETURN_NULL(); 969 970 PG_RETURN_OID(beentry->st_userid); 971 } 972 973 974 Datum 975 pg_stat_get_backend_activity(PG_FUNCTION_ARGS) 976 { 977 int32 beid = PG_GETARG_INT32(0); 978 PgBackendStatus *beentry; 979 const char *activity; 980 char *clipped_activity; 981 text *ret; 982 983 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL) 984 activity = "<backend information not available>"; 985 else if (!HAS_PGSTAT_PERMISSIONS(beentry->st_userid)) 986 activity = "<insufficient privilege>"; 987 else if (*(beentry->st_activity_raw) == '\0') 988 activity = "<command string not enabled>"; 989 else 990 activity = beentry->st_activity_raw; 991 992 clipped_activity = pgstat_clip_activity(activity); 993 ret = cstring_to_text(activity); 994 pfree(clipped_activity); 995 996 PG_RETURN_TEXT_P(ret); 997 } 998 999 Datum 1000 pg_stat_get_backend_wait_event_type(PG_FUNCTION_ARGS) 1001 { 1002 int32 beid = PG_GETARG_INT32(0); 1003 PgBackendStatus *beentry; 1004 PGPROC *proc; 1005 const char *wait_event_type = NULL; 1006 1007 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL) 1008 wait_event_type = "<backend information not available>"; 1009 else if (!HAS_PGSTAT_PERMISSIONS(beentry->st_userid)) 1010 wait_event_type = "<insufficient privilege>"; 1011 else if ((proc = BackendPidGetProc(beentry->st_procpid)) != NULL) 1012 wait_event_type = pgstat_get_wait_event_type(proc->wait_event_info); 1013 1014 if (!wait_event_type) 1015 PG_RETURN_NULL(); 1016 1017 PG_RETURN_TEXT_P(cstring_to_text(wait_event_type)); 1018 } 1019 1020 Datum 1021 pg_stat_get_backend_wait_event(PG_FUNCTION_ARGS) 1022 { 1023 int32 beid = PG_GETARG_INT32(0); 1024 PgBackendStatus *beentry; 1025 PGPROC *proc; 1026 const char *wait_event = NULL; 1027 1028 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL) 1029 wait_event = "<backend information not available>"; 1030 else if (!HAS_PGSTAT_PERMISSIONS(beentry->st_userid)) 1031 wait_event = "<insufficient privilege>"; 1032 else if ((proc = BackendPidGetProc(beentry->st_procpid)) != NULL) 1033 wait_event = pgstat_get_wait_event(proc->wait_event_info); 1034 1035 if (!wait_event) 1036 PG_RETURN_NULL(); 1037 1038 PG_RETURN_TEXT_P(cstring_to_text(wait_event)); 1039 } 1040 1041 1042 Datum 1043 pg_stat_get_backend_activity_start(PG_FUNCTION_ARGS) 1044 { 1045 int32 beid = PG_GETARG_INT32(0); 1046 TimestampTz result; 1047 PgBackendStatus *beentry; 1048 1049 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL) 1050 PG_RETURN_NULL(); 1051 1052 else if (!HAS_PGSTAT_PERMISSIONS(beentry->st_userid)) 1053 PG_RETURN_NULL(); 1054 1055 result = beentry->st_activity_start_timestamp; 1056 1057 /* 1058 * No time recorded for start of current query -- this is the case if the 1059 * user hasn't enabled query-level stats collection. 1060 */ 1061 if (result == 0) 1062 PG_RETURN_NULL(); 1063 1064 PG_RETURN_TIMESTAMPTZ(result); 1065 } 1066 1067 1068 Datum 1069 pg_stat_get_backend_xact_start(PG_FUNCTION_ARGS) 1070 { 1071 int32 beid = PG_GETARG_INT32(0); 1072 TimestampTz result; 1073 PgBackendStatus *beentry; 1074 1075 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL) 1076 PG_RETURN_NULL(); 1077 1078 else if (!HAS_PGSTAT_PERMISSIONS(beentry->st_userid)) 1079 PG_RETURN_NULL(); 1080 1081 result = beentry->st_xact_start_timestamp; 1082 1083 if (result == 0) /* not in a transaction */ 1084 PG_RETURN_NULL(); 1085 1086 PG_RETURN_TIMESTAMPTZ(result); 1087 } 1088 1089 1090 Datum 1091 pg_stat_get_backend_start(PG_FUNCTION_ARGS) 1092 { 1093 int32 beid = PG_GETARG_INT32(0); 1094 TimestampTz result; 1095 PgBackendStatus *beentry; 1096 1097 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL) 1098 PG_RETURN_NULL(); 1099 1100 else if (!HAS_PGSTAT_PERMISSIONS(beentry->st_userid)) 1101 PG_RETURN_NULL(); 1102 1103 result = beentry->st_proc_start_timestamp; 1104 1105 if (result == 0) /* probably can't happen? */ 1106 PG_RETURN_NULL(); 1107 1108 PG_RETURN_TIMESTAMPTZ(result); 1109 } 1110 1111 1112 Datum 1113 pg_stat_get_backend_client_addr(PG_FUNCTION_ARGS) 1114 { 1115 int32 beid = PG_GETARG_INT32(0); 1116 PgBackendStatus *beentry; 1117 SockAddr zero_clientaddr; 1118 char remote_host[NI_MAXHOST]; 1119 int ret; 1120 1121 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL) 1122 PG_RETURN_NULL(); 1123 1124 else if (!HAS_PGSTAT_PERMISSIONS(beentry->st_userid)) 1125 PG_RETURN_NULL(); 1126 1127 /* A zeroed client addr means we don't know */ 1128 memset(&zero_clientaddr, 0, sizeof(zero_clientaddr)); 1129 if (memcmp(&(beentry->st_clientaddr), &zero_clientaddr, 1130 sizeof(zero_clientaddr)) == 0) 1131 PG_RETURN_NULL(); 1132 1133 switch (beentry->st_clientaddr.addr.ss_family) 1134 { 1135 case AF_INET: 1136 #ifdef HAVE_IPV6 1137 case AF_INET6: 1138 #endif 1139 break; 1140 default: 1141 PG_RETURN_NULL(); 1142 } 1143 1144 remote_host[0] = '\0'; 1145 ret = pg_getnameinfo_all(&beentry->st_clientaddr.addr, 1146 beentry->st_clientaddr.salen, 1147 remote_host, sizeof(remote_host), 1148 NULL, 0, 1149 NI_NUMERICHOST | NI_NUMERICSERV); 1150 if (ret != 0) 1151 PG_RETURN_NULL(); 1152 1153 clean_ipv6_addr(beentry->st_clientaddr.addr.ss_family, remote_host); 1154 1155 PG_RETURN_INET_P(DirectFunctionCall1(inet_in, 1156 CStringGetDatum(remote_host))); 1157 } 1158 1159 Datum 1160 pg_stat_get_backend_client_port(PG_FUNCTION_ARGS) 1161 { 1162 int32 beid = PG_GETARG_INT32(0); 1163 PgBackendStatus *beentry; 1164 SockAddr zero_clientaddr; 1165 char remote_port[NI_MAXSERV]; 1166 int ret; 1167 1168 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL) 1169 PG_RETURN_NULL(); 1170 1171 else if (!HAS_PGSTAT_PERMISSIONS(beentry->st_userid)) 1172 PG_RETURN_NULL(); 1173 1174 /* A zeroed client addr means we don't know */ 1175 memset(&zero_clientaddr, 0, sizeof(zero_clientaddr)); 1176 if (memcmp(&(beentry->st_clientaddr), &zero_clientaddr, 1177 sizeof(zero_clientaddr)) == 0) 1178 PG_RETURN_NULL(); 1179 1180 switch (beentry->st_clientaddr.addr.ss_family) 1181 { 1182 case AF_INET: 1183 #ifdef HAVE_IPV6 1184 case AF_INET6: 1185 #endif 1186 break; 1187 case AF_UNIX: 1188 PG_RETURN_INT32(-1); 1189 default: 1190 PG_RETURN_NULL(); 1191 } 1192 1193 remote_port[0] = '\0'; 1194 ret = pg_getnameinfo_all(&beentry->st_clientaddr.addr, 1195 beentry->st_clientaddr.salen, 1196 NULL, 0, 1197 remote_port, sizeof(remote_port), 1198 NI_NUMERICHOST | NI_NUMERICSERV); 1199 if (ret != 0) 1200 PG_RETURN_NULL(); 1201 1202 PG_RETURN_DATUM(DirectFunctionCall1(int4in, 1203 CStringGetDatum(remote_port))); 1204 } 1205 1206 1207 Datum 1208 pg_stat_get_db_numbackends(PG_FUNCTION_ARGS) 1209 { 1210 Oid dbid = PG_GETARG_OID(0); 1211 int32 result; 1212 int tot_backends = pgstat_fetch_stat_numbackends(); 1213 int beid; 1214 1215 result = 0; 1216 for (beid = 1; beid <= tot_backends; beid++) 1217 { 1218 PgBackendStatus *beentry = pgstat_fetch_stat_beentry(beid); 1219 1220 if (beentry && beentry->st_databaseid == dbid) 1221 result++; 1222 } 1223 1224 PG_RETURN_INT32(result); 1225 } 1226 1227 1228 Datum 1229 pg_stat_get_db_xact_commit(PG_FUNCTION_ARGS) 1230 { 1231 Oid dbid = PG_GETARG_OID(0); 1232 int64 result; 1233 PgStat_StatDBEntry *dbentry; 1234 1235 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL) 1236 result = 0; 1237 else 1238 result = (int64) (dbentry->n_xact_commit); 1239 1240 PG_RETURN_INT64(result); 1241 } 1242 1243 1244 Datum 1245 pg_stat_get_db_xact_rollback(PG_FUNCTION_ARGS) 1246 { 1247 Oid dbid = PG_GETARG_OID(0); 1248 int64 result; 1249 PgStat_StatDBEntry *dbentry; 1250 1251 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL) 1252 result = 0; 1253 else 1254 result = (int64) (dbentry->n_xact_rollback); 1255 1256 PG_RETURN_INT64(result); 1257 } 1258 1259 1260 Datum 1261 pg_stat_get_db_blocks_fetched(PG_FUNCTION_ARGS) 1262 { 1263 Oid dbid = PG_GETARG_OID(0); 1264 int64 result; 1265 PgStat_StatDBEntry *dbentry; 1266 1267 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL) 1268 result = 0; 1269 else 1270 result = (int64) (dbentry->n_blocks_fetched); 1271 1272 PG_RETURN_INT64(result); 1273 } 1274 1275 1276 Datum 1277 pg_stat_get_db_blocks_hit(PG_FUNCTION_ARGS) 1278 { 1279 Oid dbid = PG_GETARG_OID(0); 1280 int64 result; 1281 PgStat_StatDBEntry *dbentry; 1282 1283 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL) 1284 result = 0; 1285 else 1286 result = (int64) (dbentry->n_blocks_hit); 1287 1288 PG_RETURN_INT64(result); 1289 } 1290 1291 1292 Datum 1293 pg_stat_get_db_tuples_returned(PG_FUNCTION_ARGS) 1294 { 1295 Oid dbid = PG_GETARG_OID(0); 1296 int64 result; 1297 PgStat_StatDBEntry *dbentry; 1298 1299 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL) 1300 result = 0; 1301 else 1302 result = (int64) (dbentry->n_tuples_returned); 1303 1304 PG_RETURN_INT64(result); 1305 } 1306 1307 1308 Datum 1309 pg_stat_get_db_tuples_fetched(PG_FUNCTION_ARGS) 1310 { 1311 Oid dbid = PG_GETARG_OID(0); 1312 int64 result; 1313 PgStat_StatDBEntry *dbentry; 1314 1315 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL) 1316 result = 0; 1317 else 1318 result = (int64) (dbentry->n_tuples_fetched); 1319 1320 PG_RETURN_INT64(result); 1321 } 1322 1323 1324 Datum 1325 pg_stat_get_db_tuples_inserted(PG_FUNCTION_ARGS) 1326 { 1327 Oid dbid = PG_GETARG_OID(0); 1328 int64 result; 1329 PgStat_StatDBEntry *dbentry; 1330 1331 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL) 1332 result = 0; 1333 else 1334 result = (int64) (dbentry->n_tuples_inserted); 1335 1336 PG_RETURN_INT64(result); 1337 } 1338 1339 1340 Datum 1341 pg_stat_get_db_tuples_updated(PG_FUNCTION_ARGS) 1342 { 1343 Oid dbid = PG_GETARG_OID(0); 1344 int64 result; 1345 PgStat_StatDBEntry *dbentry; 1346 1347 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL) 1348 result = 0; 1349 else 1350 result = (int64) (dbentry->n_tuples_updated); 1351 1352 PG_RETURN_INT64(result); 1353 } 1354 1355 1356 Datum 1357 pg_stat_get_db_tuples_deleted(PG_FUNCTION_ARGS) 1358 { 1359 Oid dbid = PG_GETARG_OID(0); 1360 int64 result; 1361 PgStat_StatDBEntry *dbentry; 1362 1363 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL) 1364 result = 0; 1365 else 1366 result = (int64) (dbentry->n_tuples_deleted); 1367 1368 PG_RETURN_INT64(result); 1369 } 1370 1371 Datum 1372 pg_stat_get_db_stat_reset_time(PG_FUNCTION_ARGS) 1373 { 1374 Oid dbid = PG_GETARG_OID(0); 1375 TimestampTz result; 1376 PgStat_StatDBEntry *dbentry; 1377 1378 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL) 1379 result = 0; 1380 else 1381 result = dbentry->stat_reset_timestamp; 1382 1383 if (result == 0) 1384 PG_RETURN_NULL(); 1385 else 1386 PG_RETURN_TIMESTAMPTZ(result); 1387 } 1388 1389 Datum 1390 pg_stat_get_db_temp_files(PG_FUNCTION_ARGS) 1391 { 1392 Oid dbid = PG_GETARG_OID(0); 1393 int64 result; 1394 PgStat_StatDBEntry *dbentry; 1395 1396 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL) 1397 result = 0; 1398 else 1399 result = dbentry->n_temp_files; 1400 1401 PG_RETURN_INT64(result); 1402 } 1403 1404 1405 Datum 1406 pg_stat_get_db_temp_bytes(PG_FUNCTION_ARGS) 1407 { 1408 Oid dbid = PG_GETARG_OID(0); 1409 int64 result; 1410 PgStat_StatDBEntry *dbentry; 1411 1412 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL) 1413 result = 0; 1414 else 1415 result = dbentry->n_temp_bytes; 1416 1417 PG_RETURN_INT64(result); 1418 } 1419 1420 Datum 1421 pg_stat_get_db_conflict_tablespace(PG_FUNCTION_ARGS) 1422 { 1423 Oid dbid = PG_GETARG_OID(0); 1424 int64 result; 1425 PgStat_StatDBEntry *dbentry; 1426 1427 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL) 1428 result = 0; 1429 else 1430 result = (int64) (dbentry->n_conflict_tablespace); 1431 1432 PG_RETURN_INT64(result); 1433 } 1434 1435 Datum 1436 pg_stat_get_db_conflict_lock(PG_FUNCTION_ARGS) 1437 { 1438 Oid dbid = PG_GETARG_OID(0); 1439 int64 result; 1440 PgStat_StatDBEntry *dbentry; 1441 1442 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL) 1443 result = 0; 1444 else 1445 result = (int64) (dbentry->n_conflict_lock); 1446 1447 PG_RETURN_INT64(result); 1448 } 1449 1450 Datum 1451 pg_stat_get_db_conflict_snapshot(PG_FUNCTION_ARGS) 1452 { 1453 Oid dbid = PG_GETARG_OID(0); 1454 int64 result; 1455 PgStat_StatDBEntry *dbentry; 1456 1457 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL) 1458 result = 0; 1459 else 1460 result = (int64) (dbentry->n_conflict_snapshot); 1461 1462 PG_RETURN_INT64(result); 1463 } 1464 1465 Datum 1466 pg_stat_get_db_conflict_bufferpin(PG_FUNCTION_ARGS) 1467 { 1468 Oid dbid = PG_GETARG_OID(0); 1469 int64 result; 1470 PgStat_StatDBEntry *dbentry; 1471 1472 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL) 1473 result = 0; 1474 else 1475 result = (int64) (dbentry->n_conflict_bufferpin); 1476 1477 PG_RETURN_INT64(result); 1478 } 1479 1480 Datum 1481 pg_stat_get_db_conflict_startup_deadlock(PG_FUNCTION_ARGS) 1482 { 1483 Oid dbid = PG_GETARG_OID(0); 1484 int64 result; 1485 PgStat_StatDBEntry *dbentry; 1486 1487 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL) 1488 result = 0; 1489 else 1490 result = (int64) (dbentry->n_conflict_startup_deadlock); 1491 1492 PG_RETURN_INT64(result); 1493 } 1494 1495 Datum 1496 pg_stat_get_db_conflict_all(PG_FUNCTION_ARGS) 1497 { 1498 Oid dbid = PG_GETARG_OID(0); 1499 int64 result; 1500 PgStat_StatDBEntry *dbentry; 1501 1502 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL) 1503 result = 0; 1504 else 1505 result = (int64) ( 1506 dbentry->n_conflict_tablespace + 1507 dbentry->n_conflict_lock + 1508 dbentry->n_conflict_snapshot + 1509 dbentry->n_conflict_bufferpin + 1510 dbentry->n_conflict_startup_deadlock); 1511 1512 PG_RETURN_INT64(result); 1513 } 1514 1515 Datum 1516 pg_stat_get_db_deadlocks(PG_FUNCTION_ARGS) 1517 { 1518 Oid dbid = PG_GETARG_OID(0); 1519 int64 result; 1520 PgStat_StatDBEntry *dbentry; 1521 1522 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL) 1523 result = 0; 1524 else 1525 result = (int64) (dbentry->n_deadlocks); 1526 1527 PG_RETURN_INT64(result); 1528 } 1529 1530 Datum 1531 pg_stat_get_db_checksum_failures(PG_FUNCTION_ARGS) 1532 { 1533 Oid dbid = PG_GETARG_OID(0); 1534 int64 result; 1535 PgStat_StatDBEntry *dbentry; 1536 1537 if (!DataChecksumsEnabled()) 1538 PG_RETURN_NULL(); 1539 1540 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL) 1541 result = 0; 1542 else 1543 result = (int64) (dbentry->n_checksum_failures); 1544 1545 PG_RETURN_INT64(result); 1546 } 1547 1548 Datum 1549 pg_stat_get_db_checksum_last_failure(PG_FUNCTION_ARGS) 1550 { 1551 Oid dbid = PG_GETARG_OID(0); 1552 TimestampTz result; 1553 PgStat_StatDBEntry *dbentry; 1554 1555 if (!DataChecksumsEnabled()) 1556 PG_RETURN_NULL(); 1557 1558 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL) 1559 result = 0; 1560 else 1561 result = dbentry->last_checksum_failure; 1562 1563 if (result == 0) 1564 PG_RETURN_NULL(); 1565 else 1566 PG_RETURN_TIMESTAMPTZ(result); 1567 } 1568 1569 Datum 1570 pg_stat_get_db_blk_read_time(PG_FUNCTION_ARGS) 1571 { 1572 Oid dbid = PG_GETARG_OID(0); 1573 double result; 1574 PgStat_StatDBEntry *dbentry; 1575 1576 /* convert counter from microsec to millisec for display */ 1577 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL) 1578 result = 0; 1579 else 1580 result = ((double) dbentry->n_block_read_time) / 1000.0; 1581 1582 PG_RETURN_FLOAT8(result); 1583 } 1584 1585 Datum 1586 pg_stat_get_db_blk_write_time(PG_FUNCTION_ARGS) 1587 { 1588 Oid dbid = PG_GETARG_OID(0); 1589 double result; 1590 PgStat_StatDBEntry *dbentry; 1591 1592 /* convert counter from microsec to millisec for display */ 1593 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL) 1594 result = 0; 1595 else 1596 result = ((double) dbentry->n_block_write_time) / 1000.0; 1597 1598 PG_RETURN_FLOAT8(result); 1599 } 1600 1601 Datum 1602 pg_stat_get_bgwriter_timed_checkpoints(PG_FUNCTION_ARGS) 1603 { 1604 PG_RETURN_INT64(pgstat_fetch_global()->timed_checkpoints); 1605 } 1606 1607 Datum 1608 pg_stat_get_bgwriter_requested_checkpoints(PG_FUNCTION_ARGS) 1609 { 1610 PG_RETURN_INT64(pgstat_fetch_global()->requested_checkpoints); 1611 } 1612 1613 Datum 1614 pg_stat_get_bgwriter_buf_written_checkpoints(PG_FUNCTION_ARGS) 1615 { 1616 PG_RETURN_INT64(pgstat_fetch_global()->buf_written_checkpoints); 1617 } 1618 1619 Datum 1620 pg_stat_get_bgwriter_buf_written_clean(PG_FUNCTION_ARGS) 1621 { 1622 PG_RETURN_INT64(pgstat_fetch_global()->buf_written_clean); 1623 } 1624 1625 Datum 1626 pg_stat_get_bgwriter_maxwritten_clean(PG_FUNCTION_ARGS) 1627 { 1628 PG_RETURN_INT64(pgstat_fetch_global()->maxwritten_clean); 1629 } 1630 1631 Datum 1632 pg_stat_get_checkpoint_write_time(PG_FUNCTION_ARGS) 1633 { 1634 /* time is already in msec, just convert to double for presentation */ 1635 PG_RETURN_FLOAT8((double) pgstat_fetch_global()->checkpoint_write_time); 1636 } 1637 1638 Datum 1639 pg_stat_get_checkpoint_sync_time(PG_FUNCTION_ARGS) 1640 { 1641 /* time is already in msec, just convert to double for presentation */ 1642 PG_RETURN_FLOAT8((double) pgstat_fetch_global()->checkpoint_sync_time); 1643 } 1644 1645 Datum 1646 pg_stat_get_bgwriter_stat_reset_time(PG_FUNCTION_ARGS) 1647 { 1648 PG_RETURN_TIMESTAMPTZ(pgstat_fetch_global()->stat_reset_timestamp); 1649 } 1650 1651 Datum 1652 pg_stat_get_buf_written_backend(PG_FUNCTION_ARGS) 1653 { 1654 PG_RETURN_INT64(pgstat_fetch_global()->buf_written_backend); 1655 } 1656 1657 Datum 1658 pg_stat_get_buf_fsync_backend(PG_FUNCTION_ARGS) 1659 { 1660 PG_RETURN_INT64(pgstat_fetch_global()->buf_fsync_backend); 1661 } 1662 1663 Datum 1664 pg_stat_get_buf_alloc(PG_FUNCTION_ARGS) 1665 { 1666 PG_RETURN_INT64(pgstat_fetch_global()->buf_alloc); 1667 } 1668 1669 Datum 1670 pg_stat_get_xact_numscans(PG_FUNCTION_ARGS) 1671 { 1672 Oid relid = PG_GETARG_OID(0); 1673 int64 result; 1674 PgStat_TableStatus *tabentry; 1675 1676 if ((tabentry = find_tabstat_entry(relid)) == NULL) 1677 result = 0; 1678 else 1679 result = (int64) (tabentry->t_counts.t_numscans); 1680 1681 PG_RETURN_INT64(result); 1682 } 1683 1684 Datum 1685 pg_stat_get_xact_tuples_returned(PG_FUNCTION_ARGS) 1686 { 1687 Oid relid = PG_GETARG_OID(0); 1688 int64 result; 1689 PgStat_TableStatus *tabentry; 1690 1691 if ((tabentry = find_tabstat_entry(relid)) == NULL) 1692 result = 0; 1693 else 1694 result = (int64) (tabentry->t_counts.t_tuples_returned); 1695 1696 PG_RETURN_INT64(result); 1697 } 1698 1699 Datum 1700 pg_stat_get_xact_tuples_fetched(PG_FUNCTION_ARGS) 1701 { 1702 Oid relid = PG_GETARG_OID(0); 1703 int64 result; 1704 PgStat_TableStatus *tabentry; 1705 1706 if ((tabentry = find_tabstat_entry(relid)) == NULL) 1707 result = 0; 1708 else 1709 result = (int64) (tabentry->t_counts.t_tuples_fetched); 1710 1711 PG_RETURN_INT64(result); 1712 } 1713 1714 Datum 1715 pg_stat_get_xact_tuples_inserted(PG_FUNCTION_ARGS) 1716 { 1717 Oid relid = PG_GETARG_OID(0); 1718 int64 result; 1719 PgStat_TableStatus *tabentry; 1720 PgStat_TableXactStatus *trans; 1721 1722 if ((tabentry = find_tabstat_entry(relid)) == NULL) 1723 result = 0; 1724 else 1725 { 1726 result = tabentry->t_counts.t_tuples_inserted; 1727 /* live subtransactions' counts aren't in t_tuples_inserted yet */ 1728 for (trans = tabentry->trans; trans != NULL; trans = trans->upper) 1729 result += trans->tuples_inserted; 1730 } 1731 1732 PG_RETURN_INT64(result); 1733 } 1734 1735 Datum 1736 pg_stat_get_xact_tuples_updated(PG_FUNCTION_ARGS) 1737 { 1738 Oid relid = PG_GETARG_OID(0); 1739 int64 result; 1740 PgStat_TableStatus *tabentry; 1741 PgStat_TableXactStatus *trans; 1742 1743 if ((tabentry = find_tabstat_entry(relid)) == NULL) 1744 result = 0; 1745 else 1746 { 1747 result = tabentry->t_counts.t_tuples_updated; 1748 /* live subtransactions' counts aren't in t_tuples_updated yet */ 1749 for (trans = tabentry->trans; trans != NULL; trans = trans->upper) 1750 result += trans->tuples_updated; 1751 } 1752 1753 PG_RETURN_INT64(result); 1754 } 1755 1756 Datum 1757 pg_stat_get_xact_tuples_deleted(PG_FUNCTION_ARGS) 1758 { 1759 Oid relid = PG_GETARG_OID(0); 1760 int64 result; 1761 PgStat_TableStatus *tabentry; 1762 PgStat_TableXactStatus *trans; 1763 1764 if ((tabentry = find_tabstat_entry(relid)) == NULL) 1765 result = 0; 1766 else 1767 { 1768 result = tabentry->t_counts.t_tuples_deleted; 1769 /* live subtransactions' counts aren't in t_tuples_deleted yet */ 1770 for (trans = tabentry->trans; trans != NULL; trans = trans->upper) 1771 result += trans->tuples_deleted; 1772 } 1773 1774 PG_RETURN_INT64(result); 1775 } 1776 1777 Datum 1778 pg_stat_get_xact_tuples_hot_updated(PG_FUNCTION_ARGS) 1779 { 1780 Oid relid = PG_GETARG_OID(0); 1781 int64 result; 1782 PgStat_TableStatus *tabentry; 1783 1784 if ((tabentry = find_tabstat_entry(relid)) == NULL) 1785 result = 0; 1786 else 1787 result = (int64) (tabentry->t_counts.t_tuples_hot_updated); 1788 1789 PG_RETURN_INT64(result); 1790 } 1791 1792 Datum 1793 pg_stat_get_xact_blocks_fetched(PG_FUNCTION_ARGS) 1794 { 1795 Oid relid = PG_GETARG_OID(0); 1796 int64 result; 1797 PgStat_TableStatus *tabentry; 1798 1799 if ((tabentry = find_tabstat_entry(relid)) == NULL) 1800 result = 0; 1801 else 1802 result = (int64) (tabentry->t_counts.t_blocks_fetched); 1803 1804 PG_RETURN_INT64(result); 1805 } 1806 1807 Datum 1808 pg_stat_get_xact_blocks_hit(PG_FUNCTION_ARGS) 1809 { 1810 Oid relid = PG_GETARG_OID(0); 1811 int64 result; 1812 PgStat_TableStatus *tabentry; 1813 1814 if ((tabentry = find_tabstat_entry(relid)) == NULL) 1815 result = 0; 1816 else 1817 result = (int64) (tabentry->t_counts.t_blocks_hit); 1818 1819 PG_RETURN_INT64(result); 1820 } 1821 1822 Datum 1823 pg_stat_get_xact_function_calls(PG_FUNCTION_ARGS) 1824 { 1825 Oid funcid = PG_GETARG_OID(0); 1826 PgStat_BackendFunctionEntry *funcentry; 1827 1828 if ((funcentry = find_funcstat_entry(funcid)) == NULL) 1829 PG_RETURN_NULL(); 1830 PG_RETURN_INT64(funcentry->f_counts.f_numcalls); 1831 } 1832 1833 Datum 1834 pg_stat_get_xact_function_total_time(PG_FUNCTION_ARGS) 1835 { 1836 Oid funcid = PG_GETARG_OID(0); 1837 PgStat_BackendFunctionEntry *funcentry; 1838 1839 if ((funcentry = find_funcstat_entry(funcid)) == NULL) 1840 PG_RETURN_NULL(); 1841 PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(funcentry->f_counts.f_total_time)); 1842 } 1843 1844 Datum 1845 pg_stat_get_xact_function_self_time(PG_FUNCTION_ARGS) 1846 { 1847 Oid funcid = PG_GETARG_OID(0); 1848 PgStat_BackendFunctionEntry *funcentry; 1849 1850 if ((funcentry = find_funcstat_entry(funcid)) == NULL) 1851 PG_RETURN_NULL(); 1852 PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(funcentry->f_counts.f_self_time)); 1853 } 1854 1855 1856 /* Get the timestamp of the current statistics snapshot */ 1857 Datum 1858 pg_stat_get_snapshot_timestamp(PG_FUNCTION_ARGS) 1859 { 1860 PG_RETURN_TIMESTAMPTZ(pgstat_fetch_global()->stats_timestamp); 1861 } 1862 1863 /* Discard the active statistics snapshot */ 1864 Datum 1865 pg_stat_clear_snapshot(PG_FUNCTION_ARGS) 1866 { 1867 pgstat_clear_snapshot(); 1868 1869 PG_RETURN_VOID(); 1870 } 1871 1872 1873 /* Reset all counters for the current database */ 1874 Datum 1875 pg_stat_reset(PG_FUNCTION_ARGS) 1876 { 1877 pgstat_reset_counters(); 1878 1879 PG_RETURN_VOID(); 1880 } 1881 1882 /* Reset some shared cluster-wide counters */ 1883 Datum 1884 pg_stat_reset_shared(PG_FUNCTION_ARGS) 1885 { 1886 char *target = text_to_cstring(PG_GETARG_TEXT_PP(0)); 1887 1888 pgstat_reset_shared_counters(target); 1889 1890 PG_RETURN_VOID(); 1891 } 1892 1893 /* Reset a single counter in the current database */ 1894 Datum 1895 pg_stat_reset_single_table_counters(PG_FUNCTION_ARGS) 1896 { 1897 Oid taboid = PG_GETARG_OID(0); 1898 1899 pgstat_reset_single_counter(taboid, RESET_TABLE); 1900 1901 PG_RETURN_VOID(); 1902 } 1903 1904 Datum 1905 pg_stat_reset_single_function_counters(PG_FUNCTION_ARGS) 1906 { 1907 Oid funcoid = PG_GETARG_OID(0); 1908 1909 pgstat_reset_single_counter(funcoid, RESET_FUNCTION); 1910 1911 PG_RETURN_VOID(); 1912 } 1913 1914 Datum 1915 pg_stat_get_archiver(PG_FUNCTION_ARGS) 1916 { 1917 TupleDesc tupdesc; 1918 Datum values[7]; 1919 bool nulls[7]; 1920 PgStat_ArchiverStats *archiver_stats; 1921 1922 /* Initialise values and NULL flags arrays */ 1923 MemSet(values, 0, sizeof(values)); 1924 MemSet(nulls, 0, sizeof(nulls)); 1925 1926 /* Initialise attributes information in the tuple descriptor */ 1927 tupdesc = CreateTemplateTupleDesc(7); 1928 TupleDescInitEntry(tupdesc, (AttrNumber) 1, "archived_count", 1929 INT8OID, -1, 0); 1930 TupleDescInitEntry(tupdesc, (AttrNumber) 2, "last_archived_wal", 1931 TEXTOID, -1, 0); 1932 TupleDescInitEntry(tupdesc, (AttrNumber) 3, "last_archived_time", 1933 TIMESTAMPTZOID, -1, 0); 1934 TupleDescInitEntry(tupdesc, (AttrNumber) 4, "failed_count", 1935 INT8OID, -1, 0); 1936 TupleDescInitEntry(tupdesc, (AttrNumber) 5, "last_failed_wal", 1937 TEXTOID, -1, 0); 1938 TupleDescInitEntry(tupdesc, (AttrNumber) 6, "last_failed_time", 1939 TIMESTAMPTZOID, -1, 0); 1940 TupleDescInitEntry(tupdesc, (AttrNumber) 7, "stats_reset", 1941 TIMESTAMPTZOID, -1, 0); 1942 1943 BlessTupleDesc(tupdesc); 1944 1945 /* Get statistics about the archiver process */ 1946 archiver_stats = pgstat_fetch_stat_archiver(); 1947 1948 /* Fill values and NULLs */ 1949 values[0] = Int64GetDatum(archiver_stats->archived_count); 1950 if (*(archiver_stats->last_archived_wal) == '\0') 1951 nulls[1] = true; 1952 else 1953 values[1] = CStringGetTextDatum(archiver_stats->last_archived_wal); 1954 1955 if (archiver_stats->last_archived_timestamp == 0) 1956 nulls[2] = true; 1957 else 1958 values[2] = TimestampTzGetDatum(archiver_stats->last_archived_timestamp); 1959 1960 values[3] = Int64GetDatum(archiver_stats->failed_count); 1961 if (*(archiver_stats->last_failed_wal) == '\0') 1962 nulls[4] = true; 1963 else 1964 values[4] = CStringGetTextDatum(archiver_stats->last_failed_wal); 1965 1966 if (archiver_stats->last_failed_timestamp == 0) 1967 nulls[5] = true; 1968 else 1969 values[5] = TimestampTzGetDatum(archiver_stats->last_failed_timestamp); 1970 1971 if (archiver_stats->stat_reset_timestamp == 0) 1972 nulls[6] = true; 1973 else 1974 values[6] = TimestampTzGetDatum(archiver_stats->stat_reset_timestamp); 1975 1976 /* Returns the record as Datum */ 1977 PG_RETURN_DATUM(HeapTupleGetDatum( 1978 heap_form_tuple(tupdesc, values, nulls))); 1979 } 1980