Header And Logo

PostgreSQL
| The world's most advanced open source database.

pgstatfuncs.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * pgstatfuncs.c
00004  *    Functions for accessing the statistics collector data
00005  *
00006  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00007  * Portions Copyright (c) 1994, Regents of the University of California
00008  *
00009  *
00010  * IDENTIFICATION
00011  *    src/backend/utils/adt/pgstatfuncs.c
00012  *
00013  *-------------------------------------------------------------------------
00014  */
00015 #include "postgres.h"
00016 
00017 #include "access/htup_details.h"
00018 #include "catalog/pg_type.h"
00019 #include "funcapi.h"
00020 #include "libpq/ip.h"
00021 #include "miscadmin.h"
00022 #include "pgstat.h"
00023 #include "utils/builtins.h"
00024 #include "utils/inet.h"
00025 #include "utils/timestamp.h"
00026 
00027 /* bogus ... these externs should be in a header file */
00028 extern Datum pg_stat_get_numscans(PG_FUNCTION_ARGS);
00029 extern Datum pg_stat_get_tuples_returned(PG_FUNCTION_ARGS);
00030 extern Datum pg_stat_get_tuples_fetched(PG_FUNCTION_ARGS);
00031 extern Datum pg_stat_get_tuples_inserted(PG_FUNCTION_ARGS);
00032 extern Datum pg_stat_get_tuples_updated(PG_FUNCTION_ARGS);
00033 extern Datum pg_stat_get_tuples_deleted(PG_FUNCTION_ARGS);
00034 extern Datum pg_stat_get_tuples_hot_updated(PG_FUNCTION_ARGS);
00035 extern Datum pg_stat_get_live_tuples(PG_FUNCTION_ARGS);
00036 extern Datum pg_stat_get_dead_tuples(PG_FUNCTION_ARGS);
00037 extern Datum pg_stat_get_blocks_fetched(PG_FUNCTION_ARGS);
00038 extern Datum pg_stat_get_blocks_hit(PG_FUNCTION_ARGS);
00039 extern Datum pg_stat_get_last_vacuum_time(PG_FUNCTION_ARGS);
00040 extern Datum pg_stat_get_last_autovacuum_time(PG_FUNCTION_ARGS);
00041 extern Datum pg_stat_get_last_analyze_time(PG_FUNCTION_ARGS);
00042 extern Datum pg_stat_get_last_autoanalyze_time(PG_FUNCTION_ARGS);
00043 extern Datum pg_stat_get_vacuum_count(PG_FUNCTION_ARGS);
00044 extern Datum pg_stat_get_autovacuum_count(PG_FUNCTION_ARGS);
00045 extern Datum pg_stat_get_analyze_count(PG_FUNCTION_ARGS);
00046 extern Datum pg_stat_get_autoanalyze_count(PG_FUNCTION_ARGS);
00047 
00048 extern Datum pg_stat_get_function_calls(PG_FUNCTION_ARGS);
00049 extern Datum pg_stat_get_function_total_time(PG_FUNCTION_ARGS);
00050 extern Datum pg_stat_get_function_self_time(PG_FUNCTION_ARGS);
00051 
00052 extern Datum pg_stat_get_backend_idset(PG_FUNCTION_ARGS);
00053 extern Datum pg_stat_get_activity(PG_FUNCTION_ARGS);
00054 extern Datum pg_backend_pid(PG_FUNCTION_ARGS);
00055 extern Datum pg_stat_get_backend_pid(PG_FUNCTION_ARGS);
00056 extern Datum pg_stat_get_backend_dbid(PG_FUNCTION_ARGS);
00057 extern Datum pg_stat_get_backend_userid(PG_FUNCTION_ARGS);
00058 extern Datum pg_stat_get_backend_activity(PG_FUNCTION_ARGS);
00059 extern Datum pg_stat_get_backend_waiting(PG_FUNCTION_ARGS);
00060 extern Datum pg_stat_get_backend_activity_start(PG_FUNCTION_ARGS);
00061 extern Datum pg_stat_get_backend_xact_start(PG_FUNCTION_ARGS);
00062 extern Datum pg_stat_get_backend_start(PG_FUNCTION_ARGS);
00063 extern Datum pg_stat_get_backend_client_addr(PG_FUNCTION_ARGS);
00064 extern Datum pg_stat_get_backend_client_port(PG_FUNCTION_ARGS);
00065 
00066 extern Datum pg_stat_get_db_numbackends(PG_FUNCTION_ARGS);
00067 extern Datum pg_stat_get_db_xact_commit(PG_FUNCTION_ARGS);
00068 extern Datum pg_stat_get_db_xact_rollback(PG_FUNCTION_ARGS);
00069 extern Datum pg_stat_get_db_blocks_fetched(PG_FUNCTION_ARGS);
00070 extern Datum pg_stat_get_db_blocks_hit(PG_FUNCTION_ARGS);
00071 extern Datum pg_stat_get_db_tuples_returned(PG_FUNCTION_ARGS);
00072 extern Datum pg_stat_get_db_tuples_fetched(PG_FUNCTION_ARGS);
00073 extern Datum pg_stat_get_db_tuples_inserted(PG_FUNCTION_ARGS);
00074 extern Datum pg_stat_get_db_tuples_updated(PG_FUNCTION_ARGS);
00075 extern Datum pg_stat_get_db_tuples_deleted(PG_FUNCTION_ARGS);
00076 extern Datum pg_stat_get_db_conflict_tablespace(PG_FUNCTION_ARGS);
00077 extern Datum pg_stat_get_db_conflict_lock(PG_FUNCTION_ARGS);
00078 extern Datum pg_stat_get_db_conflict_snapshot(PG_FUNCTION_ARGS);
00079 extern Datum pg_stat_get_db_conflict_bufferpin(PG_FUNCTION_ARGS);
00080 extern Datum pg_stat_get_db_conflict_startup_deadlock(PG_FUNCTION_ARGS);
00081 extern Datum pg_stat_get_db_conflict_all(PG_FUNCTION_ARGS);
00082 extern Datum pg_stat_get_db_deadlocks(PG_FUNCTION_ARGS);
00083 extern Datum pg_stat_get_db_stat_reset_time(PG_FUNCTION_ARGS);
00084 extern Datum pg_stat_get_db_temp_files(PG_FUNCTION_ARGS);
00085 extern Datum pg_stat_get_db_temp_bytes(PG_FUNCTION_ARGS);
00086 extern Datum pg_stat_get_db_blk_read_time(PG_FUNCTION_ARGS);
00087 extern Datum pg_stat_get_db_blk_write_time(PG_FUNCTION_ARGS);
00088 
00089 extern Datum pg_stat_get_bgwriter_timed_checkpoints(PG_FUNCTION_ARGS);
00090 extern Datum pg_stat_get_bgwriter_requested_checkpoints(PG_FUNCTION_ARGS);
00091 extern Datum pg_stat_get_checkpoint_write_time(PG_FUNCTION_ARGS);
00092 extern Datum pg_stat_get_checkpoint_sync_time(PG_FUNCTION_ARGS);
00093 extern Datum pg_stat_get_bgwriter_buf_written_checkpoints(PG_FUNCTION_ARGS);
00094 extern Datum pg_stat_get_bgwriter_buf_written_clean(PG_FUNCTION_ARGS);
00095 extern Datum pg_stat_get_bgwriter_maxwritten_clean(PG_FUNCTION_ARGS);
00096 extern Datum pg_stat_get_bgwriter_stat_reset_time(PG_FUNCTION_ARGS);
00097 extern Datum pg_stat_get_buf_written_backend(PG_FUNCTION_ARGS);
00098 extern Datum pg_stat_get_buf_fsync_backend(PG_FUNCTION_ARGS);
00099 extern Datum pg_stat_get_buf_alloc(PG_FUNCTION_ARGS);
00100 
00101 extern Datum pg_stat_get_xact_numscans(PG_FUNCTION_ARGS);
00102 extern Datum pg_stat_get_xact_tuples_returned(PG_FUNCTION_ARGS);
00103 extern Datum pg_stat_get_xact_tuples_fetched(PG_FUNCTION_ARGS);
00104 extern Datum pg_stat_get_xact_tuples_inserted(PG_FUNCTION_ARGS);
00105 extern Datum pg_stat_get_xact_tuples_updated(PG_FUNCTION_ARGS);
00106 extern Datum pg_stat_get_xact_tuples_deleted(PG_FUNCTION_ARGS);
00107 extern Datum pg_stat_get_xact_tuples_hot_updated(PG_FUNCTION_ARGS);
00108 extern Datum pg_stat_get_xact_blocks_fetched(PG_FUNCTION_ARGS);
00109 extern Datum pg_stat_get_xact_blocks_hit(PG_FUNCTION_ARGS);
00110 
00111 extern Datum pg_stat_get_xact_function_calls(PG_FUNCTION_ARGS);
00112 extern Datum pg_stat_get_xact_function_total_time(PG_FUNCTION_ARGS);
00113 extern Datum pg_stat_get_xact_function_self_time(PG_FUNCTION_ARGS);
00114 
00115 extern Datum pg_stat_clear_snapshot(PG_FUNCTION_ARGS);
00116 extern Datum pg_stat_reset(PG_FUNCTION_ARGS);
00117 extern Datum pg_stat_reset_shared(PG_FUNCTION_ARGS);
00118 extern Datum pg_stat_reset_single_table_counters(PG_FUNCTION_ARGS);
00119 extern Datum pg_stat_reset_single_function_counters(PG_FUNCTION_ARGS);
00120 
00121 /* Global bgwriter statistics, from bgwriter.c */
00122 extern PgStat_MsgBgWriter bgwriterStats;
00123 
00124 Datum
00125 pg_stat_get_numscans(PG_FUNCTION_ARGS)
00126 {
00127     Oid         relid = PG_GETARG_OID(0);
00128     int64       result;
00129     PgStat_StatTabEntry *tabentry;
00130 
00131     if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
00132         result = 0;
00133     else
00134         result = (int64) (tabentry->numscans);
00135 
00136     PG_RETURN_INT64(result);
00137 }
00138 
00139 
00140 Datum
00141 pg_stat_get_tuples_returned(PG_FUNCTION_ARGS)
00142 {
00143     Oid         relid = PG_GETARG_OID(0);
00144     int64       result;
00145     PgStat_StatTabEntry *tabentry;
00146 
00147     if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
00148         result = 0;
00149     else
00150         result = (int64) (tabentry->tuples_returned);
00151 
00152     PG_RETURN_INT64(result);
00153 }
00154 
00155 
00156 Datum
00157 pg_stat_get_tuples_fetched(PG_FUNCTION_ARGS)
00158 {
00159     Oid         relid = PG_GETARG_OID(0);
00160     int64       result;
00161     PgStat_StatTabEntry *tabentry;
00162 
00163     if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
00164         result = 0;
00165     else
00166         result = (int64) (tabentry->tuples_fetched);
00167 
00168     PG_RETURN_INT64(result);
00169 }
00170 
00171 
00172 Datum
00173 pg_stat_get_tuples_inserted(PG_FUNCTION_ARGS)
00174 {
00175     Oid         relid = PG_GETARG_OID(0);
00176     int64       result;
00177     PgStat_StatTabEntry *tabentry;
00178 
00179     if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
00180         result = 0;
00181     else
00182         result = (int64) (tabentry->tuples_inserted);
00183 
00184     PG_RETURN_INT64(result);
00185 }
00186 
00187 
00188 Datum
00189 pg_stat_get_tuples_updated(PG_FUNCTION_ARGS)
00190 {
00191     Oid         relid = PG_GETARG_OID(0);
00192     int64       result;
00193     PgStat_StatTabEntry *tabentry;
00194 
00195     if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
00196         result = 0;
00197     else
00198         result = (int64) (tabentry->tuples_updated);
00199 
00200     PG_RETURN_INT64(result);
00201 }
00202 
00203 
00204 Datum
00205 pg_stat_get_tuples_deleted(PG_FUNCTION_ARGS)
00206 {
00207     Oid         relid = PG_GETARG_OID(0);
00208     int64       result;
00209     PgStat_StatTabEntry *tabentry;
00210 
00211     if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
00212         result = 0;
00213     else
00214         result = (int64) (tabentry->tuples_deleted);
00215 
00216     PG_RETURN_INT64(result);
00217 }
00218 
00219 
00220 Datum
00221 pg_stat_get_tuples_hot_updated(PG_FUNCTION_ARGS)
00222 {
00223     Oid         relid = PG_GETARG_OID(0);
00224     int64       result;
00225     PgStat_StatTabEntry *tabentry;
00226 
00227     if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
00228         result = 0;
00229     else
00230         result = (int64) (tabentry->tuples_hot_updated);
00231 
00232     PG_RETURN_INT64(result);
00233 }
00234 
00235 
00236 Datum
00237 pg_stat_get_live_tuples(PG_FUNCTION_ARGS)
00238 {
00239     Oid         relid = PG_GETARG_OID(0);
00240     int64       result;
00241     PgStat_StatTabEntry *tabentry;
00242 
00243     if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
00244         result = 0;
00245     else
00246         result = (int64) (tabentry->n_live_tuples);
00247 
00248     PG_RETURN_INT64(result);
00249 }
00250 
00251 
00252 Datum
00253 pg_stat_get_dead_tuples(PG_FUNCTION_ARGS)
00254 {
00255     Oid         relid = PG_GETARG_OID(0);
00256     int64       result;
00257     PgStat_StatTabEntry *tabentry;
00258 
00259     if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
00260         result = 0;
00261     else
00262         result = (int64) (tabentry->n_dead_tuples);
00263 
00264     PG_RETURN_INT64(result);
00265 }
00266 
00267 
00268 Datum
00269 pg_stat_get_blocks_fetched(PG_FUNCTION_ARGS)
00270 {
00271     Oid         relid = PG_GETARG_OID(0);
00272     int64       result;
00273     PgStat_StatTabEntry *tabentry;
00274 
00275     if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
00276         result = 0;
00277     else
00278         result = (int64) (tabentry->blocks_fetched);
00279 
00280     PG_RETURN_INT64(result);
00281 }
00282 
00283 
00284 Datum
00285 pg_stat_get_blocks_hit(PG_FUNCTION_ARGS)
00286 {
00287     Oid         relid = PG_GETARG_OID(0);
00288     int64       result;
00289     PgStat_StatTabEntry *tabentry;
00290 
00291     if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
00292         result = 0;
00293     else
00294         result = (int64) (tabentry->blocks_hit);
00295 
00296     PG_RETURN_INT64(result);
00297 }
00298 
00299 Datum
00300 pg_stat_get_last_vacuum_time(PG_FUNCTION_ARGS)
00301 {
00302     Oid         relid = PG_GETARG_OID(0);
00303     TimestampTz result;
00304     PgStat_StatTabEntry *tabentry;
00305 
00306     if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
00307         result = 0;
00308     else
00309         result = tabentry->vacuum_timestamp;
00310 
00311     if (result == 0)
00312         PG_RETURN_NULL();
00313     else
00314         PG_RETURN_TIMESTAMPTZ(result);
00315 }
00316 
00317 Datum
00318 pg_stat_get_last_autovacuum_time(PG_FUNCTION_ARGS)
00319 {
00320     Oid         relid = PG_GETARG_OID(0);
00321     TimestampTz result;
00322     PgStat_StatTabEntry *tabentry;
00323 
00324     if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
00325         result = 0;
00326     else
00327         result = tabentry->autovac_vacuum_timestamp;
00328 
00329     if (result == 0)
00330         PG_RETURN_NULL();
00331     else
00332         PG_RETURN_TIMESTAMPTZ(result);
00333 }
00334 
00335 Datum
00336 pg_stat_get_last_analyze_time(PG_FUNCTION_ARGS)
00337 {
00338     Oid         relid = PG_GETARG_OID(0);
00339     TimestampTz result;
00340     PgStat_StatTabEntry *tabentry;
00341 
00342     if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
00343         result = 0;
00344     else
00345         result = tabentry->analyze_timestamp;
00346 
00347     if (result == 0)
00348         PG_RETURN_NULL();
00349     else
00350         PG_RETURN_TIMESTAMPTZ(result);
00351 }
00352 
00353 Datum
00354 pg_stat_get_last_autoanalyze_time(PG_FUNCTION_ARGS)
00355 {
00356     Oid         relid = PG_GETARG_OID(0);
00357     TimestampTz result;
00358     PgStat_StatTabEntry *tabentry;
00359 
00360     if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
00361         result = 0;
00362     else
00363         result = tabentry->autovac_analyze_timestamp;
00364 
00365     if (result == 0)
00366         PG_RETURN_NULL();
00367     else
00368         PG_RETURN_TIMESTAMPTZ(result);
00369 }
00370 
00371 Datum
00372 pg_stat_get_vacuum_count(PG_FUNCTION_ARGS)
00373 {
00374     Oid         relid = PG_GETARG_OID(0);
00375     int64       result;
00376     PgStat_StatTabEntry *tabentry;
00377 
00378     if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
00379         result = 0;
00380     else
00381         result = (int64) (tabentry->vacuum_count);
00382 
00383     PG_RETURN_INT64(result);
00384 }
00385 
00386 Datum
00387 pg_stat_get_autovacuum_count(PG_FUNCTION_ARGS)
00388 {
00389     Oid         relid = PG_GETARG_OID(0);
00390     int64       result;
00391     PgStat_StatTabEntry *tabentry;
00392 
00393     if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
00394         result = 0;
00395     else
00396         result = (int64) (tabentry->autovac_vacuum_count);
00397 
00398     PG_RETURN_INT64(result);
00399 }
00400 
00401 Datum
00402 pg_stat_get_analyze_count(PG_FUNCTION_ARGS)
00403 {
00404     Oid         relid = PG_GETARG_OID(0);
00405     int64       result;
00406     PgStat_StatTabEntry *tabentry;
00407 
00408     if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
00409         result = 0;
00410     else
00411         result = (int64) (tabentry->analyze_count);
00412 
00413     PG_RETURN_INT64(result);
00414 }
00415 
00416 Datum
00417 pg_stat_get_autoanalyze_count(PG_FUNCTION_ARGS)
00418 {
00419     Oid         relid = PG_GETARG_OID(0);
00420     int64       result;
00421     PgStat_StatTabEntry *tabentry;
00422 
00423     if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
00424         result = 0;
00425     else
00426         result = (int64) (tabentry->autovac_analyze_count);
00427 
00428     PG_RETURN_INT64(result);
00429 }
00430 
00431 Datum
00432 pg_stat_get_function_calls(PG_FUNCTION_ARGS)
00433 {
00434     Oid         funcid = PG_GETARG_OID(0);
00435     PgStat_StatFuncEntry *funcentry;
00436 
00437     if ((funcentry = pgstat_fetch_stat_funcentry(funcid)) == NULL)
00438         PG_RETURN_NULL();
00439     PG_RETURN_INT64(funcentry->f_numcalls);
00440 }
00441 
00442 Datum
00443 pg_stat_get_function_total_time(PG_FUNCTION_ARGS)
00444 {
00445     Oid         funcid = PG_GETARG_OID(0);
00446     PgStat_StatFuncEntry *funcentry;
00447 
00448     if ((funcentry = pgstat_fetch_stat_funcentry(funcid)) == NULL)
00449         PG_RETURN_NULL();
00450     /* convert counter from microsec to millisec for display */
00451     PG_RETURN_FLOAT8(((double) funcentry->f_total_time) / 1000.0);
00452 }
00453 
00454 Datum
00455 pg_stat_get_function_self_time(PG_FUNCTION_ARGS)
00456 {
00457     Oid         funcid = PG_GETARG_OID(0);
00458     PgStat_StatFuncEntry *funcentry;
00459 
00460     if ((funcentry = pgstat_fetch_stat_funcentry(funcid)) == NULL)
00461         PG_RETURN_NULL();
00462     /* convert counter from microsec to millisec for display */
00463     PG_RETURN_FLOAT8(((double) funcentry->f_self_time) / 1000.0);
00464 }
00465 
00466 Datum
00467 pg_stat_get_backend_idset(PG_FUNCTION_ARGS)
00468 {
00469     FuncCallContext *funcctx;
00470     int        *fctx;
00471     int32       result;
00472 
00473     /* stuff done only on the first call of the function */
00474     if (SRF_IS_FIRSTCALL())
00475     {
00476         /* create a function context for cross-call persistence */
00477         funcctx = SRF_FIRSTCALL_INIT();
00478 
00479         fctx = MemoryContextAlloc(funcctx->multi_call_memory_ctx,
00480                                   2 * sizeof(int));
00481         funcctx->user_fctx = fctx;
00482 
00483         fctx[0] = 0;
00484         fctx[1] = pgstat_fetch_stat_numbackends();
00485     }
00486 
00487     /* stuff done on every call of the function */
00488     funcctx = SRF_PERCALL_SETUP();
00489     fctx = funcctx->user_fctx;
00490 
00491     fctx[0] += 1;
00492     result = fctx[0];
00493 
00494     if (result <= fctx[1])
00495     {
00496         /* do when there is more left to send */
00497         SRF_RETURN_NEXT(funcctx, Int32GetDatum(result));
00498     }
00499     else
00500     {
00501         /* do when there is no more left */
00502         SRF_RETURN_DONE(funcctx);
00503     }
00504 }
00505 
00506 Datum
00507 pg_stat_get_activity(PG_FUNCTION_ARGS)
00508 {
00509     FuncCallContext *funcctx;
00510 
00511     if (SRF_IS_FIRSTCALL())
00512     {
00513         MemoryContext oldcontext;
00514         TupleDesc   tupdesc;
00515 
00516         funcctx = SRF_FIRSTCALL_INIT();
00517 
00518         oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
00519 
00520         tupdesc = CreateTemplateTupleDesc(14, false);
00521         TupleDescInitEntry(tupdesc, (AttrNumber) 1, "datid",
00522                            OIDOID, -1, 0);
00523         TupleDescInitEntry(tupdesc, (AttrNumber) 2, "pid",
00524                            INT4OID, -1, 0);
00525         TupleDescInitEntry(tupdesc, (AttrNumber) 3, "usesysid",
00526                            OIDOID, -1, 0);
00527         TupleDescInitEntry(tupdesc, (AttrNumber) 4, "application_name",
00528                            TEXTOID, -1, 0);
00529         TupleDescInitEntry(tupdesc, (AttrNumber) 5, "state",
00530                            TEXTOID, -1, 0);
00531         TupleDescInitEntry(tupdesc, (AttrNumber) 6, "query",
00532                            TEXTOID, -1, 0);
00533         TupleDescInitEntry(tupdesc, (AttrNumber) 7, "waiting",
00534                            BOOLOID, -1, 0);
00535         TupleDescInitEntry(tupdesc, (AttrNumber) 8, "act_start",
00536                            TIMESTAMPTZOID, -1, 0);
00537         TupleDescInitEntry(tupdesc, (AttrNumber) 9, "query_start",
00538                            TIMESTAMPTZOID, -1, 0);
00539         TupleDescInitEntry(tupdesc, (AttrNumber) 10, "backend_start",
00540                            TIMESTAMPTZOID, -1, 0);
00541         TupleDescInitEntry(tupdesc, (AttrNumber) 11, "state_change",
00542                            TIMESTAMPTZOID, -1, 0);
00543         TupleDescInitEntry(tupdesc, (AttrNumber) 12, "client_addr",
00544                            INETOID, -1, 0);
00545         TupleDescInitEntry(tupdesc, (AttrNumber) 13, "client_hostname",
00546                            TEXTOID, -1, 0);
00547         TupleDescInitEntry(tupdesc, (AttrNumber) 14, "client_port",
00548                            INT4OID, -1, 0);
00549 
00550         funcctx->tuple_desc = BlessTupleDesc(tupdesc);
00551 
00552         funcctx->user_fctx = palloc0(sizeof(int));
00553         if (PG_ARGISNULL(0))
00554         {
00555             /* Get all backends */
00556             funcctx->max_calls = pgstat_fetch_stat_numbackends();
00557         }
00558         else
00559         {
00560             /*
00561              * Get one backend - locate by pid.
00562              *
00563              * We lookup the backend early, so we can return zero rows if it
00564              * doesn't exist, instead of returning a single row full of NULLs.
00565              */
00566             int         pid = PG_GETARG_INT32(0);
00567             int         i;
00568             int         n = pgstat_fetch_stat_numbackends();
00569 
00570             for (i = 1; i <= n; i++)
00571             {
00572                 PgBackendStatus *be = pgstat_fetch_stat_beentry(i);
00573 
00574                 if (be)
00575                 {
00576                     if (be->st_procpid == pid)
00577                     {
00578                         *(int *) (funcctx->user_fctx) = i;
00579                         break;
00580                     }
00581                 }
00582             }
00583 
00584             if (*(int *) (funcctx->user_fctx) == 0)
00585                 /* Pid not found, return zero rows */
00586                 funcctx->max_calls = 0;
00587             else
00588                 funcctx->max_calls = 1;
00589         }
00590 
00591         MemoryContextSwitchTo(oldcontext);
00592     }
00593 
00594     /* stuff done on every call of the function */
00595     funcctx = SRF_PERCALL_SETUP();
00596 
00597     if (funcctx->call_cntr < funcctx->max_calls)
00598     {
00599         /* for each row */
00600         Datum       values[14];
00601         bool        nulls[14];
00602         HeapTuple   tuple;
00603         PgBackendStatus *beentry;
00604         SockAddr    zero_clientaddr;
00605 
00606         MemSet(values, 0, sizeof(values));
00607         MemSet(nulls, 0, sizeof(nulls));
00608 
00609         if (*(int *) (funcctx->user_fctx) > 0)
00610         {
00611             /* Get specific pid slot */
00612             beentry = pgstat_fetch_stat_beentry(*(int *) (funcctx->user_fctx));
00613         }
00614         else
00615         {
00616             /* Get the next one in the list */
00617             beentry = pgstat_fetch_stat_beentry(funcctx->call_cntr + 1);        /* 1-based index */
00618         }
00619         if (!beentry)
00620         {
00621             int         i;
00622 
00623             for (i = 0; i < sizeof(nulls) / sizeof(nulls[0]); i++)
00624                 nulls[i] = true;
00625 
00626             nulls[5] = false;
00627             values[5] = CStringGetTextDatum("<backend information not available>");
00628 
00629             tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);
00630             SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tuple));
00631         }
00632 
00633         /* Values available to all callers */
00634         values[0] = ObjectIdGetDatum(beentry->st_databaseid);
00635         values[1] = Int32GetDatum(beentry->st_procpid);
00636         values[2] = ObjectIdGetDatum(beentry->st_userid);
00637         if (beentry->st_appname)
00638             values[3] = CStringGetTextDatum(beentry->st_appname);
00639         else
00640             nulls[3] = true;
00641 
00642         /* Values only available to same user or superuser */
00643         if (superuser() || beentry->st_userid == GetUserId())
00644         {
00645             switch (beentry->st_state)
00646             {
00647                 case STATE_IDLE:
00648                     values[4] = CStringGetTextDatum("idle");
00649                     break;
00650                 case STATE_RUNNING:
00651                     values[4] = CStringGetTextDatum("active");
00652                     break;
00653                 case STATE_IDLEINTRANSACTION:
00654                     values[4] = CStringGetTextDatum("idle in transaction");
00655                     break;
00656                 case STATE_FASTPATH:
00657                     values[4] = CStringGetTextDatum("fastpath function call");
00658                     break;
00659                 case STATE_IDLEINTRANSACTION_ABORTED:
00660                     values[4] = CStringGetTextDatum("idle in transaction (aborted)");
00661                     break;
00662                 case STATE_DISABLED:
00663                     values[4] = CStringGetTextDatum("disabled");
00664                     break;
00665                 case STATE_UNDEFINED:
00666                     nulls[4] = true;
00667                     break;
00668             }
00669 
00670             values[5] = CStringGetTextDatum(beentry->st_activity);
00671             values[6] = BoolGetDatum(beentry->st_waiting);
00672 
00673             if (beentry->st_xact_start_timestamp != 0)
00674                 values[7] = TimestampTzGetDatum(beentry->st_xact_start_timestamp);
00675             else
00676                 nulls[7] = true;
00677 
00678             if (beentry->st_activity_start_timestamp != 0)
00679                 values[8] = TimestampTzGetDatum(beentry->st_activity_start_timestamp);
00680             else
00681                 nulls[8] = true;
00682 
00683             if (beentry->st_proc_start_timestamp != 0)
00684                 values[9] = TimestampTzGetDatum(beentry->st_proc_start_timestamp);
00685             else
00686                 nulls[9] = true;
00687 
00688             if (beentry->st_state_start_timestamp != 0)
00689                 values[10] = TimestampTzGetDatum(beentry->st_state_start_timestamp);
00690             else
00691                 nulls[10] = true;
00692 
00693             /* A zeroed client addr means we don't know */
00694             memset(&zero_clientaddr, 0, sizeof(zero_clientaddr));
00695             if (memcmp(&(beentry->st_clientaddr), &zero_clientaddr,
00696                        sizeof(zero_clientaddr) == 0))
00697             {
00698                 nulls[11] = true;
00699                 nulls[12] = true;
00700                 nulls[13] = true;
00701             }
00702             else
00703             {
00704                 if (beentry->st_clientaddr.addr.ss_family == AF_INET
00705 #ifdef HAVE_IPV6
00706                     || beentry->st_clientaddr.addr.ss_family == AF_INET6
00707 #endif
00708                     )
00709                 {
00710                     char        remote_host[NI_MAXHOST];
00711                     char        remote_port[NI_MAXSERV];
00712                     int         ret;
00713 
00714                     remote_host[0] = '\0';
00715                     remote_port[0] = '\0';
00716                     ret = pg_getnameinfo_all(&beentry->st_clientaddr.addr,
00717                                              beentry->st_clientaddr.salen,
00718                                              remote_host, sizeof(remote_host),
00719                                              remote_port, sizeof(remote_port),
00720                                              NI_NUMERICHOST | NI_NUMERICSERV);
00721                     if (ret == 0)
00722                     {
00723                         clean_ipv6_addr(beentry->st_clientaddr.addr.ss_family, remote_host);
00724                         values[11] = DirectFunctionCall1(inet_in,
00725                                                CStringGetDatum(remote_host));
00726                         if (beentry->st_clienthostname)
00727                             values[12] = CStringGetTextDatum(beentry->st_clienthostname);
00728                         else
00729                             nulls[12] = true;
00730                         values[13] = Int32GetDatum(atoi(remote_port));
00731                     }
00732                     else
00733                     {
00734                         nulls[11] = true;
00735                         nulls[12] = true;
00736                         nulls[13] = true;
00737                     }
00738                 }
00739                 else if (beentry->st_clientaddr.addr.ss_family == AF_UNIX)
00740                 {
00741                     /*
00742                      * Unix sockets always reports NULL for host and -1 for
00743                      * port, so it's possible to tell the difference to
00744                      * connections we have no permissions to view, or with
00745                      * errors.
00746                      */
00747                     nulls[11] = true;
00748                     nulls[12] = true;
00749                     values[13] = DatumGetInt32(-1);
00750                 }
00751                 else
00752                 {
00753                     /* Unknown address type, should never happen */
00754                     nulls[11] = true;
00755                     nulls[12] = true;
00756                     nulls[13] = true;
00757                 }
00758             }
00759         }
00760         else
00761         {
00762             /* No permissions to view data about this session */
00763             values[5] = CStringGetTextDatum("<insufficient privilege>");
00764             nulls[4] = true;
00765             nulls[6] = true;
00766             nulls[7] = true;
00767             nulls[8] = true;
00768             nulls[9] = true;
00769             nulls[10] = true;
00770             nulls[11] = true;
00771             nulls[12] = true;
00772             nulls[13] = true;
00773         }
00774 
00775         tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);
00776 
00777         SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tuple));
00778     }
00779     else
00780     {
00781         /* nothing left */
00782         SRF_RETURN_DONE(funcctx);
00783     }
00784 }
00785 
00786 
00787 Datum
00788 pg_backend_pid(PG_FUNCTION_ARGS)
00789 {
00790     PG_RETURN_INT32(MyProcPid);
00791 }
00792 
00793 
00794 Datum
00795 pg_stat_get_backend_pid(PG_FUNCTION_ARGS)
00796 {
00797     int32       beid = PG_GETARG_INT32(0);
00798     PgBackendStatus *beentry;
00799 
00800     if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
00801         PG_RETURN_NULL();
00802 
00803     PG_RETURN_INT32(beentry->st_procpid);
00804 }
00805 
00806 
00807 Datum
00808 pg_stat_get_backend_dbid(PG_FUNCTION_ARGS)
00809 {
00810     int32       beid = PG_GETARG_INT32(0);
00811     PgBackendStatus *beentry;
00812 
00813     if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
00814         PG_RETURN_NULL();
00815 
00816     PG_RETURN_OID(beentry->st_databaseid);
00817 }
00818 
00819 
00820 Datum
00821 pg_stat_get_backend_userid(PG_FUNCTION_ARGS)
00822 {
00823     int32       beid = PG_GETARG_INT32(0);
00824     PgBackendStatus *beentry;
00825 
00826     if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
00827         PG_RETURN_NULL();
00828 
00829     PG_RETURN_OID(beentry->st_userid);
00830 }
00831 
00832 
00833 Datum
00834 pg_stat_get_backend_activity(PG_FUNCTION_ARGS)
00835 {
00836     int32       beid = PG_GETARG_INT32(0);
00837     PgBackendStatus *beentry;
00838     const char *activity;
00839 
00840     if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
00841         activity = "<backend information not available>";
00842     else if (!superuser() && beentry->st_userid != GetUserId())
00843         activity = "<insufficient privilege>";
00844     else if (*(beentry->st_activity) == '\0')
00845         activity = "<command string not enabled>";
00846     else
00847         activity = beentry->st_activity;
00848 
00849     PG_RETURN_TEXT_P(cstring_to_text(activity));
00850 }
00851 
00852 
00853 Datum
00854 pg_stat_get_backend_waiting(PG_FUNCTION_ARGS)
00855 {
00856     int32       beid = PG_GETARG_INT32(0);
00857     bool        result;
00858     PgBackendStatus *beentry;
00859 
00860     if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
00861         PG_RETURN_NULL();
00862 
00863     if (!superuser() && beentry->st_userid != GetUserId())
00864         PG_RETURN_NULL();
00865 
00866     result = beentry->st_waiting;
00867 
00868     PG_RETURN_BOOL(result);
00869 }
00870 
00871 
00872 Datum
00873 pg_stat_get_backend_activity_start(PG_FUNCTION_ARGS)
00874 {
00875     int32       beid = PG_GETARG_INT32(0);
00876     TimestampTz result;
00877     PgBackendStatus *beentry;
00878 
00879     if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
00880         PG_RETURN_NULL();
00881 
00882     if (!superuser() && beentry->st_userid != GetUserId())
00883         PG_RETURN_NULL();
00884 
00885     result = beentry->st_activity_start_timestamp;
00886 
00887     /*
00888      * No time recorded for start of current query -- this is the case if the
00889      * user hasn't enabled query-level stats collection.
00890      */
00891     if (result == 0)
00892         PG_RETURN_NULL();
00893 
00894     PG_RETURN_TIMESTAMPTZ(result);
00895 }
00896 
00897 
00898 Datum
00899 pg_stat_get_backend_xact_start(PG_FUNCTION_ARGS)
00900 {
00901     int32       beid = PG_GETARG_INT32(0);
00902     TimestampTz result;
00903     PgBackendStatus *beentry;
00904 
00905     if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
00906         PG_RETURN_NULL();
00907 
00908     if (!superuser() && beentry->st_userid != GetUserId())
00909         PG_RETURN_NULL();
00910 
00911     result = beentry->st_xact_start_timestamp;
00912 
00913     if (result == 0)            /* not in a transaction */
00914         PG_RETURN_NULL();
00915 
00916     PG_RETURN_TIMESTAMPTZ(result);
00917 }
00918 
00919 
00920 Datum
00921 pg_stat_get_backend_start(PG_FUNCTION_ARGS)
00922 {
00923     int32       beid = PG_GETARG_INT32(0);
00924     TimestampTz result;
00925     PgBackendStatus *beentry;
00926 
00927     if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
00928         PG_RETURN_NULL();
00929 
00930     if (!superuser() && beentry->st_userid != GetUserId())
00931         PG_RETURN_NULL();
00932 
00933     result = beentry->st_proc_start_timestamp;
00934 
00935     if (result == 0)            /* probably can't happen? */
00936         PG_RETURN_NULL();
00937 
00938     PG_RETURN_TIMESTAMPTZ(result);
00939 }
00940 
00941 
00942 Datum
00943 pg_stat_get_backend_client_addr(PG_FUNCTION_ARGS)
00944 {
00945     int32       beid = PG_GETARG_INT32(0);
00946     PgBackendStatus *beentry;
00947     SockAddr    zero_clientaddr;
00948     char        remote_host[NI_MAXHOST];
00949     int         ret;
00950 
00951     if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
00952         PG_RETURN_NULL();
00953 
00954     if (!superuser() && beentry->st_userid != GetUserId())
00955         PG_RETURN_NULL();
00956 
00957     /* A zeroed client addr means we don't know */
00958     memset(&zero_clientaddr, 0, sizeof(zero_clientaddr));
00959     if (memcmp(&(beentry->st_clientaddr), &zero_clientaddr,
00960                sizeof(zero_clientaddr) == 0))
00961         PG_RETURN_NULL();
00962 
00963     switch (beentry->st_clientaddr.addr.ss_family)
00964     {
00965         case AF_INET:
00966 #ifdef HAVE_IPV6
00967         case AF_INET6:
00968 #endif
00969             break;
00970         default:
00971             PG_RETURN_NULL();
00972     }
00973 
00974     remote_host[0] = '\0';
00975     ret = pg_getnameinfo_all(&beentry->st_clientaddr.addr,
00976                              beentry->st_clientaddr.salen,
00977                              remote_host, sizeof(remote_host),
00978                              NULL, 0,
00979                              NI_NUMERICHOST | NI_NUMERICSERV);
00980     if (ret != 0)
00981         PG_RETURN_NULL();
00982 
00983     clean_ipv6_addr(beentry->st_clientaddr.addr.ss_family, remote_host);
00984 
00985     PG_RETURN_INET_P(DirectFunctionCall1(inet_in,
00986                                          CStringGetDatum(remote_host)));
00987 }
00988 
00989 Datum
00990 pg_stat_get_backend_client_port(PG_FUNCTION_ARGS)
00991 {
00992     int32       beid = PG_GETARG_INT32(0);
00993     PgBackendStatus *beentry;
00994     SockAddr    zero_clientaddr;
00995     char        remote_port[NI_MAXSERV];
00996     int         ret;
00997 
00998     if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
00999         PG_RETURN_NULL();
01000 
01001     if (!superuser() && beentry->st_userid != GetUserId())
01002         PG_RETURN_NULL();
01003 
01004     /* A zeroed client addr means we don't know */
01005     memset(&zero_clientaddr, 0, sizeof(zero_clientaddr));
01006     if (memcmp(&(beentry->st_clientaddr), &zero_clientaddr,
01007                sizeof(zero_clientaddr) == 0))
01008         PG_RETURN_NULL();
01009 
01010     switch (beentry->st_clientaddr.addr.ss_family)
01011     {
01012         case AF_INET:
01013 #ifdef HAVE_IPV6
01014         case AF_INET6:
01015 #endif
01016             break;
01017         case AF_UNIX:
01018             PG_RETURN_INT32(-1);
01019         default:
01020             PG_RETURN_NULL();
01021     }
01022 
01023     remote_port[0] = '\0';
01024     ret = pg_getnameinfo_all(&beentry->st_clientaddr.addr,
01025                              beentry->st_clientaddr.salen,
01026                              NULL, 0,
01027                              remote_port, sizeof(remote_port),
01028                              NI_NUMERICHOST | NI_NUMERICSERV);
01029     if (ret != 0)
01030         PG_RETURN_NULL();
01031 
01032     PG_RETURN_DATUM(DirectFunctionCall1(int4in,
01033                                         CStringGetDatum(remote_port)));
01034 }
01035 
01036 
01037 Datum
01038 pg_stat_get_db_numbackends(PG_FUNCTION_ARGS)
01039 {
01040     Oid         dbid = PG_GETARG_OID(0);
01041     int32       result;
01042     int         tot_backends = pgstat_fetch_stat_numbackends();
01043     int         beid;
01044 
01045     result = 0;
01046     for (beid = 1; beid <= tot_backends; beid++)
01047     {
01048         PgBackendStatus *beentry = pgstat_fetch_stat_beentry(beid);
01049 
01050         if (beentry && beentry->st_databaseid == dbid)
01051             result++;
01052     }
01053 
01054     PG_RETURN_INT32(result);
01055 }
01056 
01057 
01058 Datum
01059 pg_stat_get_db_xact_commit(PG_FUNCTION_ARGS)
01060 {
01061     Oid         dbid = PG_GETARG_OID(0);
01062     int64       result;
01063     PgStat_StatDBEntry *dbentry;
01064 
01065     if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
01066         result = 0;
01067     else
01068         result = (int64) (dbentry->n_xact_commit);
01069 
01070     PG_RETURN_INT64(result);
01071 }
01072 
01073 
01074 Datum
01075 pg_stat_get_db_xact_rollback(PG_FUNCTION_ARGS)
01076 {
01077     Oid         dbid = PG_GETARG_OID(0);
01078     int64       result;
01079     PgStat_StatDBEntry *dbentry;
01080 
01081     if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
01082         result = 0;
01083     else
01084         result = (int64) (dbentry->n_xact_rollback);
01085 
01086     PG_RETURN_INT64(result);
01087 }
01088 
01089 
01090 Datum
01091 pg_stat_get_db_blocks_fetched(PG_FUNCTION_ARGS)
01092 {
01093     Oid         dbid = PG_GETARG_OID(0);
01094     int64       result;
01095     PgStat_StatDBEntry *dbentry;
01096 
01097     if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
01098         result = 0;
01099     else
01100         result = (int64) (dbentry->n_blocks_fetched);
01101 
01102     PG_RETURN_INT64(result);
01103 }
01104 
01105 
01106 Datum
01107 pg_stat_get_db_blocks_hit(PG_FUNCTION_ARGS)
01108 {
01109     Oid         dbid = PG_GETARG_OID(0);
01110     int64       result;
01111     PgStat_StatDBEntry *dbentry;
01112 
01113     if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
01114         result = 0;
01115     else
01116         result = (int64) (dbentry->n_blocks_hit);
01117 
01118     PG_RETURN_INT64(result);
01119 }
01120 
01121 
01122 Datum
01123 pg_stat_get_db_tuples_returned(PG_FUNCTION_ARGS)
01124 {
01125     Oid         dbid = PG_GETARG_OID(0);
01126     int64       result;
01127     PgStat_StatDBEntry *dbentry;
01128 
01129     if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
01130         result = 0;
01131     else
01132         result = (int64) (dbentry->n_tuples_returned);
01133 
01134     PG_RETURN_INT64(result);
01135 }
01136 
01137 
01138 Datum
01139 pg_stat_get_db_tuples_fetched(PG_FUNCTION_ARGS)
01140 {
01141     Oid         dbid = PG_GETARG_OID(0);
01142     int64       result;
01143     PgStat_StatDBEntry *dbentry;
01144 
01145     if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
01146         result = 0;
01147     else
01148         result = (int64) (dbentry->n_tuples_fetched);
01149 
01150     PG_RETURN_INT64(result);
01151 }
01152 
01153 
01154 Datum
01155 pg_stat_get_db_tuples_inserted(PG_FUNCTION_ARGS)
01156 {
01157     Oid         dbid = PG_GETARG_OID(0);
01158     int64       result;
01159     PgStat_StatDBEntry *dbentry;
01160 
01161     if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
01162         result = 0;
01163     else
01164         result = (int64) (dbentry->n_tuples_inserted);
01165 
01166     PG_RETURN_INT64(result);
01167 }
01168 
01169 
01170 Datum
01171 pg_stat_get_db_tuples_updated(PG_FUNCTION_ARGS)
01172 {
01173     Oid         dbid = PG_GETARG_OID(0);
01174     int64       result;
01175     PgStat_StatDBEntry *dbentry;
01176 
01177     if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
01178         result = 0;
01179     else
01180         result = (int64) (dbentry->n_tuples_updated);
01181 
01182     PG_RETURN_INT64(result);
01183 }
01184 
01185 
01186 Datum
01187 pg_stat_get_db_tuples_deleted(PG_FUNCTION_ARGS)
01188 {
01189     Oid         dbid = PG_GETARG_OID(0);
01190     int64       result;
01191     PgStat_StatDBEntry *dbentry;
01192 
01193     if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
01194         result = 0;
01195     else
01196         result = (int64) (dbentry->n_tuples_deleted);
01197 
01198     PG_RETURN_INT64(result);
01199 }
01200 
01201 Datum
01202 pg_stat_get_db_stat_reset_time(PG_FUNCTION_ARGS)
01203 {
01204     Oid         dbid = PG_GETARG_OID(0);
01205     TimestampTz result;
01206     PgStat_StatDBEntry *dbentry;
01207 
01208     if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
01209         result = 0;
01210     else
01211         result = dbentry->stat_reset_timestamp;
01212 
01213     if (result == 0)
01214         PG_RETURN_NULL();
01215     else
01216         PG_RETURN_TIMESTAMPTZ(result);
01217 }
01218 
01219 Datum
01220 pg_stat_get_db_temp_files(PG_FUNCTION_ARGS)
01221 {
01222     Oid         dbid = PG_GETARG_OID(0);
01223     int64       result;
01224     PgStat_StatDBEntry *dbentry;
01225 
01226     if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
01227         result = 0;
01228     else
01229         result = dbentry->n_temp_files;
01230 
01231     PG_RETURN_INT64(result);
01232 }
01233 
01234 
01235 Datum
01236 pg_stat_get_db_temp_bytes(PG_FUNCTION_ARGS)
01237 {
01238     Oid         dbid = PG_GETARG_OID(0);
01239     int64       result;
01240     PgStat_StatDBEntry *dbentry;
01241 
01242     if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
01243         result = 0;
01244     else
01245         result = dbentry->n_temp_bytes;
01246 
01247     PG_RETURN_INT64(result);
01248 }
01249 
01250 Datum
01251 pg_stat_get_db_conflict_tablespace(PG_FUNCTION_ARGS)
01252 {
01253     Oid         dbid = PG_GETARG_OID(0);
01254     int64       result;
01255     PgStat_StatDBEntry *dbentry;
01256 
01257     if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
01258         result = 0;
01259     else
01260         result = (int64) (dbentry->n_conflict_tablespace);
01261 
01262     PG_RETURN_INT64(result);
01263 }
01264 
01265 Datum
01266 pg_stat_get_db_conflict_lock(PG_FUNCTION_ARGS)
01267 {
01268     Oid         dbid = PG_GETARG_OID(0);
01269     int64       result;
01270     PgStat_StatDBEntry *dbentry;
01271 
01272     if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
01273         result = 0;
01274     else
01275         result = (int64) (dbentry->n_conflict_lock);
01276 
01277     PG_RETURN_INT64(result);
01278 }
01279 
01280 Datum
01281 pg_stat_get_db_conflict_snapshot(PG_FUNCTION_ARGS)
01282 {
01283     Oid         dbid = PG_GETARG_OID(0);
01284     int64       result;
01285     PgStat_StatDBEntry *dbentry;
01286 
01287     if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
01288         result = 0;
01289     else
01290         result = (int64) (dbentry->n_conflict_snapshot);
01291 
01292     PG_RETURN_INT64(result);
01293 }
01294 
01295 Datum
01296 pg_stat_get_db_conflict_bufferpin(PG_FUNCTION_ARGS)
01297 {
01298     Oid         dbid = PG_GETARG_OID(0);
01299     int64       result;
01300     PgStat_StatDBEntry *dbentry;
01301 
01302     if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
01303         result = 0;
01304     else
01305         result = (int64) (dbentry->n_conflict_bufferpin);
01306 
01307     PG_RETURN_INT64(result);
01308 }
01309 
01310 Datum
01311 pg_stat_get_db_conflict_startup_deadlock(PG_FUNCTION_ARGS)
01312 {
01313     Oid         dbid = PG_GETARG_OID(0);
01314     int64       result;
01315     PgStat_StatDBEntry *dbentry;
01316 
01317     if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
01318         result = 0;
01319     else
01320         result = (int64) (dbentry->n_conflict_startup_deadlock);
01321 
01322     PG_RETURN_INT64(result);
01323 }
01324 
01325 Datum
01326 pg_stat_get_db_conflict_all(PG_FUNCTION_ARGS)
01327 {
01328     Oid         dbid = PG_GETARG_OID(0);
01329     int64       result;
01330     PgStat_StatDBEntry *dbentry;
01331 
01332     if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
01333         result = 0;
01334     else
01335         result = (int64) (
01336                           dbentry->n_conflict_tablespace +
01337                           dbentry->n_conflict_lock +
01338                           dbentry->n_conflict_snapshot +
01339                           dbentry->n_conflict_bufferpin +
01340                           dbentry->n_conflict_startup_deadlock);
01341 
01342     PG_RETURN_INT64(result);
01343 }
01344 
01345 Datum
01346 pg_stat_get_db_deadlocks(PG_FUNCTION_ARGS)
01347 {
01348     Oid         dbid = PG_GETARG_OID(0);
01349     int64       result;
01350     PgStat_StatDBEntry *dbentry;
01351 
01352     if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
01353         result = 0;
01354     else
01355         result = (int64) (dbentry->n_deadlocks);
01356 
01357     PG_RETURN_INT64(result);
01358 }
01359 
01360 Datum
01361 pg_stat_get_db_blk_read_time(PG_FUNCTION_ARGS)
01362 {
01363     Oid         dbid = PG_GETARG_OID(0);
01364     double      result;
01365     PgStat_StatDBEntry *dbentry;
01366 
01367     /* convert counter from microsec to millisec for display */
01368     if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
01369         result = 0;
01370     else
01371         result = ((double) dbentry->n_block_read_time) / 1000.0;
01372 
01373     PG_RETURN_FLOAT8(result);
01374 }
01375 
01376 Datum
01377 pg_stat_get_db_blk_write_time(PG_FUNCTION_ARGS)
01378 {
01379     Oid         dbid = PG_GETARG_OID(0);
01380     double      result;
01381     PgStat_StatDBEntry *dbentry;
01382 
01383     /* convert counter from microsec to millisec for display */
01384     if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
01385         result = 0;
01386     else
01387         result = ((double) dbentry->n_block_write_time) / 1000.0;
01388 
01389     PG_RETURN_FLOAT8(result);
01390 }
01391 
01392 Datum
01393 pg_stat_get_bgwriter_timed_checkpoints(PG_FUNCTION_ARGS)
01394 {
01395     PG_RETURN_INT64(pgstat_fetch_global()->timed_checkpoints);
01396 }
01397 
01398 Datum
01399 pg_stat_get_bgwriter_requested_checkpoints(PG_FUNCTION_ARGS)
01400 {
01401     PG_RETURN_INT64(pgstat_fetch_global()->requested_checkpoints);
01402 }
01403 
01404 Datum
01405 pg_stat_get_bgwriter_buf_written_checkpoints(PG_FUNCTION_ARGS)
01406 {
01407     PG_RETURN_INT64(pgstat_fetch_global()->buf_written_checkpoints);
01408 }
01409 
01410 Datum
01411 pg_stat_get_bgwriter_buf_written_clean(PG_FUNCTION_ARGS)
01412 {
01413     PG_RETURN_INT64(pgstat_fetch_global()->buf_written_clean);
01414 }
01415 
01416 Datum
01417 pg_stat_get_bgwriter_maxwritten_clean(PG_FUNCTION_ARGS)
01418 {
01419     PG_RETURN_INT64(pgstat_fetch_global()->maxwritten_clean);
01420 }
01421 
01422 Datum
01423 pg_stat_get_checkpoint_write_time(PG_FUNCTION_ARGS)
01424 {
01425     /* time is already in msec, just convert to double for presentation */
01426     PG_RETURN_FLOAT8((double) pgstat_fetch_global()->checkpoint_write_time);
01427 }
01428 
01429 Datum
01430 pg_stat_get_checkpoint_sync_time(PG_FUNCTION_ARGS)
01431 {
01432     /* time is already in msec, just convert to double for presentation */
01433     PG_RETURN_FLOAT8((double) pgstat_fetch_global()->checkpoint_sync_time);
01434 }
01435 
01436 Datum
01437 pg_stat_get_bgwriter_stat_reset_time(PG_FUNCTION_ARGS)
01438 {
01439     PG_RETURN_TIMESTAMPTZ(pgstat_fetch_global()->stat_reset_timestamp);
01440 }
01441 
01442 Datum
01443 pg_stat_get_buf_written_backend(PG_FUNCTION_ARGS)
01444 {
01445     PG_RETURN_INT64(pgstat_fetch_global()->buf_written_backend);
01446 }
01447 
01448 Datum
01449 pg_stat_get_buf_fsync_backend(PG_FUNCTION_ARGS)
01450 {
01451     PG_RETURN_INT64(pgstat_fetch_global()->buf_fsync_backend);
01452 }
01453 
01454 Datum
01455 pg_stat_get_buf_alloc(PG_FUNCTION_ARGS)
01456 {
01457     PG_RETURN_INT64(pgstat_fetch_global()->buf_alloc);
01458 }
01459 
01460 Datum
01461 pg_stat_get_xact_numscans(PG_FUNCTION_ARGS)
01462 {
01463     Oid         relid = PG_GETARG_OID(0);
01464     int64       result;
01465     PgStat_TableStatus *tabentry;
01466 
01467     if ((tabentry = find_tabstat_entry(relid)) == NULL)
01468         result = 0;
01469     else
01470         result = (int64) (tabentry->t_counts.t_numscans);
01471 
01472     PG_RETURN_INT64(result);
01473 }
01474 
01475 Datum
01476 pg_stat_get_xact_tuples_returned(PG_FUNCTION_ARGS)
01477 {
01478     Oid         relid = PG_GETARG_OID(0);
01479     int64       result;
01480     PgStat_TableStatus *tabentry;
01481 
01482     if ((tabentry = find_tabstat_entry(relid)) == NULL)
01483         result = 0;
01484     else
01485         result = (int64) (tabentry->t_counts.t_tuples_returned);
01486 
01487     PG_RETURN_INT64(result);
01488 }
01489 
01490 Datum
01491 pg_stat_get_xact_tuples_fetched(PG_FUNCTION_ARGS)
01492 {
01493     Oid         relid = PG_GETARG_OID(0);
01494     int64       result;
01495     PgStat_TableStatus *tabentry;
01496 
01497     if ((tabentry = find_tabstat_entry(relid)) == NULL)
01498         result = 0;
01499     else
01500         result = (int64) (tabentry->t_counts.t_tuples_fetched);
01501 
01502     PG_RETURN_INT64(result);
01503 }
01504 
01505 Datum
01506 pg_stat_get_xact_tuples_inserted(PG_FUNCTION_ARGS)
01507 {
01508     Oid         relid = PG_GETARG_OID(0);
01509     int64       result;
01510     PgStat_TableStatus *tabentry;
01511     PgStat_TableXactStatus *trans;
01512 
01513     if ((tabentry = find_tabstat_entry(relid)) == NULL)
01514         result = 0;
01515     else
01516     {
01517         result = tabentry->t_counts.t_tuples_inserted;
01518         /* live subtransactions' counts aren't in t_tuples_inserted yet */
01519         for (trans = tabentry->trans; trans != NULL; trans = trans->upper)
01520             result += trans->tuples_inserted;
01521     }
01522 
01523     PG_RETURN_INT64(result);
01524 }
01525 
01526 Datum
01527 pg_stat_get_xact_tuples_updated(PG_FUNCTION_ARGS)
01528 {
01529     Oid         relid = PG_GETARG_OID(0);
01530     int64       result;
01531     PgStat_TableStatus *tabentry;
01532     PgStat_TableXactStatus *trans;
01533 
01534     if ((tabentry = find_tabstat_entry(relid)) == NULL)
01535         result = 0;
01536     else
01537     {
01538         result = tabentry->t_counts.t_tuples_updated;
01539         /* live subtransactions' counts aren't in t_tuples_updated yet */
01540         for (trans = tabentry->trans; trans != NULL; trans = trans->upper)
01541             result += trans->tuples_updated;
01542     }
01543 
01544     PG_RETURN_INT64(result);
01545 }
01546 
01547 Datum
01548 pg_stat_get_xact_tuples_deleted(PG_FUNCTION_ARGS)
01549 {
01550     Oid         relid = PG_GETARG_OID(0);
01551     int64       result;
01552     PgStat_TableStatus *tabentry;
01553     PgStat_TableXactStatus *trans;
01554 
01555     if ((tabentry = find_tabstat_entry(relid)) == NULL)
01556         result = 0;
01557     else
01558     {
01559         result = tabentry->t_counts.t_tuples_deleted;
01560         /* live subtransactions' counts aren't in t_tuples_deleted yet */
01561         for (trans = tabentry->trans; trans != NULL; trans = trans->upper)
01562             result += trans->tuples_deleted;
01563     }
01564 
01565     PG_RETURN_INT64(result);
01566 }
01567 
01568 Datum
01569 pg_stat_get_xact_tuples_hot_updated(PG_FUNCTION_ARGS)
01570 {
01571     Oid         relid = PG_GETARG_OID(0);
01572     int64       result;
01573     PgStat_TableStatus *tabentry;
01574 
01575     if ((tabentry = find_tabstat_entry(relid)) == NULL)
01576         result = 0;
01577     else
01578         result = (int64) (tabentry->t_counts.t_tuples_hot_updated);
01579 
01580     PG_RETURN_INT64(result);
01581 }
01582 
01583 Datum
01584 pg_stat_get_xact_blocks_fetched(PG_FUNCTION_ARGS)
01585 {
01586     Oid         relid = PG_GETARG_OID(0);
01587     int64       result;
01588     PgStat_TableStatus *tabentry;
01589 
01590     if ((tabentry = find_tabstat_entry(relid)) == NULL)
01591         result = 0;
01592     else
01593         result = (int64) (tabentry->t_counts.t_blocks_fetched);
01594 
01595     PG_RETURN_INT64(result);
01596 }
01597 
01598 Datum
01599 pg_stat_get_xact_blocks_hit(PG_FUNCTION_ARGS)
01600 {
01601     Oid         relid = PG_GETARG_OID(0);
01602     int64       result;
01603     PgStat_TableStatus *tabentry;
01604 
01605     if ((tabentry = find_tabstat_entry(relid)) == NULL)
01606         result = 0;
01607     else
01608         result = (int64) (tabentry->t_counts.t_blocks_hit);
01609 
01610     PG_RETURN_INT64(result);
01611 }
01612 
01613 Datum
01614 pg_stat_get_xact_function_calls(PG_FUNCTION_ARGS)
01615 {
01616     Oid         funcid = PG_GETARG_OID(0);
01617     PgStat_BackendFunctionEntry *funcentry;
01618 
01619     if ((funcentry = find_funcstat_entry(funcid)) == NULL)
01620         PG_RETURN_NULL();
01621     PG_RETURN_INT64(funcentry->f_counts.f_numcalls);
01622 }
01623 
01624 Datum
01625 pg_stat_get_xact_function_total_time(PG_FUNCTION_ARGS)
01626 {
01627     Oid         funcid = PG_GETARG_OID(0);
01628     PgStat_BackendFunctionEntry *funcentry;
01629 
01630     if ((funcentry = find_funcstat_entry(funcid)) == NULL)
01631         PG_RETURN_NULL();
01632     PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(funcentry->f_counts.f_total_time));
01633 }
01634 
01635 Datum
01636 pg_stat_get_xact_function_self_time(PG_FUNCTION_ARGS)
01637 {
01638     Oid         funcid = PG_GETARG_OID(0);
01639     PgStat_BackendFunctionEntry *funcentry;
01640 
01641     if ((funcentry = find_funcstat_entry(funcid)) == NULL)
01642         PG_RETURN_NULL();
01643     PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(funcentry->f_counts.f_self_time));
01644 }
01645 
01646 
01647 /* Discard the active statistics snapshot */
01648 Datum
01649 pg_stat_clear_snapshot(PG_FUNCTION_ARGS)
01650 {
01651     pgstat_clear_snapshot();
01652 
01653     PG_RETURN_VOID();
01654 }
01655 
01656 
01657 /* Reset all counters for the current database */
01658 Datum
01659 pg_stat_reset(PG_FUNCTION_ARGS)
01660 {
01661     pgstat_reset_counters();
01662 
01663     PG_RETURN_VOID();
01664 }
01665 
01666 /* Reset some shared cluster-wide counters */
01667 Datum
01668 pg_stat_reset_shared(PG_FUNCTION_ARGS)
01669 {
01670     char       *target = text_to_cstring(PG_GETARG_TEXT_PP(0));
01671 
01672     pgstat_reset_shared_counters(target);
01673 
01674     PG_RETURN_VOID();
01675 }
01676 
01677 /* Reset a a single counter in the current database */
01678 Datum
01679 pg_stat_reset_single_table_counters(PG_FUNCTION_ARGS)
01680 {
01681     Oid         taboid = PG_GETARG_OID(0);
01682 
01683     pgstat_reset_single_counter(taboid, RESET_TABLE);
01684 
01685     PG_RETURN_VOID();
01686 }
01687 
01688 Datum
01689 pg_stat_reset_single_function_counters(PG_FUNCTION_ARGS)
01690 {
01691     Oid         funcoid = PG_GETARG_OID(0);
01692 
01693     pgstat_reset_single_counter(funcoid, RESET_FUNCTION);
01694 
01695     PG_RETURN_VOID();
01696 }