diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index c62394e914..3ada43a798 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -1,5 +1,5 @@ @@ -4344,7 +4344,12 @@ SELECT NULLIF(value, '(none)') ... Get CREATE VIEW command for view - pg_get_ruledef(rulename) + pg_get_viewdef(viewOID) + text + Get CREATE VIEW command for view + + + pg_get_ruledef(ruleOID) text Get CREATE RULE command for rule diff --git a/doc/src/sgml/ref/comment.sgml b/doc/src/sgml/ref/comment.sgml index f3530b71ce..c07c36e82d 100644 --- a/doc/src/sgml/ref/comment.sgml +++ b/doc/src/sgml/ref/comment.sgml @@ -1,5 +1,5 @@ @@ -25,11 +25,12 @@ PostgreSQL documentation COMMENT ON [ - [ DATABASE | DOMAIN | INDEX | RULE | SEQUENCE | TABLE | TYPE | VIEW ] object_name | + [ DATABASE | DOMAIN | INDEX | SEQUENCE | TABLE | TYPE | VIEW ] object_name | COLUMN table_name.column_name | AGGREGATE agg_name (agg_type) | FUNCTION func_name (arg1, arg2, ...) | OPERATOR op (leftoperand_type rightoperand_type) | + RULE rule_name ON table_name | TRIGGER trigger_name ON table_name ] IS 'text' @@ -46,7 +47,7 @@ COMMENT ON object_name, table_name, - column_name, agg_name, func_name, op, trigger_name + column_name, agg_name, func_name, op, rule_name, trigger_name The name of the object to be be commented. @@ -143,7 +144,6 @@ COMMENT ON mytable IS 'This is my table.'; COMMENT ON DATABASE my_database IS 'Development Database'; COMMENT ON DOMAIN my_domain IS 'Email Address Domain'; COMMENT ON INDEX my_index IS 'Enforces uniqueness on employee id'; -COMMENT ON RULE my_rule IS 'Logs UPDATES of employee records'; COMMENT ON SEQUENCE my_sequence IS 'Used to generate primary keys'; COMMENT ON TABLE my_table IS 'Employee Information'; COMMENT ON TYPE my_type IS 'Complex Number support'; @@ -152,6 +152,7 @@ COMMENT ON COLUMN my_table.my_field IS 'Employee ID number'; COMMENT ON AGGREGATE my_aggregate (double precision) IS 'Computes sample variance'; COMMENT ON FUNCTION my_function (timestamp) IS 'Returns Roman Numeral'; COMMENT ON OPERATOR ^ (text, text) IS 'Performs intersection of two text'; +COMMENT ON RULE my_rule ON my_table IS 'Logs UPDATES of employee records'; COMMENT ON TRIGGER my_trigger ON my_table IS 'Used for R.I.'; diff --git a/doc/src/sgml/ref/drop_rule.sgml b/doc/src/sgml/ref/drop_rule.sgml index 452ff48a18..522c81a628 100644 --- a/doc/src/sgml/ref/drop_rule.sgml +++ b/doc/src/sgml/ref/drop_rule.sgml @@ -1,5 +1,5 @@ @@ -23,7 +23,7 @@ PostgreSQL documentation 1998-09-22 -DROP RULE name [, ...] +DROP RULE name ON relation @@ -43,6 +43,14 @@ DROP RULE name [, ...] + + relation + + + The name of the relation the rule applies to. + + + @@ -68,7 +76,7 @@ DROP -ERROR: Rule or view "name" not found +ERROR: Rule "name" not found @@ -113,11 +121,6 @@ ERROR: Rule or view "name" not fou Refer to CREATE RULE for information on how to create rules. - - - Once a rule is dropped, access to historical information - the rule has written may disappear. - @@ -129,7 +132,7 @@ ERROR: Rule or view "name" not fou To drop the rewrite rule newrule: -DROP RULE newrule; +DROP RULE newrule ON mytable; diff --git a/doc/src/sgml/release.sgml b/doc/src/sgml/release.sgml index a2ace11be5..0fe78be994 100644 --- a/doc/src/sgml/release.sgml +++ b/doc/src/sgml/release.sgml @@ -1,5 +1,5 @@ @@ -24,6 +24,7 @@ CDATA means the content is "SGML-free", so you can write without worries about funny characters. --> ev_class; - ruleoid = tuple->t_data->t_oid; + RewriteRelation = heap_openr(RewriteRelationName, AccessShareLock); + scanDesc = heap_beginscan(RewriteRelation, + 0, SnapshotNow, 1, &scanKeyData); - ReleaseSysCache(tuple); + tuple = heap_getnext(scanDesc, 0); + if (HeapTupleIsValid(tuple)) + { + reloid = ((Form_pg_rewrite) GETSTRUCT(tuple))->ev_class; + ruleoid = tuple->t_data->t_oid; + } + else + { + elog(ERROR, "rule '%s' does not exist", rulename); + reloid = ruleoid = 0; /* keep compiler quiet */ + } + + if (HeapTupleIsValid(tuple = heap_getnext(scanDesc, 0))) + elog(ERROR, "There are multiple rules '%s'" + "\n\tPlease specify a relation name as well as a rule name", + rulename); + + heap_endscan(scanDesc); + heap_close(RewriteRelation, AccessShareLock); + + /* Open the owning relation to ensure it won't go away meanwhile */ + relation = heap_open(reloid, AccessShareLock); + } + else + { + /* New-style: rule and relname both provided */ + Assert(nnames >= 2); + relname = ltruncate(nnames-1, listCopy(qualname)); + rulename = strVal(nth(nnames-1, qualname)); + + /* Open the owning relation to ensure it won't go away meanwhile */ + rel = makeRangeVarFromNameList(relname); + relation = heap_openrv(rel, AccessShareLock); + reloid = RelationGetRelid(relation); + + /* Find the rule's pg_rewrite tuple, get its OID */ + tuple = SearchSysCache(RULERELNAME, + ObjectIdGetDatum(reloid), + PointerGetDatum(rulename), + 0, 0); + if (!HeapTupleIsValid(tuple)) + elog(ERROR, "rule '%s' does not exist", rulename); + Assert(reloid == ((Form_pg_rewrite) GETSTRUCT(tuple))->ev_class); + ruleoid = tuple->t_data->t_oid; + ReleaseSysCache(tuple); + } /* Check object security */ aclcheck = pg_class_aclcheck(reloid, GetUserId(), ACL_RULE); if (aclcheck != ACLCHECK_OK) elog(ERROR, "you are not permitted to comment on rule '%s'", - rule); + rulename); /* pg_rewrite doesn't have a hard-coded OID, so must look it up */ diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index f6c9b48c09..8abd8cf80d 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.2 2002/04/15 23:45:07 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.3 2002/04/18 20:01:09 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1423,8 +1423,8 @@ AlterTableCreateToastTable(Oid relOid, bool silent) Relation ridescs[Num_pg_class_indices]; Oid toast_relid; Oid toast_idxid; - char toast_relname[NAMEDATALEN + 1]; - char toast_idxname[NAMEDATALEN + 1]; + char toast_relname[NAMEDATALEN]; + char toast_idxname[NAMEDATALEN]; IndexInfo *indexInfo; Oid classObjectId[2]; @@ -1667,7 +1667,7 @@ needs_toast_table(Relation rel) Oid DefineRelation(CreateStmt *stmt, char relkind) { - char *relname = palloc(NAMEDATALEN); + char relname[NAMEDATALEN]; Oid namespaceId; List *schema = stmt->tableElts; int numberOfAttributes; @@ -1686,7 +1686,7 @@ DefineRelation(CreateStmt *stmt, char relkind) * Truncate relname to appropriate length (probably a waste of time, * as parser should have done this already). */ - StrNCpy(relname, (stmt->relation)->relname, NAMEDATALEN); + StrNCpy(relname, stmt->relation->relname, NAMEDATALEN); /* * Look up the namespace in which we are supposed to create the @@ -2642,8 +2642,8 @@ renameatt(Oid relid, 0, 0)) elog(ERROR, "renameatt: attribute \"%s\" exists", newattname); - StrNCpy(NameStr(((Form_pg_attribute) GETSTRUCT(atttup))->attname), - newattname, NAMEDATALEN); + namestrcpy(&(((Form_pg_attribute) GETSTRUCT(atttup))->attname), + newattname); simple_heap_update(attrelation, &atttup->t_self, atttup); @@ -2699,8 +2699,8 @@ renameatt(Oid relid, /* * Update the (copied) attribute tuple. */ - StrNCpy(NameStr(((Form_pg_attribute) GETSTRUCT(atttup))->attname), - newattname, NAMEDATALEN); + namestrcpy(&(((Form_pg_attribute) GETSTRUCT(atttup))->attname), + newattname); simple_heap_update(attrelation, &atttup->t_self, atttup); @@ -2753,6 +2753,7 @@ renamerel(Oid relid, const char *newrelname) Relation relrelation; /* for RELATION relation */ HeapTuple reltup; Oid namespaceId; + char *oldrelname; char relkind; bool relhastriggers; Relation irelations[Num_pg_class_indices]; @@ -2763,13 +2764,14 @@ renamerel(Oid relid, const char *newrelname) */ targetrelation = relation_open(relid, AccessExclusiveLock); + oldrelname = pstrdup(RelationGetRelationName(targetrelation)); namespaceId = RelationGetNamespace(targetrelation); /* Validity checks */ if (!allowSystemTableMods && IsSystemRelation(targetrelation)) elog(ERROR, "renamerel: system relation \"%s\" may not be renamed", - RelationGetRelationName(targetrelation)); + oldrelname); relkind = targetrelation->rd_rel->relkind; relhastriggers = (targetrelation->rd_rel->reltriggers > 0); @@ -2785,7 +2787,7 @@ renamerel(Oid relid, const char *newrelname) 0, 0, 0); if (!HeapTupleIsValid(reltup)) elog(ERROR, "renamerel: relation \"%s\" does not exist", - RelationGetRelationName(targetrelation)); + oldrelname); if (get_relname_relid(newrelname, namespaceId) != InvalidOid) elog(ERROR, "renamerel: relation \"%s\" exists", newrelname); @@ -2794,8 +2796,7 @@ renamerel(Oid relid, const char *newrelname) * Update pg_class tuple with new relname. (Scribbling on reltup is * OK because it's a copy...) */ - StrNCpy(NameStr(((Form_pg_class) GETSTRUCT(reltup))->relname), - newrelname, NAMEDATALEN); + namestrcpy(&(((Form_pg_class) GETSTRUCT(reltup))->relname), newrelname); simple_heap_update(relrelation, &reltup->t_self, reltup); @@ -2811,8 +2812,7 @@ renamerel(Oid relid, const char *newrelname) * Also rename the associated type, if any. */ if (relkind != RELKIND_INDEX) - TypeRename(RelationGetRelationName(targetrelation), namespaceId, - newrelname); + TypeRename(oldrelname, namespaceId, newrelname); /* * If it's a view, must also rename the associated ON SELECT rule. @@ -2822,9 +2822,9 @@ renamerel(Oid relid, const char *newrelname) char *oldrulename, *newrulename; - oldrulename = MakeRetrieveViewRuleName(RelationGetRelationName(targetrelation)); + oldrulename = MakeRetrieveViewRuleName(oldrelname); newrulename = MakeRetrieveViewRuleName(newrelname); - RenameRewriteRule(oldrulename, newrulename); + RenameRewriteRule(relid, oldrulename, newrulename); } /* @@ -2834,12 +2834,12 @@ renamerel(Oid relid, const char *newrelname) { /* update tgargs where relname is primary key */ update_ri_trigger_args(relid, - RelationGetRelationName(targetrelation), + oldrelname, newrelname, false, true); /* update tgargs where relname is foreign key */ update_ri_trigger_args(relid, - RelationGetRelationName(targetrelation), + oldrelname, newrelname, true, true); } diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index 8417f7a716..d9d5d13d8d 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -15,7 +15,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.179 2002/04/17 20:57:56 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.180 2002/04/18 20:01:09 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -2380,14 +2380,15 @@ _copyCreateTrigStmt(CreateTrigStmt *from) return newnode; } -static DropTrigStmt * -_copyDropTrigStmt(DropTrigStmt *from) +static DropPropertyStmt * +_copyDropPropertyStmt(DropPropertyStmt *from) { - DropTrigStmt *newnode = makeNode(DropTrigStmt); + DropPropertyStmt *newnode = makeNode(DropPropertyStmt); - if (from->trigname) - newnode->trigname = pstrdup(from->trigname); Node_Copy(from, newnode, relation); + if (from->property) + newnode->property = pstrdup(from->property); + newnode->removeType = from->removeType; return newnode; } @@ -2915,8 +2916,8 @@ copyObject(void *from) case T_CreateTrigStmt: retval = _copyCreateTrigStmt(from); break; - case T_DropTrigStmt: - retval = _copyDropTrigStmt(from); + case T_DropPropertyStmt: + retval = _copyDropPropertyStmt(from); break; case T_CreatePLangStmt: retval = _copyCreatePLangStmt(from); diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index 58f6b5a5d6..42030b2726 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -20,7 +20,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.127 2002/04/17 20:57:56 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.128 2002/04/18 20:01:09 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1232,12 +1232,14 @@ _equalCreateTrigStmt(CreateTrigStmt *a, CreateTrigStmt *b) } static bool -_equalDropTrigStmt(DropTrigStmt *a, DropTrigStmt *b) +_equalDropPropertyStmt(DropPropertyStmt *a, DropPropertyStmt *b) { - if (!equalstr(a->trigname, b->trigname)) - return false; if (!equal(a->relation, b->relation)) return false; + if (!equalstr(a->property, b->property)) + return false; + if (a->removeType != b->removeType) + return false; return true; } @@ -2080,8 +2082,8 @@ equal(void *a, void *b) case T_CreateTrigStmt: retval = _equalCreateTrigStmt(a, b); break; - case T_DropTrigStmt: - retval = _equalDropTrigStmt(a, b); + case T_DropPropertyStmt: + retval = _equalDropPropertyStmt(a, b); break; case T_CreatePLangStmt: retval = _equalCreatePLangStmt(a, b); diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 774f9fa743..e4ec05abf2 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.303 2002/04/17 20:57:56 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.304 2002/04/18 20:01:09 tgl Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -134,7 +134,7 @@ static bool set_name_needs_quotes(const char *name); CreateSchemaStmt, CreateSeqStmt, CreateStmt, CreateTrigStmt, CreateUserStmt, CreatedbStmt, CursorStmt, DefineStmt, DeleteStmt, DropGroupStmt, DropPLangStmt, DropSchemaStmt, DropStmt, DropTrigStmt, - DropUserStmt, DropdbStmt, ExplainStmt, FetchStmt, + DropRuleStmt, DropUserStmt, DropdbStmt, ExplainStmt, FetchStmt, GrantStmt, IndexStmt, InsertStmt, ListenStmt, LoadStmt, LockStmt, NotifyStmt, OptimizableStmt, ProcedureStmt, ReindexStmt, RemoveAggrStmt, RemoveFuncStmt, RemoveOperStmt, @@ -469,6 +469,7 @@ stmt : AlterDatabaseSetStmt | DropGroupStmt | DropPLangStmt | DropTrigStmt + | DropRuleStmt | DropUserStmt | ExplainStmt | FetchStmt @@ -2062,9 +2063,10 @@ ConstraintTimeSpec: INITIALLY IMMEDIATE DropTrigStmt: DROP TRIGGER name ON qualified_name { - DropTrigStmt *n = makeNode(DropTrigStmt); - n->trigname = $3; + DropPropertyStmt *n = makeNode(DropPropertyStmt); n->relation = $5; + n->property = $3; + n->removeType = DROP_TRIGGER; $$ = (Node *) n; } ; @@ -2154,7 +2156,6 @@ drop_type: TABLE { $$ = DROP_TABLE; } | SEQUENCE { $$ = DROP_SEQUENCE; } | VIEW { $$ = DROP_VIEW; } | INDEX { $$ = DROP_INDEX; } - | RULE { $$ = DROP_RULE; } | TYPE_P { $$ = DROP_TYPE; } | DOMAIN_P { $$ = DROP_DOMAIN; } ; @@ -2191,11 +2192,11 @@ TruncateStmt: TRUNCATE opt_table qualified_name * The COMMENT ON statement can take different forms based upon the type of * the object associated with the comment. The form of the statement is: * - * COMMENT ON [ [ DATABASE | DOMAIN | INDEX | RULE | SEQUENCE | TABLE | TYPE | VIEW ] + * COMMENT ON [ [ DATABASE | DOMAIN | INDEX | SEQUENCE | TABLE | TYPE | VIEW ] * | AGGREGATE () | FUNCTION * (arg1, arg2, ...) | OPERATOR * (leftoperand_typ rightoperand_typ) | TRIGGER ON - * ] IS 'text' + * | RULE ON ] IS 'text' * *****************************************************************************/ @@ -2244,12 +2245,30 @@ CommentStmt: COMMENT ON comment_type any_name IS comment_text n->comment = $8; $$ = (Node *) n; } + | COMMENT ON RULE name ON any_name IS comment_text + { + CommentStmt *n = makeNode(CommentStmt); + n->objtype = RULE; + n->objname = lappend($6, makeString($4)); + n->objargs = NIL; + n->comment = $8; + $$ = (Node *) n; + } + | COMMENT ON RULE name IS comment_text + { + /* Obsolete syntax supported for awhile for compatibility */ + CommentStmt *n = makeNode(CommentStmt); + n->objtype = RULE; + n->objname = makeList1(makeString($4)); + n->objargs = NIL; + n->comment = $6; + $$ = (Node *) n; + } ; comment_type: COLUMN { $$ = COLUMN; } | DATABASE { $$ = DATABASE; } | INDEX { $$ = INDEX; } - | RULE { $$ = RULE; } | SEQUENCE { $$ = SEQUENCE; } | TABLE { $$ = TABLE; } | DOMAIN_P { $$ = TYPE_P; } @@ -2977,6 +2996,17 @@ opt_instead: INSTEAD { $$ = TRUE; } ; +DropRuleStmt: DROP RULE name ON qualified_name + { + DropPropertyStmt *n = makeNode(DropPropertyStmt); + n->relation = $5; + n->property = $3; + n->removeType = DROP_RULE; + $$ = (Node *) n; + } + ; + + /***************************************************************************** * * QUERY: diff --git a/src/backend/rewrite/rewriteDefine.c b/src/backend/rewrite/rewriteDefine.c index f20c9a0d98..8b40aeb4f7 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.66 2002/03/26 19:16:02 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.67 2002/04/18 20:01:09 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -37,7 +37,7 @@ static bool setRuleCheckAsUser_walker(Node *node, Oid *context); /* * InsertRule - - * takes the arguments and inserts them as attributes into the system + * takes the arguments and inserts them as a row into the system * relation "pg_rewrite" */ static Oid @@ -58,7 +58,7 @@ InsertRule(char *rulname, HeapTuple tup; Oid rewriteObjectId; - if (IsDefinedRewriteRule(rulname)) + if (IsDefinedRewriteRule(eventrel_oid, rulname)) elog(ERROR, "Attempt to insert rule \"%s\" failed: already exists", rulname); @@ -69,13 +69,13 @@ InsertRule(char *rulname, i = 0; namestrcpy(&rname, rulname); - values[i++] = NameGetDatum(&rname); - values[i++] = CharGetDatum(evtype + '0'); - values[i++] = ObjectIdGetDatum(eventrel_oid); - values[i++] = Int16GetDatum(evslot_index); - values[i++] = BoolGetDatum(evinstead); - values[i++] = DirectFunctionCall1(textin, CStringGetDatum(evqual)); - values[i++] = DirectFunctionCall1(textin, CStringGetDatum(actiontree)); + values[i++] = NameGetDatum(&rname); /* rulename */ + values[i++] = ObjectIdGetDatum(eventrel_oid); /* ev_class */ + values[i++] = Int16GetDatum(evslot_index); /* ev_attr */ + values[i++] = CharGetDatum(evtype + '0'); /* ev_type */ + values[i++] = BoolGetDatum(evinstead); /* is_instead */ + values[i++] = DirectFunctionCall1(textin, CStringGetDatum(evqual)); /* ev_qual */ + values[i++] = DirectFunctionCall1(textin, CStringGetDatum(actiontree)); /* ev_action */ /* * create a new pg_rewrite tuple @@ -423,26 +423,27 @@ setRuleCheckAsUser_walker(Node *node, Oid *context) * ON SELECT rule associated with a view, when the view is renamed. */ void -RenameRewriteRule(char *oldname, char *newname) +RenameRewriteRule(Oid owningRel, const char *oldName, + const char *newName) { Relation pg_rewrite_desc; HeapTuple ruletup; pg_rewrite_desc = heap_openr(RewriteRelationName, RowExclusiveLock); - ruletup = SearchSysCacheCopy(RULENAME, - PointerGetDatum(oldname), - 0, 0, 0); + ruletup = SearchSysCacheCopy(RULERELNAME, + ObjectIdGetDatum(owningRel), + PointerGetDatum(oldName), + 0, 0); if (!HeapTupleIsValid(ruletup)) - elog(ERROR, "RenameRewriteRule: rule \"%s\" does not exist", oldname); + elog(ERROR, "RenameRewriteRule: rule \"%s\" does not exist", oldName); /* should not already exist */ - if (IsDefinedRewriteRule(newname)) + if (IsDefinedRewriteRule(owningRel, newName)) elog(ERROR, "Attempt to rename rule \"%s\" failed: \"%s\" already exists", - oldname, newname); + oldName, newName); - StrNCpy(NameStr(((Form_pg_rewrite) GETSTRUCT(ruletup))->rulename), - newname, NAMEDATALEN); + namestrcpy(&(((Form_pg_rewrite) GETSTRUCT(ruletup))->rulename), newName); simple_heap_update(pg_rewrite_desc, &ruletup->t_self, ruletup); diff --git a/src/backend/rewrite/rewriteRemove.c b/src/backend/rewrite/rewriteRemove.c index da8f1b8e54..df85fa504a 100644 --- a/src/backend/rewrite/rewriteRemove.c +++ b/src/backend/rewrite/rewriteRemove.c @@ -8,15 +8,16 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteRemove.c,v 1.47 2002/03/29 19:06:13 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteRemove.c,v 1.48 2002/04/18 20:01:09 tgl Exp $ * *------------------------------------------------------------------------- */ #include "postgres.h" -#include "utils/builtins.h" +#include "access/genam.h" #include "access/heapam.h" #include "catalog/catname.h" +#include "catalog/indexing.h" #include "catalog/pg_rewrite.h" #include "commands/comment.h" #include "miscadmin.h" @@ -30,12 +31,11 @@ /* * RemoveRewriteRule * - * Delete a rule given its (possibly qualified) rulename. + * Delete a rule given its name. */ void -RemoveRewriteRule(List *names) +RemoveRewriteRule(Oid owningRel, const char *ruleName) { - char *ruleName; Relation RewriteRelation; Relation event_relation; HeapTuple tuple; @@ -44,13 +44,6 @@ RemoveRewriteRule(List *names) bool hasMoreRules; int32 aclcheck_result; - /* - * XXX temporary until rules become schema-tized - */ - if (length(names) != 1) - elog(ERROR, "Qualified rule names not supported yet"); - ruleName = strVal(lfirst(names)); - /* * Open the pg_rewrite relation. */ @@ -59,9 +52,10 @@ RemoveRewriteRule(List *names) /* * Find the tuple for the target rule. */ - tuple = SearchSysCacheCopy(RULENAME, + tuple = SearchSysCacheCopy(RULERELNAME, + ObjectIdGetDatum(owningRel), PointerGetDatum(ruleName), - 0, 0, 0); + 0, 0); /* * complain if no rule with such name existed @@ -75,6 +69,7 @@ RemoveRewriteRule(List *names) */ ruleId = tuple->t_data->t_oid; eventRelationOid = ((Form_pg_rewrite) GETSTRUCT(tuple))->ev_class; + Assert(eventRelationOid == owningRel); /* * We had better grab AccessExclusiveLock so that we know no other @@ -137,10 +132,10 @@ RemoveRewriteRule(List *names) void RelationRemoveRules(Oid relid) { - Relation RewriteRelation = NULL; - HeapScanDesc scanDesc = NULL; + Relation RewriteRelation; + SysScanDesc scanDesc; ScanKeyData scanKeyData; - HeapTuple tuple = NULL; + HeapTuple tuple; /* * Open the pg_rewrite relation. @@ -148,18 +143,21 @@ RelationRemoveRules(Oid relid) RewriteRelation = heap_openr(RewriteRelationName, RowExclusiveLock); /* - * Scan the RuleRelation ('pg_rewrite') for all the tuples that has - * the same ev_class as relid (the relation to be removed). + * Scan pg_rewrite for all the tuples that have the same ev_class + * as relid (the relation to be removed). */ ScanKeyEntryInitialize(&scanKeyData, 0, Anum_pg_rewrite_ev_class, F_OIDEQ, ObjectIdGetDatum(relid)); - scanDesc = heap_beginscan(RewriteRelation, - 0, SnapshotNow, 1, &scanKeyData); - while (HeapTupleIsValid(tuple = heap_getnext(scanDesc, 0))) + scanDesc = systable_beginscan(RewriteRelation, + RewriteRelRulenameIndex, + true, SnapshotNow, + 1, &scanKeyData); + + while (HeapTupleIsValid(tuple = systable_getnext(scanDesc))) { /* Delete any comments associated with this rule */ DeleteComments(tuple->t_data->t_oid, RelationGetRelid(RewriteRelation)); @@ -167,6 +165,7 @@ RelationRemoveRules(Oid relid) simple_heap_delete(RewriteRelation, &tuple->t_self); } - heap_endscan(scanDesc); + systable_endscan(scanDesc); + heap_close(RewriteRelation, RowExclusiveLock); } diff --git a/src/backend/rewrite/rewriteSupport.c b/src/backend/rewrite/rewriteSupport.c index bc2f04932a..62a951aaf6 100644 --- a/src/backend/rewrite/rewriteSupport.c +++ b/src/backend/rewrite/rewriteSupport.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteSupport.c,v 1.49 2001/08/12 21:35:19 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteSupport.c,v 1.50 2002/04/18 20:01:09 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -29,11 +29,12 @@ * Is there a rule by the given name? */ bool -IsDefinedRewriteRule(const char *ruleName) +IsDefinedRewriteRule(Oid owningRel, const char *ruleName) { - return SearchSysCacheExists(RULENAME, + return SearchSysCacheExists(RULERELNAME, + ObjectIdGetDatum(owningRel), PointerGetDatum(ruleName), - 0, 0, 0); + 0, 0); } /* diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index bef1b8064c..d8c2065258 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.260 2002/03/24 04:31:07 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.261 2002/04/18 20:01:09 tgl Exp $ * * NOTES * this is the "main" module of the postgres backend and @@ -1688,7 +1688,7 @@ PostgresMain(int argc, char *argv[], const char *username) if (!IsUnderPostmaster) { puts("\nPOSTGRES backend interactive interface "); - puts("$Revision: 1.260 $ $Date: 2002/03/24 04:31:07 $\n"); + puts("$Revision: 1.261 $ $Date: 2002/04/18 20:01:09 $\n"); } /* @@ -2322,7 +2322,7 @@ CreateCommandTag(Node *parsetree) tag = "CREATE"; break; - case T_DropTrigStmt: + case T_DropPropertyStmt: tag = "DROP"; break; diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index 63e6b5dd9b..24a1e3d296 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.149 2002/04/15 05:22:04 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.150 2002/04/18 20:01:09 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -312,11 +312,6 @@ ProcessUtility(Node *parsetree, RemoveIndex(rel); break; - case DROP_RULE: - /* RemoveRewriteRule checks permissions */ - RemoveRewriteRule(names); - break; - case DROP_TYPE: /* RemoveType does its own permissions checks */ RemoveType(names); @@ -714,12 +709,24 @@ ProcessUtility(Node *parsetree, CreateTrigger((CreateTrigStmt *) parsetree); break; - case T_DropTrigStmt: + case T_DropPropertyStmt: { - DropTrigStmt *stmt = (DropTrigStmt *) parsetree; + DropPropertyStmt *stmt = (DropPropertyStmt *) parsetree; + Oid relId; - DropTrigger(RangeVarGetRelid(stmt->relation, false), - stmt->trigname); + relId = RangeVarGetRelid(stmt->relation, false); + + switch (stmt->removeType) + { + case DROP_RULE: + /* RemoveRewriteRule checks permissions */ + RemoveRewriteRule(relId, stmt->property); + break; + case DROP_TRIGGER: + /* DropTrigger checks permissions */ + DropTrigger(relId, stmt->property); + break; + } } break; diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index 501d5a2095..5207488405 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -3,7 +3,7 @@ * back to source text * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.96 2002/04/11 20:00:04 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.97 2002/04/18 20:01:09 tgl Exp $ * * This software is copyrighted by Jan Wieck - Hamburg. * @@ -42,6 +42,7 @@ #include "catalog/heap.h" #include "catalog/index.h" +#include "catalog/namespace.h" #include "catalog/pg_index.h" #include "catalog/pg_opclass.h" #include "catalog/pg_operator.h" @@ -97,11 +98,10 @@ typedef struct * Global data * ---------- */ -static char *rulename = NULL; -static void *plan_getrule = NULL; -static char *query_getrule = "SELECT * FROM pg_rewrite WHERE rulename = $1"; -static void *plan_getview = NULL; -static char *query_getview = "SELECT * FROM pg_rewrite WHERE rulename = $1"; +static void *plan_getrulebyoid = NULL; +static char *query_getrulebyoid = "SELECT * FROM pg_rewrite WHERE oid = $1"; +static void *plan_getviewrule = NULL; +static char *query_getviewrule = "SELECT * FROM pg_rewrite WHERE ev_class = $1 AND rulename = $2"; /* ---------- @@ -112,6 +112,7 @@ static char *query_getview = "SELECT * FROM pg_rewrite WHERE rulename = $1"; * as a parameter, and append their text output to its contents. * ---------- */ +static text *pg_do_getviewdef(Oid viewoid); static void make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc); static void make_viewdef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc); static void get_query_def(Query *query, StringInfo buf, List *parentnamespace); @@ -156,21 +157,16 @@ static char *get_relid_attribute_name(Oid relid, AttrNumber attnum); Datum pg_get_ruledef(PG_FUNCTION_ARGS) { - Name rname = PG_GETARG_NAME(0); + Oid ruleoid = PG_GETARG_OID(0); text *ruledef; Datum args[1]; - char nulls[2]; + char nulls[1]; int spirc; HeapTuple ruletup; TupleDesc rulettc; StringInfoData buf; int len; - /* - * We need the rules name somewhere deep down: rulename is global - */ - rulename = pstrdup(NameStr(*rname)); - /* * Connect to SPI manager */ @@ -182,27 +178,26 @@ pg_get_ruledef(PG_FUNCTION_ARGS) * pg_rewrite over the SPI manager instead of using the syscache to be * checked for read access on pg_rewrite. */ - if (plan_getrule == NULL) + if (plan_getrulebyoid == NULL) { Oid argtypes[1]; void *plan; - argtypes[0] = NAMEOID; - plan = SPI_prepare(query_getrule, 1, argtypes); + argtypes[0] = OIDOID; + plan = SPI_prepare(query_getrulebyoid, 1, argtypes); if (plan == NULL) - elog(ERROR, "SPI_prepare() failed for \"%s\"", query_getrule); - plan_getrule = SPI_saveplan(plan); + elog(ERROR, "SPI_prepare() failed for \"%s\"", query_getrulebyoid); + plan_getrulebyoid = SPI_saveplan(plan); } /* * Get the pg_rewrite tuple for this rule */ - args[0] = PointerGetDatum(rulename); - nulls[0] = (rulename == NULL) ? 'n' : ' '; - nulls[1] = '\0'; - spirc = SPI_execp(plan_getrule, args, nulls, 1); + args[0] = ObjectIdGetDatum(ruleoid); + nulls[0] = ' '; + spirc = SPI_execp(plan_getrulebyoid, args, nulls, 1); if (spirc != SPI_OK_SELECT) - elog(ERROR, "failed to get pg_rewrite tuple for %s", rulename); + elog(ERROR, "failed to get pg_rewrite tuple for %u", ruleoid); if (SPI_processed != 1) { if (SPI_finish() != SPI_OK_FINISH) @@ -248,22 +243,48 @@ pg_get_ruledef(PG_FUNCTION_ARGS) Datum pg_get_viewdef(PG_FUNCTION_ARGS) { - Name vname = PG_GETARG_NAME(0); + /* By OID */ + Oid viewoid = PG_GETARG_OID(0); text *ruledef; - Datum args[1]; - char nulls[1]; + + ruledef = pg_do_getviewdef(viewoid); + PG_RETURN_TEXT_P(ruledef); +} + +Datum +pg_get_viewdef_name(PG_FUNCTION_ARGS) +{ + /* By qualified name */ + text *viewname = PG_GETARG_TEXT_P(0); + RangeVar *viewrel; + Oid viewoid; + text *ruledef; + + viewrel = makeRangeVarFromNameList(textToQualifiedNameList(viewname, + "get_viewdef")); + viewoid = RangeVarGetRelid(viewrel, false); + + ruledef = pg_do_getviewdef(viewoid); + PG_RETURN_TEXT_P(ruledef); +} + +/* + * Common code for by-OID and by-name variants of pg_get_viewdef + */ +static text * +pg_do_getviewdef(Oid viewoid) +{ + text *ruledef; + Datum args[2]; + char nulls[2]; int spirc; HeapTuple ruletup; TupleDesc rulettc; StringInfoData buf; int len; + char *viewname; char *name; - /* - * We need the view name somewhere deep down - */ - rulename = pstrdup(NameStr(*vname)); - /* * Connect to SPI manager */ @@ -275,28 +296,31 @@ pg_get_viewdef(PG_FUNCTION_ARGS) * pg_rewrite over the SPI manager instead of using the syscache to be * checked for read access on pg_rewrite. */ - if (plan_getview == NULL) + if (plan_getviewrule == NULL) { - Oid argtypes[1]; + Oid argtypes[2]; void *plan; - argtypes[0] = NAMEOID; - plan = SPI_prepare(query_getview, 1, argtypes); + argtypes[0] = OIDOID; + argtypes[1] = NAMEOID; + plan = SPI_prepare(query_getviewrule, 2, argtypes); if (plan == NULL) - elog(ERROR, "SPI_prepare() failed for \"%s\"", query_getview); - plan_getview = SPI_saveplan(plan); + elog(ERROR, "SPI_prepare() failed for \"%s\"", query_getviewrule); + plan_getviewrule = SPI_saveplan(plan); } /* - * Get the pg_rewrite tuple for this rule: rulename is actually - * viewname here + * Get the pg_rewrite tuple for the view's SELECT rule */ - name = MakeRetrieveViewRuleName(rulename); - args[0] = PointerGetDatum(name); + viewname = get_rel_name(viewoid); + name = MakeRetrieveViewRuleName(viewname); + args[0] = ObjectIdGetDatum(viewoid); + args[1] = PointerGetDatum(name); nulls[0] = ' '; - spirc = SPI_execp(plan_getview, args, nulls, 1); + nulls[1] = ' '; + spirc = SPI_execp(plan_getviewrule, args, nulls, 2); if (spirc != SPI_OK_SELECT) - elog(ERROR, "failed to get pg_rewrite tuple for view %s", rulename); + elog(ERROR, "failed to get pg_rewrite tuple for view %s", viewname); initStringInfo(&buf); if (SPI_processed != 1) appendStringInfo(&buf, "Not a view"); @@ -322,10 +346,7 @@ pg_get_viewdef(PG_FUNCTION_ARGS) if (SPI_finish() != SPI_OK_FINISH) elog(ERROR, "get_viewdef: SPI_finish() failed"); - /* - * Easy - isn't it? - */ - PG_RETURN_TEXT_P(ruledef); + return ruledef; } @@ -633,8 +654,6 @@ deparse_expression(Node *expr, List *dpcontext, bool forceprefix) context.namespaces = dpcontext; context.varprefix = forceprefix; - rulename = ""; /* in case of errors */ - get_rule_expr(expr, &context); return buf.data; @@ -792,6 +811,7 @@ deparse_context_for_subplan(const char *name, List *tlist, static void make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc) { + char *rulename; char ev_type; Oid ev_class; int2 ev_attr; @@ -800,23 +820,38 @@ make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc) char *ev_action; List *actions = NIL; int fno; + Datum dat; bool isnull; /* * Get the attribute values from the rules tuple */ + fno = SPI_fnumber(rulettc, "rulename"); + dat = SPI_getbinval(ruletup, rulettc, fno, &isnull); + Assert(!isnull); + rulename = NameStr(*(DatumGetName(dat))); + fno = SPI_fnumber(rulettc, "ev_type"); - ev_type = (char) SPI_getbinval(ruletup, rulettc, fno, &isnull); + dat = SPI_getbinval(ruletup, rulettc, fno, &isnull); + Assert(!isnull); + ev_type = DatumGetChar(dat); fno = SPI_fnumber(rulettc, "ev_class"); - ev_class = (Oid) SPI_getbinval(ruletup, rulettc, fno, &isnull); + dat = SPI_getbinval(ruletup, rulettc, fno, &isnull); + Assert(!isnull); + ev_class = DatumGetObjectId(dat); fno = SPI_fnumber(rulettc, "ev_attr"); - ev_attr = (int2) SPI_getbinval(ruletup, rulettc, fno, &isnull); + dat = SPI_getbinval(ruletup, rulettc, fno, &isnull); + Assert(!isnull); + ev_attr = DatumGetInt16(dat); fno = SPI_fnumber(rulettc, "is_instead"); - is_instead = (bool) SPI_getbinval(ruletup, rulettc, fno, &isnull); + dat = SPI_getbinval(ruletup, rulettc, fno, &isnull); + Assert(!isnull); + is_instead = DatumGetBool(dat); + /* these could be nulls */ fno = SPI_fnumber(rulettc, "ev_qual"); ev_qual = SPI_getvalue(ruletup, rulettc, fno); @@ -1051,8 +1086,8 @@ get_query_def(Query *query, StringInfo buf, List *parentnamespace) break; default: - elog(ERROR, "get_ruledef of %s: query command type %d not implemented yet", - rulename, query->commandType); + elog(ERROR, "get_query_def: unknown query command type %d", + query->commandType); break; } } @@ -1901,9 +1936,7 @@ get_rule_expr(Node *node, deparse_context *context) break; default: - printf("\n%s\n", nodeToString(node)); - elog(ERROR, "get_ruledef of %s: unknown node type %d in get_rule_expr()", - rulename, nodeTag(node)); + elog(ERROR, "get_rule_expr: unknown node type %d", nodeTag(node)); break; } } diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index 9a8e76f492..686fcc8416 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.160 2002/04/12 20:38:29 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.161 2002/04/18 20:01:09 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -675,17 +675,18 @@ RelationBuildRuleLock(Relation relation) /* * open pg_rewrite and begin a scan - * - * XXX: there is no suitable index for this scan. FIXME. */ pg_rewrite_desc = heap_openr(RewriteRelationName, AccessShareLock); pg_rewrite_tupdesc = RelationGetDescr(pg_rewrite_desc); - pg_rewrite_scan = systable_beginscan(pg_rewrite_desc, NULL, false, + pg_rewrite_scan = systable_beginscan(pg_rewrite_desc, + RewriteRelRulenameIndex, + criticalRelcachesBuilt, SnapshotNow, 1, &key); while (HeapTupleIsValid(pg_rewrite_tuple = systable_getnext(pg_rewrite_scan))) { + Form_pg_rewrite rewrite_form = (Form_pg_rewrite) GETSTRUCT(pg_rewrite_tuple); bool isnull; Datum ruleaction; Datum rule_evqual; @@ -698,18 +699,11 @@ RelationBuildRuleLock(Relation relation) rule->ruleId = pg_rewrite_tuple->t_data->t_oid; - rule->event = DatumGetInt32(heap_getattr(pg_rewrite_tuple, - Anum_pg_rewrite_ev_type, - pg_rewrite_tupdesc, - &isnull)) - 48; - rule->attrno = DatumGetInt16(heap_getattr(pg_rewrite_tuple, - Anum_pg_rewrite_ev_attr, - pg_rewrite_tupdesc, - &isnull)); - rule->isInstead = DatumGetBool(heap_getattr(pg_rewrite_tuple, - Anum_pg_rewrite_is_instead, - pg_rewrite_tupdesc, - &isnull)); + rule->event = rewrite_form->ev_type - '0'; + rule->attrno = rewrite_form->ev_attr; + rule->isInstead = rewrite_form->is_instead; + + /* Must use heap_getattr to fetch ev_qual and ev_action */ ruleaction = heap_getattr(pg_rewrite_tuple, Anum_pg_rewrite_ev_action, diff --git a/src/backend/utils/cache/syscache.c b/src/backend/utils/cache/syscache.c index 5deea86089..03acac91b0 100644 --- a/src/backend/utils/cache/syscache.c +++ b/src/backend/utils/cache/syscache.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.78 2002/04/17 20:57:56 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.79 2002/04/18 20:01:10 tgl Exp $ * * NOTES * These routines allow the parser/planner/executor to perform @@ -333,14 +333,14 @@ static const struct cachedesc cacheinfo[] = { 0, 0 }}, - {RewriteRelationName, /* RULENAME */ - RewriteRulenameIndex, + {RewriteRelationName, /* RULERELNAME */ + RewriteRelRulenameIndex, Anum_pg_rewrite_ev_class, - 1, + 2, { + Anum_pg_rewrite_ev_class, Anum_pg_rewrite_rulename, 0, - 0, 0 }}, {ShadowRelationName, /* SHADOWNAME */ diff --git a/src/bin/initdb/initdb.sh b/src/bin/initdb/initdb.sh index 03fa12a846..efacbe6c31 100644 --- a/src/bin/initdb/initdb.sh +++ b/src/bin/initdb/initdb.sh @@ -27,7 +27,7 @@ # Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # -# $Header: /cvsroot/pgsql/src/bin/initdb/Attic/initdb.sh,v 1.148 2002/04/15 22:33:21 tgl Exp $ +# $Header: /cvsroot/pgsql/src/bin/initdb/Attic/initdb.sh,v 1.149 2002/04/18 20:01:10 tgl Exp $ # #------------------------------------------------------------------------- @@ -689,19 +689,21 @@ CREATE VIEW pg_user AS \ CREATE VIEW pg_rules AS \ SELECT \ + N.nspname AS schemaname, \ C.relname AS tablename, \ R.rulename AS rulename, \ - pg_get_ruledef(R.rulename) AS definition \ - FROM pg_rewrite R, pg_class C \ - WHERE R.rulename !~ '^_RET' \ - AND C.oid = R.ev_class; + 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 !~ '^_RET'; CREATE VIEW pg_views AS \ SELECT \ + N.nspname AS schemaname, \ C.relname AS viewname, \ pg_get_userbyid(C.relowner) AS viewowner, \ - pg_get_viewdef(C.relname) AS definition \ - FROM pg_class C \ + pg_get_viewdef(C.oid) AS definition \ + FROM pg_class C LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace) \ WHERE C.relkind = 'v'; -- XXX why does pg_tables include sequences? diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index f1cf4854f5..2c5d14e5f8 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -22,7 +22,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.248 2002/04/13 19:57:18 momjian Exp $ + * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.249 2002/04/18 20:01:10 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -2274,17 +2274,28 @@ getTables(int *numTables, FuncInfo *finfo, int numFuncs, const char *tablename) PGresult *res2; resetPQExpBuffer(query); - appendPQExpBuffer(query, "SELECT definition as viewdef, "); - /* - * XXX 7.2 - replace with att from pg_views or some other - * generic source - */ - appendPQExpBuffer(query, "(select oid from pg_rewrite where " - " rulename=('_RET' || viewname)::name) as view_oid" - " from pg_views where viewname = "); - formatStringLiteral(query, tblinfo[i].relname, CONV_ALL); - appendPQExpBuffer(query, ";"); + if (g_fout->remoteVersion < 70300) + { + appendPQExpBuffer(query, "SELECT definition as viewdef, " + "(select oid from pg_rewrite where " + " rulename=('_RET' || viewname)::name) as view_oid" + " from pg_views where viewname = "); + formatStringLiteral(query, tblinfo[i].relname, CONV_ALL); + appendPQExpBuffer(query, ";"); + } + else + { + /* Beginning in 7.3, viewname is not unique; use OID */ + appendPQExpBuffer(query, "SELECT pg_get_viewdef(ev_class) as viewdef, " + "oid as view_oid" + " from pg_rewrite where" + " ev_class = '%s'::oid and" + " rulename = ('_RET' || ", + tblinfo[i].oid); + formatStringLiteral(query, tblinfo[i].relname, CONV_ALL); + appendPQExpBuffer(query, ")::name;"); + } res2 = PQexec(g_conn, query->data); if (!res2 || PQresultStatus(res2) != PGRES_TUPLES_OK) @@ -4995,23 +5006,41 @@ dumpRules(Archive *fout, const char *tablename, continue; /* - * Get all rules defined for this table We include pg_rules in the - * cross since it filters out all view rules (pjw 15-Sep-2000). - * - * XXXX: Use LOJ here + * Get all rules defined for this table */ resetPQExpBuffer(query); - appendPQExpBuffer(query, "SELECT definition," - " (select usename from pg_user where pg_class.relowner = usesysid) AS viewowner, " - " pg_rewrite.oid, pg_rewrite.rulename " - "FROM pg_rewrite, pg_class, pg_rules " - "WHERE pg_class.relname = "); - formatStringLiteral(query, tblinfo[t].relname, CONV_ALL); - appendPQExpBuffer(query, - " AND pg_rewrite.ev_class = pg_class.oid " - " AND pg_rules.tablename = pg_class.relname " - " AND pg_rules.rulename = pg_rewrite.rulename " - "ORDER BY pg_rewrite.oid"); + + if (g_fout->remoteVersion < 70300) + { + /* + * We include pg_rules in the cross since it filters out all view + * rules (pjw 15-Sep-2000). + */ + appendPQExpBuffer(query, "SELECT definition," + " (select usename from pg_user where pg_class.relowner = usesysid) AS viewowner, " + " pg_rewrite.oid, pg_rewrite.rulename " + "FROM pg_rewrite, pg_class, pg_rules " + "WHERE pg_class.relname = "); + formatStringLiteral(query, tblinfo[t].relname, CONV_ALL); + appendPQExpBuffer(query, + " AND pg_rewrite.ev_class = pg_class.oid " + " AND pg_rules.tablename = pg_class.relname " + " AND pg_rules.rulename = pg_rewrite.rulename " + "ORDER BY pg_rewrite.oid"); + } + else + { + appendPQExpBuffer(query, "SELECT pg_get_ruledef(pg_rewrite.oid) AS definition," + " (select usename from pg_user where pg_class.relowner = usesysid) AS viewowner, " + " pg_rewrite.oid, pg_rewrite.rulename " + "FROM pg_rewrite, pg_class " + "WHERE pg_class.oid = '%s'::oid " + " AND pg_rewrite.ev_class = pg_class.oid " + " AND pg_rewrite.rulename !~ '^_RET' " + "ORDER BY pg_rewrite.oid", + tblinfo[t].oid); + } + res = PQexec(g_conn, query->data); if (!res || PQresultStatus(res) != PGRES_TUPLES_OK) @@ -5041,6 +5070,7 @@ dumpRules(Archive *fout, const char *tablename, resetPQExpBuffer(query); appendPQExpBuffer(query, "RULE %s", fmtId(PQgetvalue(res, i, i_rulename), force_quotes)); + appendPQExpBuffer(query, " ON %s", fmtId(tblinfo[t].relname, force_quotes)); dumpComment(fout, query->data, PQgetvalue(res, i, i_oid), "pg_rewrite", 0, NULL); diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index 492c3e9b3f..4d6742fdbd 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -37,7 +37,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: catversion.h,v 1.117 2002/04/17 20:57:56 tgl Exp $ + * $Id: catversion.h,v 1.118 2002/04/18 20:01:10 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 200204171 +#define CATALOG_VERSION_NO 200204181 #endif diff --git a/src/include/catalog/indexing.h b/src/include/catalog/indexing.h index b2b3f1f39c..e08e3aa8e9 100644 --- a/src/include/catalog/indexing.h +++ b/src/include/catalog/indexing.h @@ -8,7 +8,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: indexing.h,v 1.64 2002/04/17 20:57:56 tgl Exp $ + * $Id: indexing.h,v 1.65 2002/04/18 20:01:10 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -80,7 +80,7 @@ #define ProcedureOidIndex "pg_proc_oid_index" #define RelCheckIndex "pg_relcheck_rcrelid_index" #define RewriteOidIndex "pg_rewrite_oid_index" -#define RewriteRulenameIndex "pg_rewrite_rulename_index" +#define RewriteRelRulenameIndex "pg_rewrite_rel_rulename_index" #define ShadowNameIndex "pg_shadow_usename_index" #define ShadowSysidIndex "pg_shadow_usesysid_index" #define StatisticRelidAttnumIndex "pg_statistic_relid_att_index" @@ -178,7 +178,7 @@ DECLARE_UNIQUE_INDEX(pg_proc_proname_args_nsp_index on pg_proc using btree(prona /* This following index is not used for a cache and is not unique */ DECLARE_INDEX(pg_relcheck_rcrelid_index on pg_relcheck using btree(rcrelid oid_ops)); DECLARE_UNIQUE_INDEX(pg_rewrite_oid_index on pg_rewrite using btree(oid oid_ops)); -DECLARE_UNIQUE_INDEX(pg_rewrite_rulename_index on pg_rewrite using btree(rulename name_ops)); +DECLARE_UNIQUE_INDEX(pg_rewrite_rel_rulename_index on pg_rewrite using btree(ev_class oid_ops, rulename name_ops)); DECLARE_UNIQUE_INDEX(pg_shadow_usename_index on pg_shadow using btree(usename name_ops)); DECLARE_UNIQUE_INDEX(pg_shadow_usesysid_index on pg_shadow using btree(usesysid int4_ops)); DECLARE_UNIQUE_INDEX(pg_statistic_relid_att_index on pg_statistic using btree(starelid oid_ops, staattnum int2_ops)); diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index a7f77f1f7d..f8863d9340 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: pg_proc.h,v 1.227 2002/04/11 20:00:12 tgl Exp $ + * $Id: pg_proc.h,v 1.228 2002/04/18 20:01:10 tgl Exp $ * * NOTES * The script catalog/genbki.sh reads this file and generates .bki @@ -2150,9 +2150,11 @@ DATA(insert OID = 1639 ( oidge PGNSP PGUID 12 f t f t f i 2 16 "26 26" 10 DESCR("greater-than-or-equal"); /* System-view support functions */ -DATA(insert OID = 1640 ( pg_get_ruledef PGNSP PGUID 12 f t f t f s 1 25 "19" 100 0 0 100 pg_get_ruledef - _null_ )); +DATA(insert OID = 1573 ( pg_get_ruledef PGNSP PGUID 12 f t f t f s 1 25 "26" 100 0 0 100 pg_get_ruledef - _null_ )); DESCR("source text of a rule"); -DATA(insert OID = 1641 ( pg_get_viewdef PGNSP PGUID 12 f t f t f s 1 25 "19" 100 0 0 100 pg_get_viewdef - _null_ )); +DATA(insert OID = 1640 ( pg_get_viewdef PGNSP PGUID 12 f t f t f s 1 25 "25" 100 0 0 100 pg_get_viewdef_name - _null_ )); +DESCR("select statement of a view"); +DATA(insert OID = 1641 ( pg_get_viewdef PGNSP PGUID 12 f t f t f s 1 25 "26" 100 0 0 100 pg_get_viewdef - _null_ )); DESCR("select statement of a view"); DATA(insert OID = 1642 ( pg_get_userbyid PGNSP PGUID 12 f t f t f s 1 19 "23" 100 0 0 100 pg_get_userbyid - _null_ )); DESCR("user name by UID (with fallback)"); diff --git a/src/include/catalog/pg_rewrite.h b/src/include/catalog/pg_rewrite.h index 46b73bc083..00b0eb2974 100644 --- a/src/include/catalog/pg_rewrite.h +++ b/src/include/catalog/pg_rewrite.h @@ -4,11 +4,14 @@ * definition of the system "rewrite-rule" relation (pg_rewrite) * along with the relation's initial contents. * + * As of Postgres 7.3, the primary key for this table is + * --- ie, rule names are only unique among the rules of a given table. + * * * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: pg_rewrite.h,v 1.17 2001/11/05 17:46:32 momjian Exp $ + * $Id: pg_rewrite.h,v 1.18 2002/04/18 20:01:11 tgl Exp $ * * NOTES * the genbki.sh script reads this file and generates .bki @@ -34,9 +37,9 @@ CATALOG(pg_rewrite) { NameData rulename; - char ev_type; Oid ev_class; int2 ev_attr; + char ev_type; bool is_instead; /* NB: remaining fields must be accessed via heap_getattr */ @@ -57,9 +60,9 @@ typedef FormData_pg_rewrite *Form_pg_rewrite; */ #define Natts_pg_rewrite 7 #define Anum_pg_rewrite_rulename 1 -#define Anum_pg_rewrite_ev_type 2 -#define Anum_pg_rewrite_ev_class 3 -#define Anum_pg_rewrite_ev_attr 4 +#define Anum_pg_rewrite_ev_class 2 +#define Anum_pg_rewrite_ev_attr 3 +#define Anum_pg_rewrite_ev_type 4 #define Anum_pg_rewrite_is_instead 5 #define Anum_pg_rewrite_ev_qual 6 #define Anum_pg_rewrite_ev_action 7 diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h index ff03eb1228..1664e76900 100644 --- a/src/include/nodes/nodes.h +++ b/src/include/nodes/nodes.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: nodes.h,v 1.104 2002/04/05 11:56:54 momjian Exp $ + * $Id: nodes.h,v 1.105 2002/04/18 20:01:11 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -181,7 +181,7 @@ typedef enum NodeTag T_VariableShowStmt, T_VariableResetStmt, T_CreateTrigStmt, - T_DropTrigStmt, + T_DropPropertyStmt, T_CreatePLangStmt, T_DropPLangStmt, T_CreateUserStmt, diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index ba9ed9aa8d..dc2eabb5b2 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: parsenodes.h,v 1.171 2002/04/17 20:57:57 tgl Exp $ + * $Id: parsenodes.h,v 1.172 2002/04/18 20:01:11 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -940,13 +940,6 @@ typedef struct CreateTrigStmt RangeVar *constrrel; /* opposite relation */ } CreateTrigStmt; -typedef struct DropTrigStmt -{ - NodeTag type; - char *trigname; /* TRIGGER' name */ - RangeVar *relation; /* triggered relation */ -} DropTrigStmt; - /* ---------------------- * Create/Drop PROCEDURAL LANGUAGE Statement * ---------------------- @@ -1060,7 +1053,7 @@ typedef struct CreateDomainStmt } CreateDomainStmt; /* ---------------------- - * Drop Table|Sequence|View|Index|Rule|Type Statement + * Drop Table|Sequence|View|Index|Type|Domain Statement * ---------------------- */ @@ -1068,9 +1061,8 @@ typedef struct CreateDomainStmt #define DROP_SEQUENCE 2 #define DROP_VIEW 3 #define DROP_INDEX 4 -#define DROP_RULE 5 -#define DROP_TYPE 6 -#define DROP_DOMAIN 7 +#define DROP_TYPE 5 +#define DROP_DOMAIN 6 typedef struct DropStmt { @@ -1080,6 +1072,25 @@ typedef struct DropStmt int behavior; /* CASCADE or RESTRICT drop behavior */ } DropStmt; +/* ---------------------- + * Drop Rule|Trigger Statement + * + * In general this may be used for dropping any property of a relation; + * for example, someday soon we may have DROP ATTRIBUTE. + * ---------------------- + */ + +#define DROP_RULE 100 +#define DROP_TRIGGER 101 + +typedef struct DropPropertyStmt +{ + NodeTag type; + RangeVar *relation; /* owning relation */ + char *property; /* name of rule, trigger, etc */ + int removeType; +} DropPropertyStmt; + /* ---------------------- * Truncate Table Statement * ---------------------- diff --git a/src/include/rewrite/rewriteDefine.h b/src/include/rewrite/rewriteDefine.h index a9f7792a61..4bf20a2ca7 100644 --- a/src/include/rewrite/rewriteDefine.h +++ b/src/include/rewrite/rewriteDefine.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: rewriteDefine.h,v 1.13 2001/11/05 17:46:35 momjian Exp $ + * $Id: rewriteDefine.h,v 1.14 2002/04/18 20:01:11 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -18,6 +18,7 @@ extern void DefineQueryRewrite(RuleStmt *args); -extern void RenameRewriteRule(char *oldname, char *newname); +extern void RenameRewriteRule(Oid owningRel, const char *oldName, + const char *newName); #endif /* REWRITEDEFINE_H */ diff --git a/src/include/rewrite/rewriteRemove.h b/src/include/rewrite/rewriteRemove.h index ac79e6c919..3aa4cbdf53 100644 --- a/src/include/rewrite/rewriteRemove.h +++ b/src/include/rewrite/rewriteRemove.h @@ -7,14 +7,14 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: rewriteRemove.h,v 1.12 2002/03/29 19:06:26 tgl Exp $ + * $Id: rewriteRemove.h,v 1.13 2002/04/18 20:01:11 tgl Exp $ * *------------------------------------------------------------------------- */ #ifndef REWRITEREMOVE_H #define REWRITEREMOVE_H -extern void RemoveRewriteRule(List *names); +extern void RemoveRewriteRule(Oid owningRel, const char *ruleName); extern void RelationRemoveRules(Oid relid); #endif /* REWRITEREMOVE_H */ diff --git a/src/include/rewrite/rewriteSupport.h b/src/include/rewrite/rewriteSupport.h index 6f955d6eea..7453dd9958 100644 --- a/src/include/rewrite/rewriteSupport.h +++ b/src/include/rewrite/rewriteSupport.h @@ -7,14 +7,14 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: rewriteSupport.h,v 1.20 2001/11/05 17:46:35 momjian Exp $ + * $Id: rewriteSupport.h,v 1.21 2002/04/18 20:01:11 tgl Exp $ * *------------------------------------------------------------------------- */ #ifndef REWRITESUPPORT_H #define REWRITESUPPORT_H -extern bool IsDefinedRewriteRule(const char *ruleName); +extern bool IsDefinedRewriteRule(Oid owningRel, const char *ruleName); extern char *MakeRetrieveViewRuleName(const char *view_name); diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h index b38f4429cb..caa2c57102 100644 --- a/src/include/utils/builtins.h +++ b/src/include/utils/builtins.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: builtins.h,v 1.176 2002/04/11 20:00:17 tgl Exp $ + * $Id: builtins.h,v 1.177 2002/04/18 20:01:11 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -337,6 +337,7 @@ extern Datum regproctooid(PG_FUNCTION_ARGS); /* ruleutils.c */ extern Datum pg_get_ruledef(PG_FUNCTION_ARGS); extern Datum pg_get_viewdef(PG_FUNCTION_ARGS); +extern Datum pg_get_viewdef_name(PG_FUNCTION_ARGS); extern Datum pg_get_indexdef(PG_FUNCTION_ARGS); extern Datum pg_get_userbyid(PG_FUNCTION_ARGS); extern Datum pg_get_expr(PG_FUNCTION_ARGS); diff --git a/src/include/utils/syscache.h b/src/include/utils/syscache.h index dbe50b37be..a5282a9753 100644 --- a/src/include/utils/syscache.h +++ b/src/include/utils/syscache.h @@ -9,7 +9,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: syscache.h,v 1.46 2002/04/17 20:57:57 tgl Exp $ + * $Id: syscache.h,v 1.47 2002/04/18 20:01:11 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -52,7 +52,7 @@ #define PROCOID 21 #define RELNAMENSP 22 #define RELOID 23 -#define RULENAME 24 +#define RULERELNAME 24 #define SHADOWNAME 25 #define SHADOWSYSID 26 #define STATRELATT 27 diff --git a/src/test/regress/expected/errors.out b/src/test/regress/expected/errors.out index 27a7b38dd4..2d90066fc7 100644 --- a/src/test/regress/expected/errors.out +++ b/src/test/regress/expected/errors.out @@ -217,13 +217,13 @@ ERROR: parser: parse error at or near ";" drop rule 314159; ERROR: parser: parse error at or near "314159" -- no such rule -drop rule nonesuch; -ERROR: Rule "nonesuch" not found +drop rule nonesuch on noplace; +ERROR: Relation "noplace" does not exist -- bad keyword drop tuple rule nonesuch; ERROR: parser: parse error at or near "tuple" -- no such rule -drop instance rule nonesuch; +drop instance rule nonesuch on noplace; ERROR: parser: parse error at or near "instance" -- no such rule drop rewrite rule nonesuch; diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out index 8e0d9e3239..75578b76e0 100644 --- a/src/test/regress/expected/rules.out +++ b/src/test/regress/expected/rules.out @@ -648,8 +648,8 @@ select * from rtest_order2; ---+---+------------------------------------- 1 | 1 | rule 2 - this should run 1st 1 | 2 | rule 4 - this should run 2nd - 1 | 3 | rule 3 - this should run 3rd or 4th - 1 | 4 | rule 1 - this should run 3rd or 4th + 1 | 3 | rule 1 - this should run 3rd or 4th + 1 | 4 | rule 3 - this should run 3rd or 4th (4 rows) -- @@ -1173,7 +1173,7 @@ select * from foo; 1001 (1 row) -drop rule foorule; +drop rule foorule on foo; -- this should fail because f1 is not exposed for unqualified reference: create rule foorule as on insert to foo where f1 < 100 do instead insert into foo2 values (f1); @@ -1196,7 +1196,7 @@ select * from foo2; 2 (1 row) -drop rule foorule; +drop rule foorule on foo; drop table foo; drop table foo2; -- @@ -1256,7 +1256,7 @@ select * from cchild; 2 | test2 (2 rows) -drop rule rrule; +drop rule rrule on vview; drop view vview; drop table pparent; drop table cchild; @@ -1268,7 +1268,7 @@ SELECT viewname, definition FROM pg_views ORDER BY viewname; --------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- iexit | SELECT ih.name, ih.thepath, interpt_pp(ih.thepath, r.thepath) AS exit FROM ihighway ih, ramp r WHERE (ih.thepath ## r.thepath); pg_indexes | SELECT c.relname AS tablename, i.relname AS indexname, pg_get_indexdef(x.indexrelid) AS indexdef FROM pg_index x, pg_class c, pg_class i WHERE ((((c.relkind = 'r'::"char") AND (i.relkind = 'i'::"char")) AND (c.oid = x.indrelid)) AND (i.oid = x.indexrelid)); - pg_rules | SELECT c.relname AS tablename, r.rulename, pg_get_ruledef(r.rulename) AS definition FROM pg_rewrite r, pg_class c WHERE ((r.rulename !~ '^_RET'::text) AND (c.oid = r.ev_class)); + 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 !~ '^_RET'::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 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, 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, pg_class i, pg_index x WHERE (((c.relkind = 'r'::"char") AND (x.indrelid = c.oid)) AND (x.indexrelid = i.oid)); pg_stat_all_tables | SELECT c.oid AS relid, 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))) WHERE (c.relkind = 'r'::"char") GROUP BY c.oid, c.relname; @@ -1289,7 +1289,7 @@ SELECT viewname, definition FROM pg_views ORDER BY viewname; pg_stats | SELECT c.relname AS tablename, a.attname, s.stanullfrac AS null_frac, s.stawidth AS avg_width, s.stadistinct AS n_distinct, CASE WHEN (1 = s.stakind1) THEN s.stavalues1 WHEN (1 = s.stakind2) THEN s.stavalues2 WHEN (1 = s.stakind3) THEN s.stavalues3 WHEN (1 = s.stakind4) THEN s.stavalues4 ELSE NULL::"_text" END AS most_common_vals, CASE WHEN (1 = s.stakind1) THEN s.stanumbers1 WHEN (1 = s.stakind2) THEN s.stanumbers2 WHEN (1 = s.stakind3) THEN s.stanumbers3 WHEN (1 = s.stakind4) THEN s.stanumbers4 ELSE NULL::"_float4" END AS most_common_freqs, CASE WHEN (2 = s.stakind1) THEN s.stavalues1 WHEN (2 = s.stakind2) THEN s.stavalues2 WHEN (2 = s.stakind3) THEN s.stavalues3 WHEN (2 = s.stakind4) THEN s.stavalues4 ELSE NULL::"_text" END AS histogram_bounds, CASE WHEN (3 = s.stakind1) THEN s.stanumbers1[1] WHEN (3 = s.stakind2) THEN s.stanumbers2[1] WHEN (3 = s.stakind3) THEN s.stanumbers3[1] WHEN (3 = s.stakind4) THEN s.stanumbers4[1] ELSE NULL::float4 END AS correlation FROM pg_class c, pg_attribute a, pg_statistic s WHERE ((((c.oid = s.starelid) AND (c.oid = a.attrelid)) AND (a.attnum = s.staattnum)) AND has_table_privilege(c.oid, 'select'::text)); pg_tables | SELECT c.relname AS tablename, pg_get_userbyid(c.relowner) AS tableowner, c.relhasindex AS hasindexes, c.relhasrules AS hasrules, (c.reltriggers > 0) AS hastriggers FROM pg_class c WHERE ((c.relkind = 'r'::"char") OR (c.relkind = 's'::"char")); pg_user | SELECT pg_shadow.usename, pg_shadow.usesysid, pg_shadow.usecreatedb, pg_shadow.usetrace, pg_shadow.usesuper, pg_shadow.usecatupd, '********'::text AS passwd, pg_shadow.valuntil, pg_shadow.useconfig FROM pg_shadow; - pg_views | SELECT c.relname AS viewname, pg_get_userbyid(c.relowner) AS viewowner, pg_get_viewdef(c.relname) AS definition FROM pg_class c WHERE (c.relkind = 'v'::"char"); + pg_views | SELECT n.nspname AS schemaname, c.relname AS viewname, pg_get_userbyid(c.relowner) AS viewowner, pg_get_viewdef(c.oid) AS definition FROM (pg_class c LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) WHERE (c.relkind = 'v'::"char"); rtest_v1 | SELECT rtest_t1.a, rtest_t1.b FROM rtest_t1; rtest_vcomp | SELECT x.part, (x.size * y.factor) AS size_in_cm FROM rtest_comp x, rtest_unitfact y WHERE (x.unit = y.unit); rtest_vview1 | SELECT x.a, x.b FROM rtest_view1 x WHERE (0 < (SELECT count(*) AS count FROM rtest_view2 y WHERE (y.a = x.a))); diff --git a/src/test/regress/sql/errors.sql b/src/test/regress/sql/errors.sql index 5ab09d2a12..db041fa9cb 100644 --- a/src/test/regress/sql/errors.sql +++ b/src/test/regress/sql/errors.sql @@ -239,13 +239,13 @@ drop rule; drop rule 314159; -- no such rule -drop rule nonesuch; +drop rule nonesuch on noplace; -- bad keyword drop tuple rule nonesuch; -- no such rule -drop instance rule nonesuch; +drop instance rule nonesuch on noplace; -- no such rule drop rewrite rule nonesuch; diff --git a/src/test/regress/sql/rules.sql b/src/test/regress/sql/rules.sql index 4322cf6cd2..01c202e116 100644 --- a/src/test/regress/sql/rules.sql +++ b/src/test/regress/sql/rules.sql @@ -699,7 +699,7 @@ insert into foo values(1); insert into foo values(1001); select * from foo; -drop rule foorule; +drop rule foorule on foo; -- this should fail because f1 is not exposed for unqualified reference: create rule foorule as on insert to foo where f1 < 100 @@ -714,7 +714,7 @@ insert into foo values(100); select * from foo; select * from foo2; -drop rule foorule; +drop rule foorule on foo; drop table foo; drop table foo2; @@ -751,7 +751,7 @@ update vview set descrip='test3' where pid=3; select * from vview; select * from cchild; -drop rule rrule; +drop rule rrule on vview; drop view vview; drop table pparent; drop table cchild;