]> granicus.if.org Git - postgresql/blob - src/backend/utils/adt/pgstatfuncs.c
This patch reduces the size of the message header used by statistics
[postgresql] / src / backend / utils / adt / pgstatfuncs.c
1 /*-------------------------------------------------------------------------
2  *
3  * pgstatfuncs.c
4  *        Functions for accessing the statistics collector data
5  *
6  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *        $PostgreSQL: pgsql/src/backend/utils/adt/pgstatfuncs.c,v 1.22 2005/05/11 01:41:41 neilc Exp $
12  *
13  *-------------------------------------------------------------------------
14  */
15 #include "postgres.h"
16
17 #include "access/xact.h"
18 #include "catalog/pg_shadow.h"
19 #include "fmgr.h"
20 #include "funcapi.h"
21 #include "miscadmin.h"
22 #include "nodes/execnodes.h"
23 #include "pgstat.h"
24 #include "utils/hsearch.h"
25 #include "utils/inet.h"
26 #include "utils/builtins.h"
27 #include "libpq/ip.h"
28
29 /* bogus ... these externs should be in a header file */
30 extern Datum pg_stat_get_numscans(PG_FUNCTION_ARGS);
31 extern Datum pg_stat_get_tuples_returned(PG_FUNCTION_ARGS);
32 extern Datum pg_stat_get_tuples_fetched(PG_FUNCTION_ARGS);
33 extern Datum pg_stat_get_tuples_inserted(PG_FUNCTION_ARGS);
34 extern Datum pg_stat_get_tuples_updated(PG_FUNCTION_ARGS);
35 extern Datum pg_stat_get_tuples_deleted(PG_FUNCTION_ARGS);
36 extern Datum pg_stat_get_blocks_fetched(PG_FUNCTION_ARGS);
37 extern Datum pg_stat_get_blocks_hit(PG_FUNCTION_ARGS);
38
39 extern Datum pg_stat_get_backend_idset(PG_FUNCTION_ARGS);
40 extern Datum pg_backend_pid(PG_FUNCTION_ARGS);
41 extern Datum pg_stat_reset(PG_FUNCTION_ARGS);
42 extern Datum pg_stat_get_backend_pid(PG_FUNCTION_ARGS);
43 extern Datum pg_stat_get_backend_dbid(PG_FUNCTION_ARGS);
44 extern Datum pg_stat_get_backend_userid(PG_FUNCTION_ARGS);
45 extern Datum pg_stat_get_backend_activity(PG_FUNCTION_ARGS);
46 extern Datum pg_stat_get_backend_activity_start(PG_FUNCTION_ARGS);
47 extern Datum pg_stat_get_backend_start(PG_FUNCTION_ARGS);
48 extern Datum pg_stat_get_backend_client_addr(PG_FUNCTION_ARGS);
49 extern Datum pg_stat_get_backend_client_port(PG_FUNCTION_ARGS);
50
51 extern Datum pg_stat_get_db_numbackends(PG_FUNCTION_ARGS);
52 extern Datum pg_stat_get_db_xact_commit(PG_FUNCTION_ARGS);
53 extern Datum pg_stat_get_db_xact_rollback(PG_FUNCTION_ARGS);
54 extern Datum pg_stat_get_db_blocks_fetched(PG_FUNCTION_ARGS);
55 extern Datum pg_stat_get_db_blocks_hit(PG_FUNCTION_ARGS);
56
57
58 Datum
59 pg_stat_get_numscans(PG_FUNCTION_ARGS)
60 {
61         PgStat_StatTabEntry *tabentry;
62         Oid                     relid;
63         int64           result;
64
65         relid = PG_GETARG_OID(0);
66
67         if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
68                 result = 0;
69         else
70                 result = (int64) (tabentry->numscans);
71
72         PG_RETURN_INT64(result);
73 }
74
75
76 Datum
77 pg_stat_get_tuples_returned(PG_FUNCTION_ARGS)
78 {
79         PgStat_StatTabEntry *tabentry;
80         Oid                     relid;
81         int64           result;
82
83         relid = PG_GETARG_OID(0);
84
85         if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
86                 result = 0;
87         else
88                 result = (int64) (tabentry->tuples_returned);
89
90         PG_RETURN_INT64(result);
91 }
92
93
94 Datum
95 pg_stat_get_tuples_fetched(PG_FUNCTION_ARGS)
96 {
97         PgStat_StatTabEntry *tabentry;
98         Oid                     relid;
99         int64           result;
100
101         relid = PG_GETARG_OID(0);
102
103         if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
104                 result = 0;
105         else
106                 result = (int64) (tabentry->tuples_fetched);
107
108         PG_RETURN_INT64(result);
109 }
110
111
112 Datum
113 pg_stat_get_tuples_inserted(PG_FUNCTION_ARGS)
114 {
115         PgStat_StatTabEntry *tabentry;
116         Oid                     relid;
117         int64           result;
118
119         relid = PG_GETARG_OID(0);
120
121         if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
122                 result = 0;
123         else
124                 result = (int64) (tabentry->tuples_inserted);
125
126         PG_RETURN_INT64(result);
127 }
128
129
130 Datum
131 pg_stat_get_tuples_updated(PG_FUNCTION_ARGS)
132 {
133         PgStat_StatTabEntry *tabentry;
134         Oid                     relid;
135         int64           result;
136
137         relid = PG_GETARG_OID(0);
138
139         if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
140                 result = 0;
141         else
142                 result = (int64) (tabentry->tuples_updated);
143
144         PG_RETURN_INT64(result);
145 }
146
147
148 Datum
149 pg_stat_get_tuples_deleted(PG_FUNCTION_ARGS)
150 {
151         PgStat_StatTabEntry *tabentry;
152         Oid                     relid;
153         int64           result;
154
155         relid = PG_GETARG_OID(0);
156
157         if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
158                 result = 0;
159         else
160                 result = (int64) (tabentry->tuples_deleted);
161
162         PG_RETURN_INT64(result);
163 }
164
165
166 Datum
167 pg_stat_get_blocks_fetched(PG_FUNCTION_ARGS)
168 {
169         PgStat_StatTabEntry *tabentry;
170         Oid                     relid;
171         int64           result;
172
173         relid = PG_GETARG_OID(0);
174
175         if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
176                 result = 0;
177         else
178                 result = (int64) (tabentry->blocks_fetched);
179
180         PG_RETURN_INT64(result);
181 }
182
183
184 Datum
185 pg_stat_get_blocks_hit(PG_FUNCTION_ARGS)
186 {
187         PgStat_StatTabEntry *tabentry;
188         Oid                     relid;
189         int64           result;
190
191         relid = PG_GETARG_OID(0);
192
193         if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
194                 result = 0;
195         else
196                 result = (int64) (tabentry->blocks_hit);
197
198         PG_RETURN_INT64(result);
199 }
200
201
202 Datum
203 pg_stat_get_backend_idset(PG_FUNCTION_ARGS)
204 {
205         FuncCallContext *funcctx;
206         int                *fctx;
207         int32           result;
208
209         /* stuff done only on the first call of the function */
210         if (SRF_IS_FIRSTCALL())
211         {
212                 /* create a function context for cross-call persistence */
213                 funcctx = SRF_FIRSTCALL_INIT();
214
215                 fctx = MemoryContextAlloc(funcctx->multi_call_memory_ctx,
216                                                                   2 * sizeof(int));
217                 funcctx->user_fctx = fctx;
218
219                 fctx[0] = 0;
220                 fctx[1] = pgstat_fetch_stat_numbackends();
221         }
222
223         /* stuff done on every call of the function */
224         funcctx = SRF_PERCALL_SETUP();
225         fctx = funcctx->user_fctx;
226
227         fctx[0] += 1;
228         result = fctx[0];
229
230         if (result <= fctx[1])
231         {
232                 /* do when there is more left to send */
233                 SRF_RETURN_NEXT(funcctx, Int32GetDatum(result));
234         }
235         else
236         {
237                 /* do when there is no more left */
238                 SRF_RETURN_DONE(funcctx);
239         }
240 }
241
242
243 Datum
244 pg_backend_pid(PG_FUNCTION_ARGS)
245 {
246         PG_RETURN_INT32(MyProcPid);
247 }
248
249 /*
250  * Built-in function for resetting the counters
251  */
252 Datum
253 pg_stat_reset(PG_FUNCTION_ARGS)
254 {
255         pgstat_reset_counters();
256
257         PG_RETURN_BOOL(true);
258 }
259
260 Datum
261 pg_stat_get_backend_pid(PG_FUNCTION_ARGS)
262 {
263         PgStat_StatBeEntry *beentry;
264         int32           beid;
265
266         beid = PG_GETARG_INT32(0);
267
268         if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
269                 PG_RETURN_NULL();
270
271         PG_RETURN_INT32(beentry->procpid);
272 }
273
274
275 Datum
276 pg_stat_get_backend_dbid(PG_FUNCTION_ARGS)
277 {
278         PgStat_StatBeEntry *beentry;
279         int32           beid;
280
281         beid = PG_GETARG_INT32(0);
282
283         if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
284                 PG_RETURN_NULL();
285
286         /* Not initialized yet? */
287         if (!OidIsValid(beentry->databaseid))
288                 PG_RETURN_NULL();
289
290         PG_RETURN_OID(beentry->databaseid);
291 }
292
293
294 Datum
295 pg_stat_get_backend_userid(PG_FUNCTION_ARGS)
296 {
297         PgStat_StatBeEntry *beentry;
298         int32           beid;
299
300         beid = PG_GETARG_INT32(0);
301
302         if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
303                 PG_RETURN_NULL();
304
305         /* Not initialized yet? */
306         if (!OidIsValid(beentry->userid))
307                 PG_RETURN_NULL();
308
309         PG_RETURN_INT32(beentry->userid);
310 }
311
312
313 Datum
314 pg_stat_get_backend_activity(PG_FUNCTION_ARGS)
315 {
316         PgStat_StatBeEntry *beentry;
317         int32           beid;
318         int                     len;
319         char       *activity;
320         text       *result;
321
322         beid = PG_GETARG_INT32(0);
323
324         if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
325                 activity = "<backend information not available>";
326         else if (!superuser() && beentry->userid != GetUserId())
327                 activity = "<insufficient privilege>";
328         else if (*(beentry->activity) == '\0')
329                 activity = "<command string not enabled>";
330         else
331                 activity = beentry->activity;
332
333         len = strlen(activity);
334         result = palloc(VARHDRSZ + len);
335         VARATT_SIZEP(result) = VARHDRSZ + len;
336         memcpy(VARDATA(result), activity, len);
337
338         PG_RETURN_TEXT_P(result);
339 }
340
341
342 Datum
343 pg_stat_get_backend_activity_start(PG_FUNCTION_ARGS)
344 {
345         PgStat_StatBeEntry *beentry;
346         int32           beid;
347         AbsoluteTime sec;
348         int                     usec;
349         TimestampTz result;
350
351         beid = PG_GETARG_INT32(0);
352
353         if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
354                 PG_RETURN_NULL();
355
356         if (!superuser() && beentry->userid != GetUserId())
357                 PG_RETURN_NULL();
358
359         sec = beentry->activity_start_sec;
360         usec = beentry->activity_start_usec;
361
362         /*
363          * No time recorded for start of current query -- this is the case if
364          * the user hasn't enabled query-level stats collection.
365          */
366         if (sec == 0 && usec == 0)
367                 PG_RETURN_NULL();
368
369         result = AbsoluteTimeUsecToTimestampTz(sec, usec);
370
371         PG_RETURN_TIMESTAMPTZ(result);
372 }
373
374 Datum
375 pg_stat_get_backend_start(PG_FUNCTION_ARGS)
376 {
377         PgStat_StatBeEntry *beentry;
378         int32       beid;
379         AbsoluteTime sec;
380         int         usec;
381         TimestampTz result;
382
383         beid = PG_GETARG_INT32(0);
384
385         if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
386                 PG_RETURN_NULL();
387
388         if (!superuser() && beentry->userid != GetUserId())
389                 PG_RETURN_NULL();
390
391         sec = beentry->start_sec;
392         usec = beentry->start_usec;
393
394         if (sec == 0 && usec == 0)
395                 PG_RETURN_NULL();
396
397         result = AbsoluteTimeUsecToTimestampTz(sec, usec);
398
399         PG_RETURN_TIMESTAMPTZ(result);
400 }
401
402
403 Datum
404 pg_stat_get_backend_client_addr(PG_FUNCTION_ARGS)
405 {
406         PgStat_StatBeEntry *beentry;
407         int32       beid;
408         char            remote_host[NI_MAXHOST];
409         int                     ret;
410
411         beid = PG_GETARG_INT32(0);
412
413         if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
414                 PG_RETURN_NULL();
415
416         /* Not initialized yet? */
417         if (!OidIsValid(beentry->userid))
418                 PG_RETURN_NULL();
419
420         if (!superuser() && beentry->userid != GetUserId())
421                 PG_RETURN_NULL();
422
423         switch (beentry->clientaddr.addr.ss_family)
424         {
425                 case AF_INET:
426 #ifdef HAVE_IPV6
427                 case AF_INET6:
428 #endif
429                         break;
430                 default:
431                         PG_RETURN_NULL();
432         }
433
434         remote_host[0] = '\0';
435         ret = getnameinfo_all(&beentry->clientaddr.addr, beentry->clientaddr.salen,
436                                                   remote_host, sizeof(remote_host),
437                                                   NULL, 0,
438                                                   NI_NUMERICHOST | NI_NUMERICSERV);
439         if (ret)
440                 PG_RETURN_NULL();
441
442         PG_RETURN_INET_P(DirectFunctionCall1(inet_in,
443                                                                                  CStringGetDatum(remote_host)));
444 }
445
446 Datum
447 pg_stat_get_backend_client_port(PG_FUNCTION_ARGS)
448 {
449         PgStat_StatBeEntry *beentry;
450         int32       beid;
451         char            remote_port[NI_MAXSERV];
452         int                     ret;
453
454         beid = PG_GETARG_INT32(0);
455
456         if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
457                 PG_RETURN_NULL();
458
459         /* Not initialized yet? */
460         if (!OidIsValid(beentry->userid))
461                 PG_RETURN_NULL();
462
463         if (!superuser() && beentry->userid != GetUserId())
464                 PG_RETURN_NULL();
465
466         switch (beentry->clientaddr.addr.ss_family)
467         {
468                 case AF_INET:
469 #ifdef HAVE_IPV6
470                 case AF_INET6:
471 #endif
472                         break;
473                 case AF_UNIX:
474                         PG_RETURN_INT32(-1);
475                 default:
476                         PG_RETURN_NULL();
477         }
478
479         remote_port[0] = '\0';
480         ret = getnameinfo_all(&beentry->clientaddr.addr,
481                                                   beentry->clientaddr.salen,
482                                                   NULL, 0,
483                                                   remote_port, sizeof(remote_port),
484                                                   NI_NUMERICHOST | NI_NUMERICSERV);
485         if (ret)
486                 PG_RETURN_NULL();
487
488         PG_RETURN_DATUM(DirectFunctionCall1(int4in, CStringGetDatum(remote_port)));
489 }
490
491
492 Datum
493 pg_stat_get_db_numbackends(PG_FUNCTION_ARGS)
494 {
495         PgStat_StatDBEntry *dbentry;
496         Oid                     dbid;
497         int32           result;
498
499         dbid = PG_GETARG_OID(0);
500
501         if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
502                 result = 0;
503         else
504                 result = (int32) (dbentry->n_backends);
505
506         PG_RETURN_INT32(result);
507 }
508
509
510 Datum
511 pg_stat_get_db_xact_commit(PG_FUNCTION_ARGS)
512 {
513         PgStat_StatDBEntry *dbentry;
514         Oid                     dbid;
515         int64           result;
516
517         dbid = PG_GETARG_OID(0);
518
519         if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
520                 result = 0;
521         else
522                 result = (int64) (dbentry->n_xact_commit);
523
524         PG_RETURN_INT64(result);
525 }
526
527
528 Datum
529 pg_stat_get_db_xact_rollback(PG_FUNCTION_ARGS)
530 {
531         PgStat_StatDBEntry *dbentry;
532         Oid                     dbid;
533         int64           result;
534
535         dbid = PG_GETARG_OID(0);
536
537         if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
538                 result = 0;
539         else
540                 result = (int64) (dbentry->n_xact_rollback);
541
542         PG_RETURN_INT64(result);
543 }
544
545
546 Datum
547 pg_stat_get_db_blocks_fetched(PG_FUNCTION_ARGS)
548 {
549         PgStat_StatDBEntry *dbentry;
550         Oid                     dbid;
551         int64           result;
552
553         dbid = PG_GETARG_OID(0);
554
555         if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
556                 result = 0;
557         else
558                 result = (int64) (dbentry->n_blocks_fetched);
559
560         PG_RETURN_INT64(result);
561 }
562
563
564 Datum
565 pg_stat_get_db_blocks_hit(PG_FUNCTION_ARGS)
566 {
567         PgStat_StatDBEntry *dbentry;
568         Oid                     dbid;
569         int64           result;
570
571         dbid = PG_GETARG_OID(0);
572
573         if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
574                 result = 0;
575         else
576                 result = (int64) (dbentry->n_blocks_hit);
577
578         PG_RETURN_INT64(result);
579 }