aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/catalog/heap.c8
-rw-r--r--src/backend/commands/command.c29
-rw-r--r--src/backend/commands/comment.c9
-rw-r--r--src/backend/commands/vacuum.c4
-rw-r--r--src/backend/commands/view.c4
-rw-r--r--src/backend/executor/execMain.c6
-rw-r--r--src/backend/rewrite/rewriteDefine.c71
-rw-r--r--src/backend/rewrite/rewriteRemove.c7
-rw-r--r--src/backend/tcop/utility.c5
-rw-r--r--src/backend/utils/cache/relcache.c22
-rw-r--r--src/include/catalog/catversion.h4
-rw-r--r--src/include/catalog/pg_class.h3
-rw-r--r--src/test/regress/expected/type_sanity.out2
-rw-r--r--src/test/regress/sql/type_sanity.sql2
14 files changed, 139 insertions, 37 deletions
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index cf4b86e2e82..68bb8276981 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.142 2000/08/03 19:19:08 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.143 2000/09/12 04:49:06 momjian Exp $
*
*
* INTERFACE ROUTINES
@@ -842,7 +842,9 @@ heap_create_with_catalog(char *relname,
/*
* We create the disk file for this relation here
*/
- heap_storage_create(new_rel_desc);
+ if (relkind != RELKIND_VIEW)
+ heap_storage_create(new_rel_desc);
+
/* ----------------
* ok, the relation has been cataloged, so close our relations
* and return the oid of the newly created relation.
@@ -1468,7 +1470,7 @@ heap_drop_with_catalog(const char *relname,
* unlink the relation's physical file and finish up.
* ----------------
*/
- if (! rel->rd_unlinked)
+ if (rel->rd_rel->relkind != RELKIND_VIEW && ! rel->rd_unlinked)
smgrunlink(DEFAULT_SMGR, rel);
rel->rd_unlinked = true;
diff --git a/src/backend/commands/command.c b/src/backend/commands/command.c
index d0de9e2e4de..d0faa943cfd 100644
--- a/src/backend/commands/command.c
+++ b/src/backend/commands/command.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.100 2000/09/12 04:33:18 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.101 2000/09/12 04:49:06 momjian Exp $
*
* NOTES
* The PerformAddAttribute() code, like most of the relation
@@ -533,6 +533,9 @@ AlterTableAlterColumn(const char *relationName,
#endif
rel = heap_openr(relationName, AccessExclusiveLock);
+ if ( rel->rd_rel->relkind == RELKIND_VIEW )
+ elog(ERROR, "ALTER TABLE: %s is a view", relationName);
+
myrelid = RelationGetRelid(rel);
heap_close(rel, NoLock);
@@ -1133,6 +1136,10 @@ AlterTableAddConstraint(char *relationName,
rel = heap_openr(relationName, AccessExclusiveLock);
+ /* make sure it is not a view */
+ if (rel->rd_rel->relkind == RELKIND_VIEW)
+ elog(ERROR, "ALTER TABLE: cannot add constraint to a view");
+
/*
* Scan all of the rows, looking for a false match
*/
@@ -1251,19 +1258,20 @@ AlterTableAddConstraint(char *relationName,
elog(ERROR, "ALTER TABLE / ADD CONSTRAINT: Unable to reference temporary table from permanent table constraint.");
}
- /* check to see if the referenced table is a view. */
- if (is_viewr(fkconstraint->pktable_name))
- elog(ERROR, "ALTER TABLE: Cannot add constraints to views.");
-
/*
* Grab an exclusive lock on the pk table, so that someone
* doesn't delete rows out from under us.
*/
pkrel = heap_openr(fkconstraint->pktable_name, AccessExclusiveLock);
- if (pkrel == NULL)
- elog(ERROR, "referenced table \"%s\" not found",
+ if (pkrel == NULL)
+ elog(ERROR, "referenced table \"%s\" not found",
+ fkconstraint->pktable_name);
+
+ if (pkrel->rd_rel->relkind != RELKIND_RELATION)
+ elog(ERROR, "referenced table \"%s\" not a relation",
fkconstraint->pktable_name);
+
/*
* Grab an exclusive lock on the fk table, and then scan
@@ -1277,6 +1285,9 @@ AlterTableAddConstraint(char *relationName,
elog(ERROR, "table \"%s\" not found",
relationName);
+ if (rel->rd_rel->relkind != RELKIND_RELATION)
+ elog(ERROR, "referencing table \"%s\" not a relation", relationName);
+
/* First we check for limited correctness of the constraint */
rel_attrs = pkrel->rd_att->attrs;
@@ -1503,6 +1514,7 @@ AlterTableCreateToastTable(const char *relationName, bool silent)
* allow to create TOAST tables for views. But why not - someone
* can insert into a view, so it shouldn't be impossible to hide
* huge data there :-)
+ * Not any more.
*/
if (((Form_pg_class) GETSTRUCT(reltup))->relkind != RELKIND_RELATION)
{
@@ -1702,6 +1714,9 @@ LockTableCommand(LockStmt *lockstmt)
rel = heap_openr(lockstmt->relname, NoLock);
+ if (rel->rd_rel->relkind != RELKIND_RELATION)
+ elog(ERROR, "LOCK TABLE: %s is not a table", lockstmt->relname);
+
if (is_view(rel))
elog(ERROR, "LOCK TABLE: cannot lock a view");
diff --git a/src/backend/commands/comment.c b/src/backend/commands/comment.c
index 87c7d84727d..51832bc2c7b 100644
--- a/src/backend/commands/comment.c
+++ b/src/backend/commands/comment.c
@@ -21,6 +21,7 @@
#include "catalog/pg_shadow.h"
#include "catalog/pg_trigger.h"
#include "catalog/pg_type.h"
+#include "catalog/pg_class.h"
#include "commands/comment.h"
#include "miscadmin.h"
#include "parser/parse.h"
@@ -301,19 +302,19 @@ CommentRelation(int reltype, char *relname, char *comment)
switch (reltype)
{
case (INDEX):
- if (relkind != 'i')
+ if (relkind != RELKIND_INDEX)
elog(ERROR, "relation '%s' is not an index", relname);
break;
case (TABLE):
- if (relkind != 'r')
+ if (relkind != RELKIND_RELATION)
elog(ERROR, "relation '%s' is not a table", relname);
break;
case (VIEW):
- if (relkind != 'r')
+ if (relkind != RELKIND_VIEW)
elog(ERROR, "relation '%s' is not a view", relname);
break;
case (SEQUENCE):
- if (relkind != 'S')
+ if (relkind != RELKIND_SEQUENCE)
elog(ERROR, "relation '%s' is not a sequence", relname);
break;
}
diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 398d002ffcd..7d4005d21d5 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.164 2000/09/06 14:15:16 petere Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.165 2000/09/12 04:49:07 momjian Exp $
*
*-------------------------------------------------------------------------
@@ -306,7 +306,7 @@ getrels(NameData *VacRelP)
if (rkind != RELKIND_RELATION)
{
- elog(NOTICE, "Vacuum: can not process index and certain system tables");
+ elog(NOTICE, "Vacuum: can not process indecies, views and certain system tables");
continue;
}
diff --git a/src/backend/commands/view.c b/src/backend/commands/view.c
index 01e23d13150..af10805b71f 100644
--- a/src/backend/commands/view.c
+++ b/src/backend/commands/view.c
@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: view.c,v 1.46 2000/09/12 04:15:56 momjian Exp $
+ * $Id: view.c,v 1.47 2000/09/12 04:49:07 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -102,7 +102,7 @@ DefineVirtualRelation(char *relname, List *tlist)
/*
* finally create the relation...
*/
- DefineRelation(&createStmt, RELKIND_RELATION);
+ DefineRelation(&createStmt, RELKIND_VIEW);
}
/*------------------------------------------------------------------
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index c6571279e1f..d25530b44fb 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -27,7 +27,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.125 2000/09/06 14:15:17 petere Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.126 2000/09/12 04:49:08 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -720,6 +720,10 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
elog(ERROR, "You can't change toast relation %s",
RelationGetRelationName(resultRelationDesc));
+ if (resultRelationDesc->rd_rel->relkind == RELKIND_VIEW)
+ elog(ERROR, "You can't change view relation %s",
+ RelationGetRelationName(resultRelationDesc));
+
resultRelationInfo = makeNode(RelationInfo);
resultRelationInfo->ri_RangeTableIndex = resultRelationIndex;
resultRelationInfo->ri_RelationDesc = resultRelationDesc;
diff --git a/src/backend/rewrite/rewriteDefine.c b/src/backend/rewrite/rewriteDefine.c
index c9315f6d338..8444bd91384 100644
--- a/src/backend/rewrite/rewriteDefine.c
+++ b/src/backend/rewrite/rewriteDefine.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.50 2000/09/12 04:15:57 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.51 2000/09/12 04:49:09 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -23,6 +23,8 @@
#include "parser/parse_relation.h"
#include "rewrite/rewriteDefine.h"
#include "rewrite/rewriteSupport.h"
+#include "utils/syscache.h"
+#include "storage/smgr.h"
#include "commands/view.h"
@@ -162,6 +164,7 @@ DefineQueryRewrite(RuleStmt *stmt)
*event_qualP;
List *l;
Query *query;
+ bool RelisBecomingView = false;
/*
* If we are installing an ON SELECT rule, we had better grab
@@ -207,6 +210,30 @@ DefineQueryRewrite(RuleStmt *stmt)
elog(ERROR, "rule actions on NEW currently not supported"
"\n\tuse triggers instead");
}
+
+ if (event_relation->rd_rel->relkind != RELKIND_VIEW)
+ {
+ HeapScanDesc scanDesc;
+ HeapTuple tuple;
+ /*
+ * A relation is about to become a view.
+ * check that the relation is empty because
+ * the storage for the relation is going to
+ * be deleted.
+ */
+
+ scanDesc = heap_beginscan(event_relation, 0, SnapshotNow, 0, NULL);
+ tuple = heap_getnext(scanDesc, 0);
+ if (HeapTupleIsValid(tuple))
+ elog(ERROR, "relation %s is not empty. Cannot convert to view", event_obj->relname);
+
+ /* don't need heap_freetuple because we never got a valid tuple */
+ heap_endscan(scanDesc);
+
+
+ RelisBecomingView = true;
+ }
+
}
/*
@@ -338,6 +365,10 @@ DefineQueryRewrite(RuleStmt *stmt)
/* discard rule if it's null action and not INSTEAD; it's a no-op */
if (action != NULL || is_instead)
{
+ Relation relationRelation;
+ HeapTuple tuple;
+ Relation idescs[Num_pg_class_indices];
+
event_qualP = nodeToString(event_qual);
actionP = nodeToString(action);
@@ -351,14 +382,50 @@ DefineQueryRewrite(RuleStmt *stmt)
/*
* Set pg_class 'relhasrules' field TRUE for event relation.
+ * Also modify the 'relkind' field to show that the relation is
+ * now a view.
*
* Important side effect: an SI notice is broadcast to force all
* backends (including me!) to update relcache entries with the new
* rule.
+ *
+ * NOTE : Used to call setRelhasrulesInRelation. The code
+ * was inlined so that two updates were not needed. mhh 31-aug-2000
+ */
+
+ /*
+ * Find the tuple to update in pg_class, using syscache for the lookup.
*/
- setRelhasrulesInRelation(ev_relid, true);
+ relationRelation = heap_openr(RelationRelationName, RowExclusiveLock);
+ tuple = SearchSysCacheTupleCopy(RELOID,
+ ObjectIdGetDatum(ev_relid),
+ 0, 0, 0);
+ Assert(HeapTupleIsValid(tuple));
+
+ /* Do the update */
+ ((Form_pg_class) GETSTRUCT(tuple))->relhasrules = true;
+ if (RelisBecomingView)
+ ((Form_pg_class) GETSTRUCT(tuple))->relkind = RELKIND_VIEW;
+
+ heap_update(relationRelation, &tuple->t_self, tuple, NULL);
+
+ /* Keep the catalog indices up to date */
+ CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, idescs);
+ CatalogIndexInsert(idescs, Num_pg_class_indices, relationRelation, tuple);
+ CatalogCloseIndices(Num_pg_class_indices, idescs);
+
+ heap_freetuple(tuple);
+ heap_close(relationRelation, RowExclusiveLock);
}
+ /*
+ * IF the relation is becoming a view, delete the storage
+ * files associated with it.
+ */
+ if (RelisBecomingView)
+ smgrunlink(DEFAULT_SMGR, event_relation);
+
+
/* Close rel, but keep lock till commit... */
heap_close(event_relation, NoLock);
}
diff --git a/src/backend/rewrite/rewriteRemove.c b/src/backend/rewrite/rewriteRemove.c
index d50e1049097..2af77853c46 100644
--- a/src/backend/rewrite/rewriteRemove.c
+++ b/src/backend/rewrite/rewriteRemove.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteRemove.c,v 1.38 2000/06/30 07:04:23 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteRemove.c,v 1.39 2000/09/12 04:49:09 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -103,6 +103,11 @@ RemoveRewriteRule(char *ruleName)
*/
event_relation = heap_open(eventRelationOid, AccessExclusiveLock);
+ /* do not allow the removal of a view's SELECT rule */
+ if (event_relation->rd_rel->relkind == RELKIND_VIEW &&
+ ((Form_pg_rewrite) GETSTRUCT(tuple))->ev_type == '1' )
+ elog(ERROR, "Cannot remove a view's SELECT rule");
+
hasMoreRules = event_relation->rd_rules != NULL &&
event_relation->rd_rules->numLocks > 1;
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 558f678430f..d603914c514 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.92 2000/09/06 14:15:21 petere Exp $
+ * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.93 2000/09/12 04:49:11 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -228,6 +228,9 @@ ProcessUtility(Node *parsetree,
if (rel->rd_rel->relkind == RELKIND_SEQUENCE)
elog(ERROR, "TRUNCATE cannot be used on sequences. '%s' is a sequence",
relname);
+ if (rel->rd_rel->relkind == RELKIND_VIEW)
+ elog(ERROR, "TRUNCATE cannot be used on views. '%s' is a sequence",
+ relname);
heap_close(rel, NoLock);
#ifndef NO_SECURITY
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 013ade75288..e39f1cfd12d 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.110 2000/08/30 08:48:55 inoue Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.111 2000/09/12 04:49:13 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1022,14 +1022,18 @@ RelationBuildDesc(RelationBuildDescInfo buildinfo,
* by the storage manager code to rd_fd.
* ----------------
*/
- fd = smgropen(DEFAULT_SMGR, relation);
+ if (relation->rd_rel->relkind != RELKIND_VIEW) {
+ fd = smgropen(DEFAULT_SMGR, relation);
- Assert(fd >= -1);
- if (fd == -1)
- elog(NOTICE, "RelationIdBuildRelation: smgropen(%s): %m",
- NameStr(relation->rd_rel->relname));
+ Assert(fd >= -1);
+ if (fd == -1)
+ elog(NOTICE, "RelationBuildDesc: smgropen(%s): %m",
+ NameStr(relation->rd_rel->relname));
- relation->rd_fd = fd;
+ relation->rd_fd = fd;
+ } else {
+ relation->rd_fd = -1;
+ }
/* ----------------
* insert newly created relation into proper relcaches,
@@ -1279,7 +1283,7 @@ RelationIdCacheGetRelation(Oid relationId)
if (RelationIsValid(rd))
{
- if (rd->rd_fd == -1)
+ if (rd->rd_fd == -1 && rd->rd_rel->relkind != RELKIND_VIEW)
{
rd->rd_fd = smgropen(DEFAULT_SMGR, rd);
Assert(rd->rd_fd != -1 || rd->rd_unlinked);
@@ -1313,7 +1317,7 @@ RelationNameCacheGetRelation(const char *relationName)
if (RelationIsValid(rd))
{
- if (rd->rd_fd == -1)
+ if (rd->rd_fd == -1 && rd->rd_rel->relkind != RELKIND_VIEW)
{
rd->rd_fd = smgropen(DEFAULT_SMGR, rd);
Assert(rd->rd_fd != -1 || rd->rd_unlinked);
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index 22b3cb7354e..b73ea0e6136 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: catversion.h,v 1.43 2000/08/23 06:04:43 thomas Exp $
+ * $Id: catversion.h,v 1.44 2000/09/12 04:49:15 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -53,6 +53,6 @@
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 200008221
+#define CATALOG_VERSION_NO 200009111
#endif
diff --git a/src/include/catalog/pg_class.h b/src/include/catalog/pg_class.h
index 1ea5b7b7792..3fc4a7fd76c 100644
--- a/src/include/catalog/pg_class.h
+++ b/src/include/catalog/pg_class.h
@@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: pg_class.h,v 1.39 2000/07/03 23:10:05 wieck Exp $
+ * $Id: pg_class.h,v 1.40 2000/09/12 04:49:15 momjian Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
@@ -178,5 +178,6 @@ DESCR("");
#define RELKIND_SEQUENCE 'S' /* SEQUENCE relation */
#define RELKIND_UNCATALOGED 'u' /* temporary heap */
#define RELKIND_TOASTVALUE 't' /* moved off huge values */
+#define RELKIND_VIEW 'v' /* view */
#endif /* PG_CLASS_H */
diff --git a/src/test/regress/expected/type_sanity.out b/src/test/regress/expected/type_sanity.out
index 38eaf0b21da..4f388b0e456 100644
--- a/src/test/regress/expected/type_sanity.out
+++ b/src/test/regress/expected/type_sanity.out
@@ -111,7 +111,7 @@ WHERE p1.typsend = p2.oid AND p1.typtype = 'b' AND
-- Look for illegal values in pg_class fields
SELECT p1.oid, p1.relname
FROM pg_class as p1
-WHERE p1.relkind NOT IN ('r', 'i', 's', 'S', 't');
+WHERE p1.relkind NOT IN ('r', 'i', 's', 'S', 't', 'v');
oid | relname
-----+---------
(0 rows)
diff --git a/src/test/regress/sql/type_sanity.sql b/src/test/regress/sql/type_sanity.sql
index 106a86b87c8..dbd6d0af409 100644
--- a/src/test/regress/sql/type_sanity.sql
+++ b/src/test/regress/sql/type_sanity.sql
@@ -99,7 +99,7 @@ WHERE p1.typsend = p2.oid AND p1.typtype = 'b' AND
SELECT p1.oid, p1.relname
FROM pg_class as p1
-WHERE p1.relkind NOT IN ('r', 'i', 's', 'S', 't');
+WHERE p1.relkind NOT IN ('r', 'i', 's', 'S', 't', 'v');
-- Indexes should have an access method, others not.