Replace pg_class.reltriggers with relhastriggers, which is just a boolean hint

("there might be triggers") rather than an exact count.  This is necessary
catalog infrastructure for the upcoming patch to reduce the strength of
locking needed for trigger addition/removal.  Split out and committed
separately for ease of reviewing/testing.

In passing, also get rid of the unused pg_class columns relukeys, relfkeys,
and relrefs, which haven't been maintained in many years and now have no
chance of ever being maintained (because of wishing to avoid locking).

Simon Riggs
This commit is contained in:
Tom Lane 2008-11-09 21:24:33 +00:00
parent 1d577f5e49
commit e4718f2c9e
13 changed files with 162 additions and 197 deletions

View File

@ -1,4 +1,4 @@
<!-- $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.180 2008/10/31 08:39:19 heikki Exp $ -->
<!-- $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.181 2008/11/09 21:24:32 tgl Exp $ -->
<!--
Documentation of the system catalogs, directed toward PostgreSQL developers
-->
@ -1711,37 +1711,6 @@
</entry>
</row>
<row>
<entry><structfield>reltriggers</structfield></entry>
<entry><type>int2</type></entry>
<entry></entry>
<entry>
Number of triggers on the table; see
<link linkend="catalog-pg-trigger"><structname>pg_trigger</structname></link> catalog
</entry>
</row>
<row>
<entry><structfield>relukeys</structfield></entry>
<entry><type>int2</type></entry>
<entry></entry>
<entry>Unused (<emphasis>not</emphasis> the number of unique keys)</entry>
</row>
<row>
<entry><structfield>relfkeys</structfield></entry>
<entry><type>int2</type></entry>
<entry></entry>
<entry>Unused (<emphasis>not</emphasis> the number of foreign keys on the table)</entry>
</row>
<row>
<entry><structfield>relrefs</structfield></entry>
<entry><type>int2</type></entry>
<entry></entry>
<entry>Unused</entry>
</row>
<row>
<entry><structfield>relhasoids</structfield></entry>
<entry><type>bool</type></entry>
@ -1765,11 +1734,21 @@
<entry><type>bool</type></entry>
<entry></entry>
<entry>
True if table has rules; see
True if table has (or once had) rules; see
<link linkend="catalog-pg-rewrite"><structname>pg_rewrite</structname></link> catalog
</entry>
</row>
<row>
<entry><structfield>relhastriggers</structfield></entry>
<entry><type>bool</type></entry>
<entry></entry>
<entry>
True if table has (or once had) triggers; see
<link linkend="catalog-pg-trigger"><structname>pg_trigger</structname></link> catalog
</entry>
</row>
<row>
<entry><structfield>relhassubclass</structfield></entry>
<entry><type>bool</type></entry>
@ -4499,13 +4478,6 @@
</para>
</note>
<note>
<para>
<literal>pg_class.reltriggers</literal> needs to agree with the
number of triggers found in this table for each relation.
</para>
</note>
</sect1>
@ -6818,13 +6790,13 @@
<entry><structfield>hasrules</structfield></entry>
<entry><type>boolean</type></entry>
<entry><literal><link linkend="catalog-pg-class"><structname>pg_class</structname></link>.relhasrules</literal></entry>
<entry>true if table has rules</entry>
<entry>true if table has (or once had) rules</entry>
</row>
<row>
<entry><structfield>hastriggers</structfield></entry>
<entry><type>boolean</type></entry>
<entry><literal><link linkend="catalog-pg-class"><structname>pg_class</structname></link>.reltriggers</literal></entry>
<entry>true if table has triggers</entry>
<entry><literal><link linkend="catalog-pg-class"><structname>pg_class</structname></link>.relhastriggers</literal></entry>
<entry>true if table has (or once had) triggers</entry>
</row>
</tbody>
</tgroup>

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.342 2008/11/02 01:45:27 tgl Exp $
* $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.343 2008/11/09 21:24:32 tgl Exp $
*
*
* INTERFACE ROUTINES
@ -641,13 +641,10 @@ InsertPgClassTuple(Relation pg_class_desc,
values[Anum_pg_class_relkind - 1] = CharGetDatum(rd_rel->relkind);
values[Anum_pg_class_relnatts - 1] = Int16GetDatum(rd_rel->relnatts);
values[Anum_pg_class_relchecks - 1] = Int16GetDatum(rd_rel->relchecks);
values[Anum_pg_class_reltriggers - 1] = Int16GetDatum(rd_rel->reltriggers);
values[Anum_pg_class_relukeys - 1] = Int16GetDatum(rd_rel->relukeys);
values[Anum_pg_class_relfkeys - 1] = Int16GetDatum(rd_rel->relfkeys);
values[Anum_pg_class_relrefs - 1] = Int16GetDatum(rd_rel->relrefs);
values[Anum_pg_class_relhasoids - 1] = BoolGetDatum(rd_rel->relhasoids);
values[Anum_pg_class_relhaspkey - 1] = BoolGetDatum(rd_rel->relhaspkey);
values[Anum_pg_class_relhasrules - 1] = BoolGetDatum(rd_rel->relhasrules);
values[Anum_pg_class_relhastriggers - 1] = BoolGetDatum(rd_rel->relhastriggers);
values[Anum_pg_class_relhassubclass - 1] = BoolGetDatum(rd_rel->relhassubclass);
values[Anum_pg_class_relfrozenxid - 1] = TransactionIdGetDatum(rd_rel->relfrozenxid);
/* start out with empty permissions */
@ -2366,7 +2363,7 @@ heap_truncate_check_FKs(List *relations, bool tempTables)
{
Relation rel = lfirst(cell);
if (rel->rd_rel->reltriggers != 0)
if (rel->rd_rel->relhastriggers)
oids = lappend_oid(oids, RelationGetRelid(rel));
}

View File

@ -3,7 +3,7 @@
*
* Copyright (c) 1996-2008, PostgreSQL Global Development Group
*
* $PostgreSQL: pgsql/src/backend/catalog/system_views.sql,v 1.55 2008/09/21 19:38:56 tgl Exp $
* $PostgreSQL: pgsql/src/backend/catalog/system_views.sql,v 1.56 2008/11/09 21:24:32 tgl Exp $
*/
CREATE VIEW pg_roles AS
@ -84,7 +84,7 @@ CREATE VIEW pg_tables AS
T.spcname AS tablespace,
C.relhasindex AS hasindexes,
C.relhasrules AS hasrules,
(C.reltriggers > 0) AS hastriggers
C.relhastriggers AS hastriggers
FROM pg_class C LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
LEFT JOIN pg_tablespace T ON (T.oid = C.reltablespace)
WHERE C.relkind = 'r';

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.239 2008/11/02 01:45:28 tgl Exp $
* $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.240 2008/11/09 21:24:32 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -95,7 +95,6 @@ CreateTrigger(CreateTrigStmt *stmt, Oid constraintOid)
Oid funcoid;
Oid funcrettype;
Oid trigoid;
int found = 0;
int i;
char constrtrigname[NAMEDATALEN];
char *trigname;
@ -280,10 +279,9 @@ CreateTrigger(CreateTrigStmt *stmt, Oid constraintOid)
}
/*
* Scan pg_trigger for existing triggers on relation. We do this mainly
* because we must count them; a secondary benefit is to give a nice error
* message if there's already a trigger of the same name. (The unique
* index on tgrelid/tgname would complain anyway.)
* Scan pg_trigger for existing triggers on relation. We do this only
* to give a nice error message if there's already a trigger of the same
* name. (The unique index on tgrelid/tgname would complain anyway.)
*
* NOTE that this is cool only because we have AccessExclusiveLock on the
* relation, so the trigger set won't be changing underneath us.
@ -303,7 +301,6 @@ CreateTrigger(CreateTrigStmt *stmt, Oid constraintOid)
(errcode(ERRCODE_DUPLICATE_OBJECT),
errmsg("trigger \"%s\" for relation \"%s\" already exists",
trigname, stmt->relation->relname)));
found++;
}
systable_endscan(tgscan);
@ -405,7 +402,7 @@ CreateTrigger(CreateTrigStmt *stmt, Oid constraintOid)
elog(ERROR, "cache lookup failed for relation %u",
RelationGetRelid(rel));
((Form_pg_class) GETSTRUCT(tuple))->reltriggers = found + 1;
((Form_pg_class) GETSTRUCT(tuple))->relhastriggers = true;
simple_heap_update(pgrel, &tuple->t_self, tuple);
@ -818,9 +815,6 @@ RemoveTriggerById(Oid trigOid)
HeapTuple tup;
Oid relid;
Relation rel;
Relation pgrel;
HeapTuple tuple;
Form_pg_class classForm;
tgrel = heap_open(TriggerRelationId, RowExclusiveLock);
@ -867,33 +861,15 @@ RemoveTriggerById(Oid trigOid)
heap_close(tgrel, RowExclusiveLock);
/*
* Update relation's pg_class entry. Crucial side-effect: other backends
* (and this one too!) are sent SI message to make them rebuild relcache
* entries.
*
* Note this is OK only because we have AccessExclusiveLock on the rel, so
* no one else is creating/deleting triggers on this rel at the same time.
* We do not bother to try to determine whether any other triggers remain,
* which would be needed in order to decide whether it's safe to clear
* the relation's relhastriggers. (In any case, there might be a
* concurrent process adding new triggers.) Instead, just force a
* relcache inval to make other backends (and this one too!) rebuild
* their relcache entries. There's no great harm in leaving relhastriggers
* true even if there are no triggers left.
*/
pgrel = heap_open(RelationRelationId, RowExclusiveLock);
tuple = SearchSysCacheCopy(RELOID,
ObjectIdGetDatum(relid),
0, 0, 0);
if (!HeapTupleIsValid(tuple))
elog(ERROR, "cache lookup failed for relation %u", relid);
classForm = (Form_pg_class) GETSTRUCT(tuple);
if (classForm->reltriggers == 0) /* should not happen */
elog(ERROR, "relation \"%s\" has reltriggers = 0",
RelationGetRelationName(rel));
classForm->reltriggers--;
simple_heap_update(pgrel, &tuple->t_self, tuple);
CatalogUpdateIndexes(pgrel, tuple);
heap_freetuple(tuple);
heap_close(pgrel, RowExclusiveLock);
CacheInvalidateRelcache(rel);
/* Keep lock on trigger's rel until end of xact */
heap_close(rel, NoLock);
@ -1134,18 +1110,23 @@ void
RelationBuildTriggers(Relation relation)
{
TriggerDesc *trigdesc;
int ntrigs = relation->rd_rel->reltriggers;
int numtrigs;
int maxtrigs;
Trigger *triggers;
int found = 0;
Relation tgrel;
ScanKeyData skey;
SysScanDesc tgscan;
HeapTuple htup;
MemoryContext oldContext;
int i;
Assert(ntrigs > 0); /* else I should not have been called */
triggers = (Trigger *) palloc(ntrigs * sizeof(Trigger));
/*
* Allocate a working array to hold the triggers (the array is extended
* if necessary)
*/
maxtrigs = 16;
triggers = (Trigger *) palloc(maxtrigs * sizeof(Trigger));
numtrigs = 0;
/*
* Note: since we scan the triggers using TriggerRelidNameIndexId, we will
@ -1167,10 +1148,12 @@ RelationBuildTriggers(Relation relation)
Form_pg_trigger pg_trigger = (Form_pg_trigger) GETSTRUCT(htup);
Trigger *build;
if (found >= ntrigs)
elog(ERROR, "too many trigger records found for relation \"%s\"",
RelationGetRelationName(relation));
build = &(triggers[found]);
if (numtrigs >= maxtrigs)
{
maxtrigs *= 2;
triggers = (Trigger *) repalloc(triggers, maxtrigs * sizeof(Trigger));
}
build = &(triggers[numtrigs]);
build->tgoid = HeapTupleGetOid(htup);
build->tgname = DatumGetCString(DirectFunctionCall1(nameout,
@ -1199,7 +1182,6 @@ RelationBuildTriggers(Relation relation)
bytea *val;
bool isnull;
char *p;
int i;
val = DatumGetByteaP(fastgetattr(htup,
Anum_pg_trigger_tgargs,
@ -1218,23 +1200,25 @@ RelationBuildTriggers(Relation relation)
else
build->tgargs = NULL;
found++;
numtrigs++;
}
systable_endscan(tgscan);
heap_close(tgrel, AccessShareLock);
if (found != ntrigs)
elog(ERROR, "%d trigger record(s) not found for relation \"%s\"",
ntrigs - found,
RelationGetRelationName(relation));
/* There might not be any triggers */
if (numtrigs == 0)
{
pfree(triggers);
return;
}
/* Build trigdesc */
trigdesc = (TriggerDesc *) palloc0(sizeof(TriggerDesc));
trigdesc->triggers = triggers;
trigdesc->numtriggers = ntrigs;
for (found = 0; found < ntrigs; found++)
InsertTrigger(trigdesc, &(triggers[found]), found);
trigdesc->numtriggers = numtrigs;
for (i = 0; i < numtrigs; i++)
InsertTrigger(trigdesc, &(triggers[i]), i);
/* Copy completed trigdesc into cache storage */
oldContext = MemoryContextSwitchTo(CacheMemoryContext);

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/rewrite/rewriteDefine.c,v 1.131 2008/11/02 01:45:28 tgl Exp $
* $PostgreSQL: pgsql/src/backend/rewrite/rewriteDefine.c,v 1.132 2008/11/09 21:24:32 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -371,7 +371,11 @@ DefineQueryRewrite(char *rulename,
*
* If so, check that the relation is empty because the storage for the
* relation is going to be deleted. Also insist that the rel not have
* any triggers, indexes, or child tables.
* any triggers, indexes, or child tables. (Note: these tests are
* too strict, because they will reject relations that once had such
* but don't anymore. But we don't really care, because this whole
* business of converting relations to views is just a kluge to allow
* loading ancient pg_dump files.)
*/
if (event_relation->rd_rel->relkind != RELKIND_VIEW)
{
@ -385,7 +389,7 @@ DefineQueryRewrite(char *rulename,
RelationGetRelationName(event_relation))));
heap_endscan(scanDesc);
if (event_relation->rd_rel->reltriggers != 0)
if (event_relation->rd_rel->relhastriggers)
ereport(ERROR,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("could not convert table \"%s\" to a view because it has triggers",

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.274 2008/09/30 10:52:13 heikki Exp $
* $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.275 2008/11/09 21:24:32 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -856,7 +856,7 @@ RelationBuildDesc(Oid targetRelId, Relation oldrelation)
relation->rd_rulescxt = NULL;
}
if (relation->rd_rel->reltriggers > 0)
if (relation->rd_rel->relhastriggers)
RelationBuildTriggers(relation);
else
relation->trigdesc = NULL;
@ -2641,7 +2641,7 @@ RelationCacheInitializePhase2(void)
*/
if (relation->rd_rel->relhasrules && relation->rd_rules == NULL)
RelationBuildRuleLock(relation);
if (relation->rd_rel->reltriggers > 0 && relation->trigdesc == NULL)
if (relation->rd_rel->relhastriggers && relation->trigdesc == NULL)
RelationBuildTriggers(relation);
}

View File

@ -12,7 +12,7 @@
* by PostgreSQL
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.504 2008/11/09 00:28:35 tgl Exp $
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.505 2008/11/09 21:24:32 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -3070,7 +3070,7 @@ getTables(int *numTables)
int i_relacl;
int i_rolname;
int i_relchecks;
int i_reltriggers;
int i_relhastriggers;
int i_relhasindex;
int i_relhasrules;
int i_relhasoids;
@ -3102,7 +3102,7 @@ getTables(int *numTables)
* we cannot correctly identify inherited columns, owned sequences, etc.
*/
if (g_fout->remoteVersion >= 80200)
if (g_fout->remoteVersion >= 80400)
{
/*
* Left join to pick up dependency info linking sequences to their
@ -3112,7 +3112,36 @@ getTables(int *numTables)
"SELECT c.tableoid, c.oid, relname, "
"relacl, relkind, relnamespace, "
"(%s relowner) as rolname, "
"relchecks, reltriggers, "
"relchecks, relhastriggers, "
"relhasindex, relhasrules, relhasoids, "
"d.refobjid as owning_tab, "
"d.refobjsubid as owning_col, "
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
"array_to_string(c.reloptions, ', ') as reloptions "
"from pg_class c "
"left join pg_depend d on "
"(c.relkind = '%c' and "
"d.classid = c.tableoid and d.objid = c.oid and "
"d.objsubid = 0 and "
"d.refclassid = c.tableoid and d.deptype = 'a') "
"where relkind in ('%c', '%c', '%c', '%c') "
"order by c.oid",
username_subquery,
RELKIND_SEQUENCE,
RELKIND_RELATION, RELKIND_SEQUENCE,
RELKIND_VIEW, RELKIND_COMPOSITE_TYPE);
}
else if (g_fout->remoteVersion >= 80200)
{
/*
* Left join to pick up dependency info linking sequences to their
* owning column, if any (note this dependency is AUTO as of 8.2)
*/
appendPQExpBuffer(query,
"SELECT c.tableoid, c.oid, relname, "
"relacl, relkind, relnamespace, "
"(%s relowner) as rolname, "
"relchecks, (reltriggers <> 0) as relhastriggers, "
"relhasindex, relhasrules, relhasoids, "
"d.refobjid as owning_tab, "
"d.refobjsubid as owning_col, "
@ -3141,7 +3170,7 @@ getTables(int *numTables)
"SELECT c.tableoid, c.oid, relname, "
"relacl, relkind, relnamespace, "
"(%s relowner) as rolname, "
"relchecks, reltriggers, "
"relchecks, (reltriggers <> 0) as relhastriggers, "
"relhasindex, relhasrules, relhasoids, "
"d.refobjid as owning_tab, "
"d.refobjsubid as owning_col, "
@ -3170,7 +3199,7 @@ getTables(int *numTables)
"SELECT c.tableoid, c.oid, relname, "
"relacl, relkind, relnamespace, "
"(%s relowner) as rolname, "
"relchecks, reltriggers, "
"relchecks, (reltriggers <> 0) as relhastriggers, "
"relhasindex, relhasrules, relhasoids, "
"d.refobjid as owning_tab, "
"d.refobjsubid as owning_col, "
@ -3195,7 +3224,7 @@ getTables(int *numTables)
"SELECT tableoid, oid, relname, relacl, relkind, "
"0::oid as relnamespace, "
"(%s relowner) as rolname, "
"relchecks, reltriggers, "
"relchecks, (reltriggers <> 0) as relhastriggers, "
"relhasindex, relhasrules, relhasoids, "
"NULL::oid as owning_tab, "
"NULL::int4 as owning_col, "
@ -3214,7 +3243,7 @@ getTables(int *numTables)
"SELECT tableoid, oid, relname, relacl, relkind, "
"0::oid as relnamespace, "
"(%s relowner) as rolname, "
"relchecks, reltriggers, "
"relchecks, (reltriggers <> 0) as relhastriggers, "
"relhasindex, relhasrules, "
"'t'::bool as relhasoids, "
"NULL::oid as owning_tab, "
@ -3244,7 +3273,7 @@ getTables(int *numTables)
"ELSE relkind END AS relkind,"
"0::oid as relnamespace, "
"(%s relowner) as rolname, "
"relchecks, reltriggers, "
"relchecks, (reltriggers <> 0) as relhastriggers, "
"relhasindex, relhasrules, "
"'t'::bool as relhasoids, "
"NULL::oid as owning_tab, "
@ -3285,7 +3314,7 @@ getTables(int *numTables)
i_relkind = PQfnumber(res, "relkind");
i_rolname = PQfnumber(res, "rolname");
i_relchecks = PQfnumber(res, "relchecks");
i_reltriggers = PQfnumber(res, "reltriggers");
i_relhastriggers = PQfnumber(res, "relhastriggers");
i_relhasindex = PQfnumber(res, "relhasindex");
i_relhasrules = PQfnumber(res, "relhasrules");
i_relhasoids = PQfnumber(res, "relhasoids");
@ -3323,9 +3352,9 @@ getTables(int *numTables)
tblinfo[i].relkind = *(PQgetvalue(res, i, i_relkind));
tblinfo[i].hasindex = (strcmp(PQgetvalue(res, i, i_relhasindex), "t") == 0);
tblinfo[i].hasrules = (strcmp(PQgetvalue(res, i, i_relhasrules), "t") == 0);
tblinfo[i].hastriggers = (strcmp(PQgetvalue(res, i, i_relhastriggers), "t") == 0);
tblinfo[i].hasoids = (strcmp(PQgetvalue(res, i, i_relhasoids), "t") == 0);
tblinfo[i].ncheck = atoi(PQgetvalue(res, i, i_relchecks));
tblinfo[i].ntrig = atoi(PQgetvalue(res, i, i_reltriggers));
if (PQgetisnull(res, i, i_owning_tab))
{
tblinfo[i].owning_tab = InvalidOid;
@ -3779,7 +3808,7 @@ getConstraints(TableInfo tblinfo[], int numTables)
{
TableInfo *tbinfo = &tblinfo[i];
if (tbinfo->ntrig == 0 || !tbinfo->dobj.dump)
if (!tbinfo->hastriggers || !tbinfo->dobj.dump)
continue;
if (g_verbose)
@ -4090,7 +4119,7 @@ getTriggers(TableInfo tblinfo[], int numTables)
{
TableInfo *tbinfo = &tblinfo[i];
if (tbinfo->ntrig == 0 || !tbinfo->dobj.dump)
if (!tbinfo->hastriggers || !tbinfo->dobj.dump)
continue;
if (g_verbose)
@ -4177,16 +4206,6 @@ getTriggers(TableInfo tblinfo[], int numTables)
ntups = PQntuples(res);
/*
* We may have less triggers than recorded due to having ignored
* foreign-key triggers
*/
if (ntups > tbinfo->ntrig)
{
write_msg(NULL, "expected %d triggers on table \"%s\" but found %d\n",
tbinfo->ntrig, tbinfo->dobj.name, ntups);
exit_nicely();
}
i_tableoid = PQfnumber(res, "tableoid");
i_oid = PQfnumber(res, "oid");
i_tgname = PQfnumber(res, "tgname");

View File

@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.h,v 1.142 2008/10/31 08:39:21 heikki Exp $
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.h,v 1.143 2008/11/09 21:24:33 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -240,9 +240,9 @@ typedef struct _tableInfo
char *reloptions; /* options specified by WITH (...) */
bool hasindex; /* does it have any indexes? */
bool hasrules; /* does it have any rules? */
bool hastriggers; /* does it have any triggers? */
bool hasoids; /* does it have OIDs? */
int ncheck; /* # of CHECK expressions */
int ntrig; /* # of triggers */
/* these two are set only if table is a sequence owned by a column: */
Oid owning_tab; /* OID of table owning sequence */
int owning_col; /* attr # of column owning sequence */

View File

@ -8,7 +8,7 @@
*
* Copyright (c) 2000-2008, PostgreSQL Global Development Group
*
* $PostgreSQL: pgsql/src/bin/psql/describe.c,v 1.187 2008/11/06 15:18:35 tgl Exp $
* $PostgreSQL: pgsql/src/bin/psql/describe.c,v 1.188 2008/11/09 21:24:33 tgl Exp $
*/
#include "postgres_fe.h"
@ -840,10 +840,10 @@ describeOneTableDetails(const char *schemaname,
struct
{
int16 checks;
int16 triggers;
char relkind;
bool hasindex;
bool hasrules;
bool hastriggers;
bool hasoids;
Oid tablespace;
} tableinfo;
@ -861,9 +861,10 @@ describeOneTableDetails(const char *schemaname,
/* Get general table info */
printfPQExpBuffer(&buf,
"SELECT relhasindex, relkind, relchecks, reltriggers, relhasrules, "
"SELECT relchecks, relkind, relhasindex, relhasrules, %s, "
"relhasoids%s\n"
"FROM pg_catalog.pg_class WHERE oid = '%s'",
(pset.sversion >= 80400 ? "relhastriggers" : "reltriggers <> 0"),
(pset.sversion >= 80000 ? ", reltablespace" : ""),
oid);
res = PSQLexec(buf.data, false);
@ -879,11 +880,11 @@ describeOneTableDetails(const char *schemaname,
goto error_return;
}
tableinfo.checks = atoi(PQgetvalue(res, 0, 2));
tableinfo.triggers = atoi(PQgetvalue(res, 0, 3));
tableinfo.checks = atoi(PQgetvalue(res, 0, 0));
tableinfo.relkind = *(PQgetvalue(res, 0, 1));
tableinfo.hasindex = strcmp(PQgetvalue(res, 0, 0), "t") == 0;
tableinfo.hasrules = strcmp(PQgetvalue(res, 0, 4), "t") == 0;
tableinfo.hasindex = strcmp(PQgetvalue(res, 0, 2), "t") == 0;
tableinfo.hasrules = strcmp(PQgetvalue(res, 0, 3), "t") == 0;
tableinfo.hastriggers = strcmp(PQgetvalue(res, 0, 4), "t") == 0;
tableinfo.hasoids = strcmp(PQgetvalue(res, 0, 5), "t") == 0;
tableinfo.tablespace = (pset.sversion >= 80000) ?
atooid(PQgetvalue(res, 0, 6)) : 0;
@ -1287,7 +1288,7 @@ describeOneTableDetails(const char *schemaname,
}
/* print foreign-key constraints (there are none if no triggers) */
if (tableinfo.triggers)
if (tableinfo.hastriggers)
{
printfPQExpBuffer(&buf,
"SELECT conname,\n"
@ -1318,7 +1319,7 @@ describeOneTableDetails(const char *schemaname,
}
/* print incoming foreign-key references (none if no triggers) */
if (tableinfo.triggers)
if (tableinfo.hastriggers)
{
printfPQExpBuffer(&buf,
"SELECT conname, conrelid::pg_catalog.regclass,\n"
@ -1446,7 +1447,7 @@ describeOneTableDetails(const char *schemaname,
}
/* print triggers (but ignore foreign-key triggers) */
if (tableinfo.triggers)
if (tableinfo.hastriggers)
{
printfPQExpBuffer(&buf,
"SELECT t.tgname, "

View File

@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.502 2008/11/04 14:49:11 petere Exp $
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.503 2008/11/09 21:24:33 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -53,6 +53,6 @@
*/
/* yyyymmddN */
#define CATALOG_VERSION_NO 200811041
#define CATALOG_VERSION_NO 200811091
#endif

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/catalog/pg_attribute.h,v 1.140 2008/07/30 17:05:05 tgl Exp $
* $PostgreSQL: pgsql/src/include/catalog/pg_attribute.h,v 1.141 2008/11/09 21:24:33 tgl Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
@ -409,17 +409,14 @@ DATA(insert ( 1249 tableoid 26 0 4 -7 0 -1 -1 t p i t f f t 0));
{ 1259, {"relkind"}, 18, -1, 1, 14, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
{ 1259, {"relnatts"}, 21, -1, 2, 15, 0, -1, -1, true, 'p', 's', true, false, false, true, 0 }, \
{ 1259, {"relchecks"}, 21, -1, 2, 16, 0, -1, -1, true, 'p', 's', true, false, false, true, 0 }, \
{ 1259, {"reltriggers"}, 21, -1, 2, 17, 0, -1, -1, true, 'p', 's', true, false, false, true, 0 }, \
{ 1259, {"relukeys"}, 21, -1, 2, 18, 0, -1, -1, true, 'p', 's', true, false, false, true, 0 }, \
{ 1259, {"relfkeys"}, 21, -1, 2, 19, 0, -1, -1, true, 'p', 's', true, false, false, true, 0 }, \
{ 1259, {"relrefs"}, 21, -1, 2, 20, 0, -1, -1, true, 'p', 's', true, false, false, true, 0 }, \
{ 1259, {"relhasoids"}, 16, -1, 1, 21, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
{ 1259, {"relhaspkey"}, 16, -1, 1, 22, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
{ 1259, {"relhasrules"}, 16, -1, 1, 23, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
{ 1259, {"relhassubclass"},16, -1, 1, 24, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
{ 1259, {"relfrozenxid"}, 28, -1, 4, 25, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
{ 1259, {"relacl"}, 1034, -1, -1, 26, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0 }, \
{ 1259, {"reloptions"}, 1009, -1, -1, 27, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0 }
{ 1259, {"relhasoids"}, 16, -1, 1, 17, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
{ 1259, {"relhaspkey"}, 16, -1, 1, 18, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
{ 1259, {"relhasrules"}, 16, -1, 1, 19, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
{ 1259, {"relhastriggers"},16, -1, 1, 20, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
{ 1259, {"relhassubclass"},16, -1, 1, 21, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
{ 1259, {"relfrozenxid"}, 28, -1, 4, 22, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
{ 1259, {"relacl"}, 1034, -1, -1, 23, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0 }, \
{ 1259, {"reloptions"}, 1009, -1, -1, 24, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0 }
DATA(insert ( 1259 relname 19 -1 NAMEDATALEN 1 0 -1 -1 f p c t f f t 0));
DATA(insert ( 1259 relnamespace 26 -1 4 2 0 -1 -1 t p i t f f t 0));
@ -437,17 +434,14 @@ DATA(insert ( 1259 relisshared 16 -1 1 13 0 -1 -1 t p c t f f t 0));
DATA(insert ( 1259 relkind 18 -1 1 14 0 -1 -1 t p c t f f t 0));
DATA(insert ( 1259 relnatts 21 -1 2 15 0 -1 -1 t p s t f f t 0));
DATA(insert ( 1259 relchecks 21 -1 2 16 0 -1 -1 t p s t f f t 0));
DATA(insert ( 1259 reltriggers 21 -1 2 17 0 -1 -1 t p s t f f t 0));
DATA(insert ( 1259 relukeys 21 -1 2 18 0 -1 -1 t p s t f f t 0));
DATA(insert ( 1259 relfkeys 21 -1 2 19 0 -1 -1 t p s t f f t 0));
DATA(insert ( 1259 relrefs 21 -1 2 20 0 -1 -1 t p s t f f t 0));
DATA(insert ( 1259 relhasoids 16 -1 1 21 0 -1 -1 t p c t f f t 0));
DATA(insert ( 1259 relhaspkey 16 -1 1 22 0 -1 -1 t p c t f f t 0));
DATA(insert ( 1259 relhasrules 16 -1 1 23 0 -1 -1 t p c t f f t 0));
DATA(insert ( 1259 relhassubclass 16 -1 1 24 0 -1 -1 t p c t f f t 0));
DATA(insert ( 1259 relfrozenxid 28 -1 4 25 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1259 relacl 1034 -1 -1 26 1 -1 -1 f x i f f f t 0));
DATA(insert ( 1259 reloptions 1009 -1 -1 27 1 -1 -1 f x i f f f t 0));
DATA(insert ( 1259 relhasoids 16 -1 1 17 0 -1 -1 t p c t f f t 0));
DATA(insert ( 1259 relhaspkey 16 -1 1 18 0 -1 -1 t p c t f f t 0));
DATA(insert ( 1259 relhasrules 16 -1 1 19 0 -1 -1 t p c t f f t 0));
DATA(insert ( 1259 relhastriggers 16 -1 1 20 0 -1 -1 t p c t f f t 0));
DATA(insert ( 1259 relhassubclass 16 -1 1 21 0 -1 -1 t p c t f f t 0));
DATA(insert ( 1259 relfrozenxid 28 -1 4 22 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1259 relacl 1034 -1 -1 23 1 -1 -1 f x i f f f t 0));
DATA(insert ( 1259 reloptions 1009 -1 -1 24 1 -1 -1 f x i f f f t 0));
DATA(insert ( 1259 ctid 27 0 6 -1 0 -1 -1 f p s t f f t 0));
DATA(insert ( 1259 oid 26 0 4 -2 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1259 xmin 28 0 4 -3 0 -1 -1 t p i t f f t 0));

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/catalog/pg_class.h,v 1.107 2008/07/30 17:05:05 tgl Exp $
* $PostgreSQL: pgsql/src/include/catalog/pg_class.h,v 1.108 2008/11/09 21:24:33 tgl Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
@ -52,14 +52,11 @@ CATALOG(pg_class,1259) BKI_BOOTSTRAP
* contain entries with negative attnums for system attributes.
*/
int2 relchecks; /* # of CHECK constraints for class */
int2 reltriggers; /* # of TRIGGERs */
int2 relukeys; /* # of Unique keys (not used) */
int2 relfkeys; /* # of FOREIGN KEYs (not used) */
int2 relrefs; /* # of references to this rel (not used) */
bool relhasoids; /* T if we generate OIDs for rows of rel */
bool relhaspkey; /* has PRIMARY KEY index */
bool relhasrules; /* has associated rules */
bool relhassubclass; /* has derived classes */
bool relhaspkey; /* has (or has had) PRIMARY KEY index */
bool relhasrules; /* has (or has had) any rules */
bool relhastriggers; /* has (or has had) any TRIGGERs */
bool relhassubclass; /* has (or has had) derived classes */
TransactionId relfrozenxid; /* all Xids < this are frozen in this rel */
/*
@ -88,7 +85,7 @@ typedef FormData_pg_class *Form_pg_class;
* ----------------
*/
#define Natts_pg_class 27
#define Natts_pg_class 24
#define Anum_pg_class_relname 1
#define Anum_pg_class_relnamespace 2
#define Anum_pg_class_reltype 3
@ -105,17 +102,14 @@ typedef FormData_pg_class *Form_pg_class;
#define Anum_pg_class_relkind 14
#define Anum_pg_class_relnatts 15
#define Anum_pg_class_relchecks 16
#define Anum_pg_class_reltriggers 17
#define Anum_pg_class_relukeys 18
#define Anum_pg_class_relfkeys 19
#define Anum_pg_class_relrefs 20
#define Anum_pg_class_relhasoids 21
#define Anum_pg_class_relhaspkey 22
#define Anum_pg_class_relhasrules 23
#define Anum_pg_class_relhassubclass 24
#define Anum_pg_class_relfrozenxid 25
#define Anum_pg_class_relacl 26
#define Anum_pg_class_reloptions 27
#define Anum_pg_class_relhasoids 17
#define Anum_pg_class_relhaspkey 18
#define Anum_pg_class_relhasrules 19
#define Anum_pg_class_relhastriggers 20
#define Anum_pg_class_relhassubclass 21
#define Anum_pg_class_relfrozenxid 22
#define Anum_pg_class_relacl 23
#define Anum_pg_class_reloptions 24
/* ----------------
* initial contents of pg_class
@ -127,13 +121,13 @@ typedef FormData_pg_class *Form_pg_class;
*/
/* Note: "3" in the relfrozenxid column stands for FirstNormalTransactionId */
DATA(insert OID = 1247 ( pg_type PGNSP 71 PGUID 0 1247 0 0 0 0 0 f f r 28 0 0 0 0 0 t f f f 3 _null_ _null_ ));
DATA(insert OID = 1247 ( pg_type PGNSP 71 PGUID 0 1247 0 0 0 0 0 f f r 28 0 t f f f f 3 _null_ _null_ ));
DESCR("");
DATA(insert OID = 1249 ( pg_attribute PGNSP 75 PGUID 0 1249 0 0 0 0 0 f f r 17 0 0 0 0 0 f f f f 3 _null_ _null_ ));
DATA(insert OID = 1249 ( pg_attribute PGNSP 75 PGUID 0 1249 0 0 0 0 0 f f r 17 0 f f f f f 3 _null_ _null_ ));
DESCR("");
DATA(insert OID = 1255 ( pg_proc PGNSP 81 PGUID 0 1255 0 0 0 0 0 f f r 22 0 0 0 0 0 t f f f 3 _null_ _null_ ));
DATA(insert OID = 1255 ( pg_proc PGNSP 81 PGUID 0 1255 0 0 0 0 0 f f r 22 0 t f f f f 3 _null_ _null_ ));
DESCR("");
DATA(insert OID = 1259 ( pg_class PGNSP 83 PGUID 0 1259 0 0 0 0 0 f f r 27 0 0 0 0 0 t f f f 3 _null_ _null_ ));
DATA(insert OID = 1259 ( pg_class PGNSP 83 PGUID 0 1259 0 0 0 0 0 f f r 24 0 t f f f f 3 _null_ _null_ ));
DESCR("");
#define RELKIND_INDEX 'i' /* secondary index */

View File

@ -1309,7 +1309,7 @@ SELECT viewname, definition FROM pg_views WHERE schemaname <> 'information_schem
pg_statio_user_sequences | SELECT pg_statio_all_sequences.relid, pg_statio_all_sequences.schemaname, pg_statio_all_sequences.relname, pg_statio_all_sequences.blks_read, pg_statio_all_sequences.blks_hit FROM pg_statio_all_sequences WHERE ((pg_statio_all_sequences.schemaname <> ALL (ARRAY['pg_catalog'::name, 'information_schema'::name])) AND (pg_statio_all_sequences.schemaname !~ '^pg_toast'::text));
pg_statio_user_tables | SELECT pg_statio_all_tables.relid, pg_statio_all_tables.schemaname, pg_statio_all_tables.relname, pg_statio_all_tables.heap_blks_read, pg_statio_all_tables.heap_blks_hit, pg_statio_all_tables.idx_blks_read, pg_statio_all_tables.idx_blks_hit, pg_statio_all_tables.toast_blks_read, pg_statio_all_tables.toast_blks_hit, pg_statio_all_tables.tidx_blks_read, pg_statio_all_tables.tidx_blks_hit FROM pg_statio_all_tables WHERE ((pg_statio_all_tables.schemaname <> ALL (ARRAY['pg_catalog'::name, 'information_schema'::name])) AND (pg_statio_all_tables.schemaname !~ '^pg_toast'::text));
pg_stats | SELECT n.nspname AS schemaname, c.relname AS tablename, a.attname, s.stanullfrac AS null_frac, s.stawidth AS avg_width, s.stadistinct AS n_distinct, CASE WHEN (s.stakind1 = ANY (ARRAY[1, 4])) THEN s.stavalues1 WHEN (s.stakind2 = ANY (ARRAY[1, 4])) THEN s.stavalues2 WHEN (s.stakind3 = ANY (ARRAY[1, 4])) THEN s.stavalues3 WHEN (s.stakind4 = ANY (ARRAY[1, 4])) THEN s.stavalues4 ELSE NULL::anyarray END AS most_common_vals, CASE WHEN (s.stakind1 = ANY (ARRAY[1, 4])) THEN s.stanumbers1 WHEN (s.stakind2 = ANY (ARRAY[1, 4])) THEN s.stanumbers2 WHEN (s.stakind3 = ANY (ARRAY[1, 4])) THEN s.stanumbers3 WHEN (s.stakind4 = ANY (ARRAY[1, 4])) THEN s.stanumbers4 ELSE NULL::real[] END AS most_common_freqs, CASE WHEN (s.stakind1 = 2) THEN s.stavalues1 WHEN (s.stakind2 = 2) THEN s.stavalues2 WHEN (s.stakind3 = 2) THEN s.stavalues3 WHEN (s.stakind4 = 2) THEN s.stavalues4 ELSE NULL::anyarray END AS histogram_bounds, CASE WHEN (s.stakind1 = 3) THEN s.stanumbers1[1] WHEN (s.stakind2 = 3) THEN s.stanumbers2[1] WHEN (s.stakind3 = 3) THEN s.stanumbers3[1] WHEN (s.stakind4 = 3) THEN s.stanumbers4[1] ELSE NULL::real END AS correlation FROM (((pg_statistic s JOIN pg_class c ON ((c.oid = s.starelid))) JOIN pg_attribute a ON (((c.oid = a.attrelid) AND (a.attnum = s.staattnum)))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) WHERE has_table_privilege(c.oid, 'select'::text);
pg_tables | SELECT n.nspname AS schemaname, c.relname AS tablename, pg_get_userbyid(c.relowner) AS tableowner, t.spcname AS tablespace, c.relhasindex AS hasindexes, c.relhasrules AS hasrules, (c.reltriggers > 0) AS hastriggers FROM ((pg_class c LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) LEFT JOIN pg_tablespace t ON ((t.oid = c.reltablespace))) WHERE (c.relkind = 'r'::"char");
pg_tables | SELECT n.nspname AS schemaname, c.relname AS tablename, pg_get_userbyid(c.relowner) AS tableowner, t.spcname AS tablespace, c.relhasindex AS hasindexes, c.relhasrules AS hasrules, c.relhastriggers AS hastriggers FROM ((pg_class c LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) LEFT JOIN pg_tablespace t ON ((t.oid = c.reltablespace))) WHERE (c.relkind = 'r'::"char");
pg_timezone_abbrevs | SELECT pg_timezone_abbrevs.abbrev, pg_timezone_abbrevs.utc_offset, pg_timezone_abbrevs.is_dst FROM pg_timezone_abbrevs() pg_timezone_abbrevs(abbrev, utc_offset, is_dst);
pg_timezone_names | SELECT pg_timezone_names.name, pg_timezone_names.abbrev, pg_timezone_names.utc_offset, pg_timezone_names.is_dst FROM pg_timezone_names() pg_timezone_names(name, abbrev, utc_offset, is_dst);
pg_user | SELECT pg_shadow.usename, pg_shadow.usesysid, pg_shadow.usecreatedb, pg_shadow.usesuper, pg_shadow.usecatupd, '********'::text AS passwd, pg_shadow.valuntil, pg_shadow.useconfig FROM pg_shadow;