? src/backend/utils/adt/.pgstatfuncs.c.swp ? src/include/.pgstat.h.swp Index: src/backend/postmaster/pgstat.c =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/backend/postmaster/pgstat.c,v retrieving revision 1.31 diff -c -r1.31 pgstat.c *** src/backend/postmaster/pgstat.c 2002/10/24 23:19:13 1.31 --- src/backend/postmaster/pgstat.c 2003/02/23 04:09:28 *************** *** 1757,1762 **** --- 1757,1764 ---- beentry->databaseid = msg->m_databaseid; beentry->procpid = msg->m_procpid; beentry->userid = msg->m_userid; + beentry->bestart = GetCurrentAbsoluteTime(); + beentry->actstart = NULL; MemSet(beentry->activity, 0, PGSTAT_ACTIVITY_SIZE); /* *************** *** 2467,2472 **** --- 2470,2477 ---- */ if (pgstat_add_backend(&msg->m_hdr) != 0) return; + + pgStatBeTable[msg->m_hdr.m_backendid - 1].actstart = GetCurrentAbsoluteTime(); strncpy(pgStatBeTable[msg->m_hdr.m_backendid - 1].activity, msg->m_what, PGSTAT_ACTIVITY_SIZE); Index: src/backend/utils/adt/pgstatfuncs.c =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/backend/utils/adt/pgstatfuncs.c,v retrieving revision 1.9 diff -c -r1.9 pgstatfuncs.c *** src/backend/utils/adt/pgstatfuncs.c 2002/12/04 05:18:34 1.9 --- src/backend/utils/adt/pgstatfuncs.c 2003/02/23 04:09:47 *************** *** 1,13 **** #include "postgres.h" #include "fmgr.h" #include "miscadmin.h" ! #include "utils/hsearch.h" #include "access/xact.h" #include "catalog/pg_shadow.h" #include "nodes/execnodes.h" ! ! #include "pgstat.h" extern Datum pg_stat_get_numscans(PG_FUNCTION_ARGS); extern Datum pg_stat_get_tuples_returned(PG_FUNCTION_ARGS); --- 1,15 ---- #include "postgres.h" #include "fmgr.h" + #include "funcapi.h" #include "miscadmin.h" ! #include "pgstat.h" ! #include "access/heapam.h" #include "access/xact.h" #include "catalog/pg_shadow.h" + #include "catalog/pg_type.h" #include "nodes/execnodes.h" ! #include "utils/hsearch.h" extern Datum pg_stat_get_numscans(PG_FUNCTION_ARGS); extern Datum pg_stat_get_tuples_returned(PG_FUNCTION_ARGS); *************** *** 18,30 **** extern Datum pg_stat_get_blocks_fetched(PG_FUNCTION_ARGS); extern Datum pg_stat_get_blocks_hit(PG_FUNCTION_ARGS); - extern Datum pg_stat_get_backend_idset(PG_FUNCTION_ARGS); extern Datum pg_backend_pid(PG_FUNCTION_ARGS); extern Datum pg_stat_reset(PG_FUNCTION_ARGS); - extern Datum pg_stat_get_backend_pid(PG_FUNCTION_ARGS); - extern Datum pg_stat_get_backend_dbid(PG_FUNCTION_ARGS); - extern Datum pg_stat_get_backend_userid(PG_FUNCTION_ARGS); - extern Datum pg_stat_get_backend_activity(PG_FUNCTION_ARGS); extern Datum pg_stat_get_db_numbackends(PG_FUNCTION_ARGS); extern Datum pg_stat_get_db_xact_commit(PG_FUNCTION_ARGS); --- 20,27 ---- *************** *** 32,37 **** --- 29,35 ---- extern Datum pg_stat_get_db_blocks_fetched(PG_FUNCTION_ARGS); extern Datum pg_stat_get_db_blocks_hit(PG_FUNCTION_ARGS); + extern Datum pg_stat_activity(PG_FUNCTION_ARGS); Datum pg_stat_get_numscans(PG_FUNCTION_ARGS) *************** *** 178,219 **** Datum - pg_stat_get_backend_idset(PG_FUNCTION_ARGS) - { - FmgrInfo *fmgr_info = fcinfo->flinfo; - int32 result; - - if (fcinfo->resultinfo == NULL || - !IsA(fcinfo->resultinfo, ReturnSetInfo)) - elog(ERROR, "pg_stat_get_backend_idset: called in context that does not accept a set result"); - - if (fmgr_info->fn_extra == NULL) - { - if (fmgr_info->fn_mcxt == NULL) - elog(ERROR, "No function memory context in set-function"); - fmgr_info->fn_extra = MemoryContextAlloc(fmgr_info->fn_mcxt, - 2 * sizeof(int)); - ((int *) (fmgr_info->fn_extra))[0] = 0; - ((int *) (fmgr_info->fn_extra))[1] = pgstat_fetch_stat_numbackends(); - } - - ((int *) (fmgr_info->fn_extra))[0] += 1; - result = ((int *) (fmgr_info->fn_extra))[0]; - - if (result > ((int *) (fmgr_info->fn_extra))[1]) - { - pfree(fmgr_info->fn_extra); - fmgr_info->fn_extra = NULL; - ((ReturnSetInfo *) (fcinfo->resultinfo))->isDone = ExprEndResult; - PG_RETURN_NULL(); - } - - ((ReturnSetInfo *) (fcinfo->resultinfo))->isDone = ExprMultipleResult; - PG_RETURN_INT32(result); - } - - - Datum pg_backend_pid(PG_FUNCTION_ARGS) { PG_RETURN_INT32(MyProcPid); --- 176,181 ---- *************** *** 231,307 **** PG_RETURN_BOOL(true); } - Datum - pg_stat_get_backend_pid(PG_FUNCTION_ARGS) - { - PgStat_StatBeEntry *beentry; - int32 beid; - - beid = PG_GETARG_INT32(0); - - if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL) - PG_RETURN_NULL(); - - PG_RETURN_INT32(beentry->procpid); - } - - - Datum - pg_stat_get_backend_dbid(PG_FUNCTION_ARGS) - { - PgStat_StatBeEntry *beentry; - int32 beid; - - beid = PG_GETARG_INT32(0); - - if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL) - PG_RETURN_NULL(); - - PG_RETURN_OID(beentry->databaseid); - } - - - Datum - pg_stat_get_backend_userid(PG_FUNCTION_ARGS) - { - PgStat_StatBeEntry *beentry; - int32 beid; - - beid = PG_GETARG_INT32(0); - - if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL) - PG_RETURN_NULL(); - - PG_RETURN_INT32(beentry->userid); - } - Datum - pg_stat_get_backend_activity(PG_FUNCTION_ARGS) - { - PgStat_StatBeEntry *beentry; - int32 beid; - int len; - text *result; - - if (!superuser()) - PG_RETURN_NULL(); - - beid = PG_GETARG_INT32(0); - - if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL) - PG_RETURN_NULL(); - - len = strlen(beentry->activity); - result = palloc(VARHDRSZ + len); - VARATT_SIZEP(result) = VARHDRSZ + len; - memcpy(VARDATA(result), beentry->activity, len); - - PG_RETURN_TEXT_P(result); - } - - - Datum pg_stat_get_db_numbackends(PG_FUNCTION_ARGS) { PgStat_StatDBEntry *dbentry; --- 193,200 ---- *************** *** 388,391 **** --- 281,409 ---- result = (int64) (dbentry->n_blocks_hit); PG_RETURN_INT64(result); + } + + /* + * pg_stat_activity + * + * Function used to build the pg_stat_activity data + */ + Datum + pg_stat_activity(PG_FUNCTION_ARGS) + { + FuncCallContext *funcctx; + TupleDesc tupdesc; + int call_cntr; + int max_calls; + TupleTableSlot *slot; + AttInMetadata *attinmeta; + MemoryContext oldcontext; + + /* stuff done only on the first call of the function */ + if (SRF_IS_FIRSTCALL()) + { + /* create a function context for cross-call persistence */ + funcctx = SRF_FIRSTCALL_INIT(); + + /* + * switch to memory context appropriate for multiple function + * calls + */ + oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); + + /* need a tuple descriptor representing the pg_stat_activity table */ + tupdesc = CreateTemplateTupleDesc(6, false); + TupleDescInitEntry(tupdesc, (AttrNumber) 1, "datid", + OIDOID, -1, 0, false); + TupleDescInitEntry(tupdesc, (AttrNumber) 2, "procpid", + INT4OID, -1, 0, false); + TupleDescInitEntry(tupdesc, (AttrNumber) 3, "connect_start", + ABSTIMEOID, -1, 0, false); + TupleDescInitEntry(tupdesc, (AttrNumber) 4, "usesysid", + INT4OID, -1, 0, false); + TupleDescInitEntry(tupdesc, (AttrNumber) 5, "query_start", + ABSTIMEOID, -1, 0, false); + TupleDescInitEntry(tupdesc, (AttrNumber) 6, "current_query", + TEXTOID, -1, 0, false); + + /* allocate a slot for a tuple with this tupdesc */ + slot = TupleDescGetSlot(tupdesc); + + /* assign slot to function context */ + funcctx->slot = slot; + + /* + * Generate attribute metadata needed later to produce tuples from + * raw C strings + */ + attinmeta = TupleDescGetAttInMetadata(tupdesc); + funcctx->attinmeta = attinmeta; + + /* total number of tuples to be returned */ + funcctx->max_calls = pgstat_fetch_stat_numbackends(); + + MemoryContextSwitchTo(oldcontext); + } + + /* stuff done on every call of the function */ + funcctx = SRF_PERCALL_SETUP(); + + call_cntr = funcctx->call_cntr; + max_calls = funcctx->max_calls; + slot = funcctx->slot; + attinmeta = funcctx->attinmeta; + + if (call_cntr < max_calls) /* do when there is more left to send */ + { + Datum values[6]; + char nulls[6]; + HeapTuple tuple; + Datum result; + PgStat_StatBeEntry *beentry; + + MemSet(values, 0, sizeof(values)); + MemSet(nulls, ' ', sizeof(nulls)); + + if ((beentry = pgstat_fetch_stat_beentry(call_cntr + 1)) == NULL) + PG_RETURN_NULL(); + + /* + * Prepare a values array for storage in our slot. This should be + * an array of C strings which will be processed later by the + * appropriate "in" functions. + */ + values[0] = ObjectIdGetDatum(beentry->databaseid); + values[1] = ObjectIdGetDatum(beentry->procpid); + values[2] = AbsoluteTimeGetDatum(beentry->bestart); + values[3] = Int32GetDatum(beentry->userid); + + /* Only the superuser is allowed to see the currently executing query */ + if (superuser() && strlen(beentry->activity) > 0) + { + text *activity; + int len; + + values[4] = AbsoluteTimeGetDatum(beentry->actstart); + + len = strlen(beentry->activity); + activity = palloc(VARHDRSZ + len); + VARATT_SIZEP(activity) = VARHDRSZ + len; + memcpy(VARDATA(activity), beentry->activity, len); + values[5] = PointerGetDatum(activity); + } + else + { + nulls[4] = 'n'; + nulls[5] = 'n'; + } + + tuple = heap_formtuple(funcctx->slot->ttc_tupleDescriptor, + values, nulls); + result = TupleGetDatum(funcctx->slot, tuple); + + SRF_RETURN_NEXT(funcctx, result); + } + else + /* do when there is no more left */ + SRF_RETURN_DONE(funcctx); } Index: src/include/pgstat.h =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/include/pgstat.h,v retrieving revision 1.12 diff -c -r1.12 pgstat.h *** src/include/pgstat.h 2003/01/09 18:00:24 1.12 --- src/include/pgstat.h 2003/02/23 04:10:01 *************** *** 11,16 **** --- 11,18 ---- #ifndef PGSTAT_H #define PGSTAT_H + #include "utils/nabstime.h" + /* ---------- * Paths for the statistics files. The %s is replaced with the * installations $PGDATA. *************** *** 110,115 **** --- 112,119 ---- Oid databaseid; Oid userid; int procpid; + AbsoluteTime bestart; + AbsoluteTime actstart; char activity[PGSTAT_ACTIVITY_SIZE]; } PgStat_StatBeEntry; Index: src/include/catalog/pg_proc.h =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/include/catalog/pg_proc.h,v retrieving revision 1.284 diff -c -r1.284 pg_proc.h *** src/include/catalog/pg_proc.h 2003/02/22 00:45:05 1.284 --- src/include/catalog/pg_proc.h 2003/02/23 04:11:42 *************** *** 2727,2746 **** DESCR("Statistics: Number of blocks fetched"); DATA(insert OID = 1935 ( pg_stat_get_blocks_hit PGNSP PGUID 12 f f t f s 1 20 "26" pg_stat_get_blocks_hit - _null_ )); DESCR("Statistics: Number of blocks found in cache"); - DATA(insert OID = 1936 ( pg_stat_get_backend_idset PGNSP PGUID 12 f f t t s 0 23 "" pg_stat_get_backend_idset - _null_ )); - DESCR("Statistics: Currently active backend IDs"); - DATA(insert OID = 2026 ( pg_backend_pid PGNSP PGUID 12 f f t f s 0 23 "" pg_backend_pid - _null_ )); - DESCR("Statistics: Current backend PID"); DATA(insert OID = 2274 ( pg_stat_reset PGNSP PGUID 12 f f f f v 0 16 "" pg_stat_reset - _null_ )); DESCR("Statistics: Reset collected statistics"); ! DATA(insert OID = 1937 ( pg_stat_get_backend_pid PGNSP PGUID 12 f f t f s 1 23 "23" pg_stat_get_backend_pid - _null_ )); ! DESCR("Statistics: PID of backend"); ! DATA(insert OID = 1938 ( pg_stat_get_backend_dbid PGNSP PGUID 12 f f t f s 1 26 "23" pg_stat_get_backend_dbid - _null_ )); ! DESCR("Statistics: Database ID of backend"); ! DATA(insert OID = 1939 ( pg_stat_get_backend_userid PGNSP PGUID 12 f f t f s 1 23 "23" pg_stat_get_backend_userid - _null_ )); ! DESCR("Statistics: User ID of backend"); ! DATA(insert OID = 1940 ( pg_stat_get_backend_activity PGNSP PGUID 12 f f t f s 1 25 "23" pg_stat_get_backend_activity - _null_ )); ! DESCR("Statistics: Current query of backend"); DATA(insert OID = 1941 ( pg_stat_get_db_numbackends PGNSP PGUID 12 f f t f s 1 23 "26" pg_stat_get_db_numbackends - _null_ )); DESCR("Statistics: Number of backends in database"); DATA(insert OID = 1942 ( pg_stat_get_db_xact_commit PGNSP PGUID 12 f f t f s 1 20 "26" pg_stat_get_db_xact_commit - _null_ )); --- 2727,2736 ---- DESCR("Statistics: Number of blocks fetched"); DATA(insert OID = 1935 ( pg_stat_get_blocks_hit PGNSP PGUID 12 f f t f s 1 20 "26" pg_stat_get_blocks_hit - _null_ )); DESCR("Statistics: Number of blocks found in cache"); DATA(insert OID = 2274 ( pg_stat_reset PGNSP PGUID 12 f f f f v 0 16 "" pg_stat_reset - _null_ )); DESCR("Statistics: Reset collected statistics"); ! DATA(insert OID = 1940 ( pg_stat_activity PGNSP PGUID 12 f f f t v 0 2249 "" pg_stat_activity - _null_ )); ! DESCR("Statustics: Supply data for pg_stat_activity view"); DATA(insert OID = 1941 ( pg_stat_get_db_numbackends PGNSP PGUID 12 f f t f s 1 23 "26" pg_stat_get_db_numbackends - _null_ )); DESCR("Statistics: Number of backends in database"); DATA(insert OID = 1942 ( pg_stat_get_db_xact_commit PGNSP PGUID 12 f f t f s 1 20 "26" pg_stat_get_db_xact_commit - _null_ )); Index: src/test/regress/expected/rules.out =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/test/regress/expected/rules.out,v retrieving revision 1.72 diff -c -r1.72 rules.out *** src/test/regress/expected/rules.out 2003/02/19 23:41:15 1.72 --- src/test/regress/expected/rules.out 2003/02/23 04:12:47 *************** *** 1274,1280 **** pg_locks | SELECT l.relation, l."database", l."transaction", l.pid, l."mode", l.granted FROM pg_lock_status() l(relation oid, "database" oid, "transaction" xid, pid integer, "mode" text, granted boolean); pg_rules | SELECT n.nspname AS schemaname, c.relname AS tablename, r.rulename, pg_get_ruledef(r.oid) AS definition FROM ((pg_rewrite r JOIN pg_class c ON ((c.oid = r.ev_class))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) WHERE (r.rulename <> '_RETURN'::name); pg_settings | SELECT a.name, a.setting FROM pg_show_all_settings() a(name text, setting text); - pg_stat_activity | SELECT d.oid AS datid, d.datname, pg_stat_get_backend_pid(s.backendid) AS procpid, pg_stat_get_backend_userid(s.backendid) AS usesysid, u.usename, pg_stat_get_backend_activity(s.backendid) AS current_query FROM pg_database d, (SELECT pg_stat_get_backend_idset() AS backendid) s, pg_shadow u WHERE ((pg_stat_get_backend_dbid(s.backendid) = d.oid) AND (pg_stat_get_backend_userid(s.backendid) = u.usesysid)); pg_stat_all_indexes | SELECT c.oid AS relid, i.oid AS indexrelid, n.nspname AS schemaname, c.relname, i.relname AS indexrelname, pg_stat_get_numscans(i.oid) AS idx_scan, pg_stat_get_tuples_returned(i.oid) AS idx_tup_read, pg_stat_get_tuples_fetched(i.oid) AS idx_tup_fetch FROM (((pg_class c JOIN pg_index x ON ((c.oid = x.indrelid))) JOIN pg_class i ON ((i.oid = x.indexrelid))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) WHERE (c.relkind = 'r'::"char"); pg_stat_all_tables | SELECT c.oid AS relid, n.nspname AS schemaname, c.relname, pg_stat_get_numscans(c.oid) AS seq_scan, pg_stat_get_tuples_returned(c.oid) AS seq_tup_read, sum(pg_stat_get_numscans(i.indexrelid)) AS idx_scan, sum(pg_stat_get_tuples_fetched(i.indexrelid)) AS idx_tup_fetch, pg_stat_get_tuples_inserted(c.oid) AS n_tup_ins, pg_stat_get_tuples_updated(c.oid) AS n_tup_upd, pg_stat_get_tuples_deleted(c.oid) AS n_tup_del FROM ((pg_class c LEFT JOIN pg_index i ON ((c.oid = i.indrelid))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) WHERE (c.relkind = 'r'::"char") GROUP BY c.oid, n.nspname, c.relname; pg_stat_database | SELECT d.oid AS datid, d.datname, pg_stat_get_db_numbackends(d.oid) AS numbackends, pg_stat_get_db_xact_commit(d.oid) AS xact_commit, pg_stat_get_db_xact_rollback(d.oid) AS xact_rollback, (pg_stat_get_db_blocks_fetched(d.oid) - pg_stat_get_db_blocks_hit(d.oid)) AS blks_read, pg_stat_get_db_blocks_hit(d.oid) AS blks_hit FROM pg_database d; --- 1274,1279 ---- *************** *** 1309,1315 **** shoelace_obsolete | SELECT shoelace.sl_name, shoelace.sl_avail, shoelace.sl_color, shoelace.sl_len, shoelace.sl_unit, shoelace.sl_len_cm FROM shoelace WHERE (NOT (EXISTS (SELECT shoe.shoename FROM shoe WHERE (shoe.slcolor = shoelace.sl_color)))); street | SELECT r.name, r.thepath, c.cname FROM ONLY road r, real_city c WHERE (c.outline ## r.thepath); toyemp | SELECT emp.name, emp.age, emp."location", (12 * emp.salary) AS annualsal FROM emp; ! (40 rows) SELECT tablename, rulename, definition FROM pg_rules ORDER BY tablename, rulename; --- 1308,1314 ---- shoelace_obsolete | SELECT shoelace.sl_name, shoelace.sl_avail, shoelace.sl_color, shoelace.sl_len, shoelace.sl_unit, shoelace.sl_len_cm FROM shoelace WHERE (NOT (EXISTS (SELECT shoe.shoename FROM shoe WHERE (shoe.slcolor = shoelace.sl_color)))); street | SELECT r.name, r.thepath, c.cname FROM ONLY road r, real_city c WHERE (c.outline ## r.thepath); toyemp | SELECT emp.name, emp.age, emp."location", (12 * emp.salary) AS annualsal FROM emp; ! (39 rows) SELECT tablename, rulename, definition FROM pg_rules ORDER BY tablename, rulename;