diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml index faee42ba1036d6e6faeec720946ce523ce6570f7..ae9a6cfd8ecf746a0d687b654d37a1d62db4715b 100644 --- a/doc/src/sgml/catalogs.sgml +++ b/doc/src/sgml/catalogs.sgml @@ -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> diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index f7585632e0519b626bbda1ba87286c49784266a7..ad0dca13e1b8561064f2c4654c338bba5b9e42a4 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -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)); } diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql index 46023c60b0450b2aa7c46b8b39bc58996af207f7..07c0809609d6836679f334a3bf6627d45bc5c743 100644 --- a/src/backend/catalog/system_views.sql +++ b/src/backend/catalog/system_views.sql @@ -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'; diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index 53fb1995fc88031a16bffec0481fce4d9946c77c..07c686c91da797f7d80ad429a36b009c5afb764d 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -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); diff --git a/src/backend/rewrite/rewriteDefine.c b/src/backend/rewrite/rewriteDefine.c index 6f40944ef2650b1310e52fb68dce474a3cdffa89..6212add6bcb9967f78b421fe8029615fb6908a7b 100644 --- a/src/backend/rewrite/rewriteDefine.c +++ b/src/backend/rewrite/rewriteDefine.c @@ -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", diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index cec75ada720ad5a358f786e29982db15c6297647..92adfd8300d1c1f5ae23108f2cd82e8fab71eb2c 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -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); } diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index 936ff42bb871297ac064ea51dfdb4786d1dbba96..d6c0f304f075252015ddfbbae2addb0f9a39abf8 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -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"); diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h index 80f02efb2f12338dd205cea99a7bd1f02acbdef3..9684163e3d58b26c26061a7c4a9b3b01fe05e509 100644 --- a/src/bin/pg_dump/pg_dump.h +++ b/src/bin/pg_dump/pg_dump.h @@ -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 */ diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c index d0ca9a034b6cf6e31b2b14bb35213c5167156a68..53087771afde4d4cad8e3bafe648ad2dc755522c 100644 --- a/src/bin/psql/describe.c +++ b/src/bin/psql/describe.c @@ -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, " diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index 58bda0f16d3411fa1f446191036dba09efe714f7..599e01db6a1f2f8464dac9c27b1602adfd68a288 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -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 diff --git a/src/include/catalog/pg_attribute.h b/src/include/catalog/pg_attribute.h index 365f45b39056f6c0bbf5add120727d82e19a8ff9..e816b3ce9adf414d697a05671b19779365c714fa 100644 --- a/src/include/catalog/pg_attribute.h +++ b/src/include/catalog/pg_attribute.h @@ -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)); diff --git a/src/include/catalog/pg_class.h b/src/include/catalog/pg_class.h index 7f418aa8478d2a4c23469fe5d9bd6903cff328cb..32b633b55ad00197ebf7256a6dcf6cd88346898e 100644 --- a/src/include/catalog/pg_class.h +++ b/src/include/catalog/pg_class.h @@ -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 */ diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out index 50abeb5b0e0e9895cff1956dd1fcfa17764f6a0d..80b002d5388440df5d0b0ad5edf000b474c9519f 100644 --- a/src/test/regress/expected/rules.out +++ b/src/test/regress/expected/rules.out @@ -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;