Tom Lane wrote:
I was thinking of proposing that we provide something just about like
that as a standard function (written in C, not in plpgsql, so that it
would be available whether or not you'd installed plpgsql).  There are
some places in the information_schema that desperately need it ---
right now, the value of FUNC_MAX_ARGS is effectively hard-wired into
some of the information_schema views, which means they are broken if
one changes that #define.  We could fix this if we had a function like
the above and exported FUNC_MAX_ARGS as a read-only GUC variable.


First installment. The attached exports FUNC_MAX_ARGS as a read-only GUC variable -- func_max_args. Comments?


While I was in guc.c, I also added short_desc to the definition of the pg_settings view. I wasn't sure if I ought to add the long_desc too, and if so, should it be it's own column in the view, or be concatenated with short_desc -- any thoughts on that?

Current output looks like this:

regression=# \x
Expanded display is on.
regression=# select * from pg_settings where name = 'func_max_args';
-[ RECORD 1 ]-----------------------------------------------------------
name       | func_max_args
setting    | 32
short_desc | Shows the compiled-in maximum number of function arguments.
context    | internal
vartype    | integer
source     | default
min_val    | 32
max_val    | 32

This will require a catalog version bump when I apply it (not done in the attached patch).

Joe

Index: src/backend/catalog/system_views.sql
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/catalog/system_views.sql,v
retrieving revision 1.3
diff -c -r1.3 system_views.sql
*** src/backend/catalog/system_views.sql        29 Nov 2003 22:39:40 -0000      1.3
--- src/backend/catalog/system_views.sql        30 Nov 2003 04:58:51 -0000
***************
*** 260,266 ****
  CREATE VIEW pg_settings AS 
      SELECT * 
      FROM pg_show_all_settings() AS A 
!     (name text, setting text, context text, vartype text, 
       source text, min_val text, max_val text);
  
  CREATE RULE pg_settings_u AS 
--- 260,266 ----
  CREATE VIEW pg_settings AS 
      SELECT * 
      FROM pg_show_all_settings() AS A 
!     (name text, setting text, short_desc text, context text, vartype text, 
       source text, min_val text, max_val text);
  
  CREATE RULE pg_settings_u AS 
Index: src/backend/utils/misc/guc.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/utils/misc/guc.c,v
retrieving revision 1.172
diff -c -r1.172 guc.c
*** src/backend/utils/misc/guc.c        29 Nov 2003 19:52:03 -0000      1.172
--- src/backend/utils/misc/guc.c        30 Nov 2003 04:58:52 -0000
***************
*** 156,161 ****
--- 156,162 ----
  static char *session_authorization_string;
  static char *timezone_string;
  static char *XactIsoLevel_string;
+ static int    func_max_args;
  
  
  /* Macros for freeing malloc'd pointers only if appropriate to do so */
***************
*** 862,867 ****
--- 863,878 ----
                8, 1, INT_MAX, NULL, NULL
        },
        {
+               /* Can't be set in postgresql.conf */
+               {"func_max_args", PGC_INTERNAL, UNGROUPED,
+                       gettext_noop("Shows the compiled-in maximum number of function 
"
+                                                "arguments."),
+                       NULL
+               },
+               &func_max_args,
+               FUNC_MAX_ARGS, FUNC_MAX_ARGS, FUNC_MAX_ARGS, NULL, NULL
+       },
+       {
                {"join_collapse_limit", PGC_USERSET, QUERY_TUNING_OTHER,
                        gettext_noop("Sets the FROM-list size beyond which JOIN 
constructs are not "
                                                 "flattened."),
***************
*** 3468,3481 ****
        /* setting : use _ShowOption in order to avoid duplicating the logic */
        values[1] = _ShowOption(conf);
  
        /* context */
!       values[2] = GucContext_Names[conf->context];
  
        /* vartype */
!       values[3] = config_type_names[conf->vartype];
  
        /* source */
!       values[4] = GucSource_Names[conf->source];
  
        /* now get the type specifc attributes */
        switch (conf->vartype)
--- 3479,3495 ----
        /* setting : use _ShowOption in order to avoid duplicating the logic */
        values[1] = _ShowOption(conf);
  
+       /* short_desc */
+       values[2] = conf->short_desc;
+ 
        /* context */
!       values[3] = GucContext_Names[conf->context];
  
        /* vartype */
!       values[4] = config_type_names[conf->vartype];
  
        /* source */
!       values[5] = GucSource_Names[conf->source];
  
        /* now get the type specifc attributes */
        switch (conf->vartype)
***************
*** 3483,3492 ****
                case PGC_BOOL:
                        {
                                /* min_val */
!                               values[5] = NULL;
  
                                /* max_val */
!                               values[6] = NULL;
                        }
                        break;
  
--- 3497,3506 ----
                case PGC_BOOL:
                        {
                                /* min_val */
!                               values[6] = NULL;
  
                                /* max_val */
!                               values[7] = NULL;
                        }
                        break;
  
***************
*** 3496,3506 ****
  
                                /* min_val */
                                snprintf(buffer, sizeof(buffer), "%d", lconf->min);
!                               values[5] = pstrdup(buffer);
  
                                /* max_val */
                                snprintf(buffer, sizeof(buffer), "%d", lconf->max);
!                               values[6] = pstrdup(buffer);
                        }
                        break;
  
--- 3510,3520 ----
  
                                /* min_val */
                                snprintf(buffer, sizeof(buffer), "%d", lconf->min);
!                               values[6] = pstrdup(buffer);
  
                                /* max_val */
                                snprintf(buffer, sizeof(buffer), "%d", lconf->max);
!                               values[7] = pstrdup(buffer);
                        }
                        break;
  
***************
*** 3510,3530 ****
  
                                /* min_val */
                                snprintf(buffer, sizeof(buffer), "%g", lconf->min);
!                               values[5] = pstrdup(buffer);
  
                                /* max_val */
                                snprintf(buffer, sizeof(buffer), "%g", lconf->max);
!                               values[6] = pstrdup(buffer);
                        }
                        break;
  
                case PGC_STRING:
                        {
                                /* min_val */
!                               values[5] = NULL;
  
                                /* max_val */
!                               values[6] = NULL;
                        }
                        break;
  
--- 3524,3544 ----
  
                                /* min_val */
                                snprintf(buffer, sizeof(buffer), "%g", lconf->min);
!                               values[6] = pstrdup(buffer);
  
                                /* max_val */
                                snprintf(buffer, sizeof(buffer), "%g", lconf->max);
!                               values[7] = pstrdup(buffer);
                        }
                        break;
  
                case PGC_STRING:
                        {
                                /* min_val */
!                               values[6] = NULL;
  
                                /* max_val */
!                               values[7] = NULL;
                        }
                        break;
  
***************
*** 3536,3545 ****
                                 */
  
                                /* min_val */
!                               values[5] = NULL;
  
                                /* max_val */
!                               values[6] = NULL;
                        }
                        break;
        }
--- 3550,3559 ----
                                 */
  
                                /* min_val */
!                               values[6] = NULL;
  
                                /* max_val */
!                               values[7] = NULL;
                        }
                        break;
        }
***************
*** 3582,3588 ****
   * show_all_settings - equiv to SHOW ALL command but implemented as
   * a Table Function.
   */
! #define NUM_PG_SETTINGS_ATTS  7
  
  Datum
  show_all_settings(PG_FUNCTION_ARGS)
--- 3596,3602 ----
   * show_all_settings - equiv to SHOW ALL command but implemented as
   * a Table Function.
   */
! #define NUM_PG_SETTINGS_ATTS  8
  
  Datum
  show_all_settings(PG_FUNCTION_ARGS)
***************
*** 3616,3630 ****
                                                   TEXTOID, -1, 0, false);
                TupleDescInitEntry(tupdesc, (AttrNumber) 2, "setting",
                                                   TEXTOID, -1, 0, false);
!               TupleDescInitEntry(tupdesc, (AttrNumber) 3, "context",
                                                   TEXTOID, -1, 0, false);
!               TupleDescInitEntry(tupdesc, (AttrNumber) 4, "vartype",
                                                   TEXTOID, -1, 0, false);
!               TupleDescInitEntry(tupdesc, (AttrNumber) 5, "source",
                                                   TEXTOID, -1, 0, false);
!               TupleDescInitEntry(tupdesc, (AttrNumber) 6, "min_val",
                                                   TEXTOID, -1, 0, false);
!               TupleDescInitEntry(tupdesc, (AttrNumber) 7, "max_val",
                                                   TEXTOID, -1, 0, false);
  
                /* allocate a slot for a tuple with this tupdesc */
--- 3630,3646 ----
                                                   TEXTOID, -1, 0, false);
                TupleDescInitEntry(tupdesc, (AttrNumber) 2, "setting",
                                                   TEXTOID, -1, 0, false);
!               TupleDescInitEntry(tupdesc, (AttrNumber) 3, "short_desc",
!                                                  TEXTOID, -1, 0, false);
!               TupleDescInitEntry(tupdesc, (AttrNumber) 4, "context",
                                                   TEXTOID, -1, 0, false);
!               TupleDescInitEntry(tupdesc, (AttrNumber) 5, "vartype",
                                                   TEXTOID, -1, 0, false);
!               TupleDescInitEntry(tupdesc, (AttrNumber) 6, "source",
                                                   TEXTOID, -1, 0, false);
!               TupleDescInitEntry(tupdesc, (AttrNumber) 7, "min_val",
                                                   TEXTOID, -1, 0, false);
!               TupleDescInitEntry(tupdesc, (AttrNumber) 8, "max_val",
                                                   TEXTOID, -1, 0, false);
  
                /* allocate a slot for a tuple with this tupdesc */
Index: src/test/regress/expected/rules.out
===================================================================
RCS file: /cvsroot/pgsql-server/src/test/regress/expected/rules.out,v
retrieving revision 1.82
diff -c -r1.82 rules.out
*** src/test/regress/expected/rules.out 21 Nov 2003 22:32:49 -0000      1.82
--- src/test/regress/expected/rules.out 30 Nov 2003 04:58:53 -0000
***************
*** 1278,1284 ****
   pg_indexes               | SELECT n.nspname AS schemaname, c.relname AS tablename, 
i.relname AS indexname, pg_get_indexdef(i.oid) AS indexdef FROM (((pg_index x JOIN 
pg_class c 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") AND (i.relkind = 'i'::"char"));
   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, a.context, a.vartype, 
a.source, a.min_val, a.max_val FROM pg_show_all_settings() a(name text, setting text, 
context text, vartype text, source text, min_val text, max_val 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, 
pg_stat_get_backend_activity_start(s.backendid) AS query_start 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;
--- 1278,1284 ----
   pg_indexes               | SELECT n.nspname AS schemaname, c.relname AS tablename, 
i.relname AS indexname, pg_get_indexdef(i.oid) AS indexdef FROM (((pg_index x JOIN 
pg_class c 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") AND (i.relkind = 'i'::"char"));
   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, a.short_desc, a.context, 
a.vartype, a.source, a.min_val, a.max_val FROM pg_show_all_settings() a(name text, 
setting text, short_desc text, context text, vartype text, source text, min_val text, 
max_val 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, 
pg_stat_get_backend_activity_start(s.backendid) AS query_start 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;
---------------------------(end of broadcast)---------------------------
TIP 7: don't forget to increase your free space map settings

Reply via email to