mirror of
https://github.com/postgres/postgres.git
synced 2025-06-29 10:41:53 +03:00
Here's a combination of all the patches I'm currently waiting
for against a just updated CVS tree. It contains Partial new rewrite system that handles subselects, view aggregate columns, insert into select from view, updates with set col = view-value and select rules restriction to view definition. Updates for rule/view backparsing utility functions to handle subselects correct. New system views pg_tables and pg_indexes (where you can see the complete index definition in the latter one). Enabling array references on query parameters. Bugfix for functional index. Little changes to system views pg_rules and pg_views. The rule system isn't a release-stopper any longer. But another stopper is that I don't know if the latest changes to PL/pgSQL (not already in CVS) made it compile on AIX. Still wait for some response from Dave. Jan
This commit is contained in:
@ -6,7 +6,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/rewrite/Attic/locks.c,v 1.13 1998/09/01 04:31:30 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/rewrite/Attic/locks.c,v 1.14 1998/10/02 16:27:45 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -24,7 +24,6 @@
|
||||
#include "utils/builtins.h"
|
||||
#include "catalog/pg_shadow.h"
|
||||
|
||||
static void checkLockPerms(List *locks, Query *parsetree, int rt_index);
|
||||
|
||||
/*
|
||||
* ThisLockWasTriggered
|
||||
@ -170,7 +169,7 @@ matchLocks(CmdType event,
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
void
|
||||
checkLockPerms(List *locks, Query *parsetree, int rt_index)
|
||||
{
|
||||
Relation ev_rel;
|
||||
|
@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.21 1998/09/01 04:31:32 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.22 1998/10/02 16:27:46 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -199,11 +199,8 @@ DefineQueryRewrite(RuleStmt *stmt)
|
||||
/* ----------
|
||||
* The current rewrite handler is known to work on relation level
|
||||
* rules only. And for SELECT events, it expects one non-nothing
|
||||
* action that is instead. Since we now hand out views and rules
|
||||
* to regular users, we must deny anything else.
|
||||
*
|
||||
* I know that I must write a new rewrite handler from scratch
|
||||
* for 6.5 so we can remove these checks and allow all the rules.
|
||||
* action that is instead and returns exactly a tuple of the
|
||||
* rewritten relation. This restricts SELECT rules to views.
|
||||
*
|
||||
* Jan
|
||||
* ----------
|
||||
@ -217,6 +214,9 @@ DefineQueryRewrite(RuleStmt *stmt)
|
||||
else
|
||||
eslot_string = NULL;
|
||||
|
||||
/*
|
||||
* No rule actions that modify OLD or NEW
|
||||
*/
|
||||
if (action != NIL)
|
||||
foreach(l, action)
|
||||
{
|
||||
@ -233,23 +233,86 @@ DefineQueryRewrite(RuleStmt *stmt)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Rules ON SELECT are restricted to view definitions
|
||||
*/
|
||||
if (event_type == CMD_SELECT)
|
||||
{
|
||||
TargetEntry *tle;
|
||||
Resdom *resdom;
|
||||
Form_pg_attribute attr;
|
||||
char *attname;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* So there cannot be INSTEAD NOTHING, ...
|
||||
*/
|
||||
if (length(action) == 0)
|
||||
{
|
||||
elog(NOTICE, "instead nothing rules on select currently not supported");
|
||||
elog(ERROR, " use views instead");
|
||||
}
|
||||
|
||||
/*
|
||||
* ... there cannot be multiple actions, ...
|
||||
*/
|
||||
if (length(action) > 1)
|
||||
elog(ERROR, "multiple action rules on select currently not supported");
|
||||
/*
|
||||
* ... the one action must be a SELECT, ...
|
||||
*/
|
||||
query = (Query *) lfirst(action);
|
||||
if (!is_instead || query->commandType != CMD_SELECT)
|
||||
elog(ERROR, "only instead-select rules currently supported on select");
|
||||
if (event_qual != NULL)
|
||||
elog(ERROR, "event qualifications not supported for rules on select");
|
||||
|
||||
/*
|
||||
* ... the targetlist of the SELECT action must
|
||||
* exactly match the event relation ...
|
||||
*/
|
||||
event_relation = heap_openr(event_obj->relname);
|
||||
if (event_relation == NULL)
|
||||
elog(ERROR, "virtual relations not supported yet");
|
||||
|
||||
if (event_relation->rd_att->natts != length(query->targetList))
|
||||
elog(ERROR, "select rules target list must match event relations structure");
|
||||
|
||||
for (i = 1; i <= event_relation->rd_att->natts; i++) {
|
||||
tle = (TargetEntry *)nth(i - 1, query->targetList);
|
||||
resdom = tle->resdom;
|
||||
attr = event_relation->rd_att->attrs[i - 1];
|
||||
attname = nameout(&(attr->attname));
|
||||
|
||||
if (strcmp(resdom->resname, attname) != 0)
|
||||
elog(ERROR, "select rules target entry %d has different column name from %s", i, attname);
|
||||
|
||||
if (attr->atttypid != resdom->restype)
|
||||
elog(ERROR, "select rules target entry %d has different type from attribute %s", i, attname);
|
||||
|
||||
if (attr->atttypmod != resdom->restypmod)
|
||||
elog(ERROR, "select rules target entry %d has different size from attribute %s", i, attname);
|
||||
}
|
||||
|
||||
/*
|
||||
* ... and final there must not be another ON SELECT
|
||||
* rule already.
|
||||
*/
|
||||
if (event_relation->rd_rules != NULL) {
|
||||
for (i = 0; i < event_relation->rd_rules->numLocks; i++) {
|
||||
RewriteRule *rule;
|
||||
|
||||
rule = event_relation->rd_rules->rules[i];
|
||||
if (rule->event == CMD_SELECT)
|
||||
elog(ERROR, "%s is already a view", nameout(&(event_relation->rd_rel->relname)));
|
||||
}
|
||||
}
|
||||
|
||||
heap_close(event_relation);
|
||||
}
|
||||
|
||||
/*
|
||||
* This rule is currently allowed - too restricted I know - but women
|
||||
* and children first Jan
|
||||
* This rule is allowed - install it.
|
||||
*/
|
||||
|
||||
event_relation = heap_openr(event_obj->relname);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -6,7 +6,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteManip.c,v 1.18 1998/09/11 16:39:59 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteManip.c,v 1.19 1998/10/02 16:27:49 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -73,6 +73,23 @@ OffsetVarNodes(Node *node, int offset)
|
||||
OffsetVarNodes((Node *) expr->args, offset);
|
||||
}
|
||||
break;
|
||||
case T_Iter:
|
||||
{
|
||||
Iter *iter = (Iter *) node;
|
||||
|
||||
OffsetVarNodes((Node *) iter->iterexpr, offset);
|
||||
}
|
||||
break;
|
||||
case T_ArrayRef:
|
||||
{
|
||||
ArrayRef *ref = (ArrayRef *) node;
|
||||
|
||||
OffsetVarNodes((Node *) ref->refupperindexpr, offset);
|
||||
OffsetVarNodes((Node *) ref->reflowerindexpr, offset);
|
||||
OffsetVarNodes((Node *) ref->refexpr, offset);
|
||||
OffsetVarNodes((Node *) ref->refassgnexpr, offset);
|
||||
}
|
||||
break;
|
||||
case T_Var:
|
||||
{
|
||||
Var *var = (Var *) node;
|
||||
@ -157,6 +174,23 @@ ChangeVarNodes(Node *node, int old_varno, int new_varno, int sublevels_up)
|
||||
ChangeVarNodes((Node *) expr->args, old_varno, new_varno, sublevels_up);
|
||||
}
|
||||
break;
|
||||
case T_Iter:
|
||||
{
|
||||
Iter *iter = (Iter *) node;
|
||||
|
||||
ChangeVarNodes((Node *) iter->iterexpr, old_varno, new_varno, sublevels_up);
|
||||
}
|
||||
break;
|
||||
case T_ArrayRef:
|
||||
{
|
||||
ArrayRef *ref = (ArrayRef *) node;
|
||||
|
||||
ChangeVarNodes((Node *) ref->refupperindexpr, old_varno, new_varno, sublevels_up);
|
||||
ChangeVarNodes((Node *) ref->reflowerindexpr, old_varno, new_varno, sublevels_up);
|
||||
ChangeVarNodes((Node *) ref->refexpr, old_varno, new_varno, sublevels_up);
|
||||
ChangeVarNodes((Node *) ref->refassgnexpr, old_varno, new_varno, sublevels_up);
|
||||
}
|
||||
break;
|
||||
case T_Var:
|
||||
{
|
||||
Var *var = (Var *) node;
|
||||
@ -353,6 +387,20 @@ ResolveNew(RewriteInfo *info, List *targetlist, Node **nodePtr,
|
||||
ResolveNew(info, targetlist, (Node **) (&(((Expr *) node)->args)),
|
||||
sublevels_up);
|
||||
break;
|
||||
case T_Iter:
|
||||
ResolveNew(info, targetlist, (Node **) (&(((Iter *) node)->iterexpr)),
|
||||
sublevels_up);
|
||||
break;
|
||||
case T_ArrayRef:
|
||||
ResolveNew(info, targetlist, (Node **) (&(((ArrayRef *) node)->refupperindexpr)),
|
||||
sublevels_up);
|
||||
ResolveNew(info, targetlist, (Node **) (&(((ArrayRef *) node)->reflowerindexpr)),
|
||||
sublevels_up);
|
||||
ResolveNew(info, targetlist, (Node **) (&(((ArrayRef *) node)->refexpr)),
|
||||
sublevels_up);
|
||||
ResolveNew(info, targetlist, (Node **) (&(((ArrayRef *) node)->refassgnexpr)),
|
||||
sublevels_up);
|
||||
break;
|
||||
case T_Var:
|
||||
{
|
||||
int this_varno = (int) ((Var *) node)->varno;
|
||||
@ -454,6 +502,38 @@ nodeHandleRIRAttributeRule(Node **nodePtr,
|
||||
sublevels_up);
|
||||
}
|
||||
break;
|
||||
case T_Iter:
|
||||
{
|
||||
Iter *iter = (Iter *) node;
|
||||
|
||||
nodeHandleRIRAttributeRule((Node **) (&(iter->iterexpr)), rtable,
|
||||
targetlist, rt_index, attr_num,
|
||||
modified, badsql,
|
||||
sublevels_up);
|
||||
}
|
||||
break;
|
||||
case T_ArrayRef:
|
||||
{
|
||||
ArrayRef *ref = (ArrayRef *) node;
|
||||
|
||||
nodeHandleRIRAttributeRule((Node **) (&(ref->refupperindexpr)), rtable,
|
||||
targetlist, rt_index, attr_num,
|
||||
modified, badsql,
|
||||
sublevels_up);
|
||||
nodeHandleRIRAttributeRule((Node **) (&(ref->reflowerindexpr)), rtable,
|
||||
targetlist, rt_index, attr_num,
|
||||
modified, badsql,
|
||||
sublevels_up);
|
||||
nodeHandleRIRAttributeRule((Node **) (&(ref->refexpr)), rtable,
|
||||
targetlist, rt_index, attr_num,
|
||||
modified, badsql,
|
||||
sublevels_up);
|
||||
nodeHandleRIRAttributeRule((Node **) (&(ref->refassgnexpr)), rtable,
|
||||
targetlist, rt_index, attr_num,
|
||||
modified, badsql,
|
||||
sublevels_up);
|
||||
}
|
||||
break;
|
||||
case T_Var:
|
||||
{
|
||||
int this_varno = ((Var *) node)->varno;
|
||||
@ -598,6 +678,33 @@ nodeHandleViewRule(Node **nodePtr,
|
||||
rt_index, modified, sublevels_up);
|
||||
}
|
||||
break;
|
||||
case T_Iter:
|
||||
{
|
||||
Iter *iter = (Iter *) node;
|
||||
|
||||
nodeHandleViewRule((Node **) (&(iter->iterexpr)),
|
||||
rtable, targetlist,
|
||||
rt_index, modified, sublevels_up);
|
||||
}
|
||||
break;
|
||||
case T_ArrayRef:
|
||||
{
|
||||
ArrayRef *ref = (ArrayRef *) node;
|
||||
|
||||
nodeHandleViewRule((Node **) (&(ref->refupperindexpr)),
|
||||
rtable, targetlist,
|
||||
rt_index, modified, sublevels_up);
|
||||
nodeHandleViewRule((Node **) (&(ref->reflowerindexpr)),
|
||||
rtable, targetlist,
|
||||
rt_index, modified, sublevels_up);
|
||||
nodeHandleViewRule((Node **) (&(ref->refexpr)),
|
||||
rtable, targetlist,
|
||||
rt_index, modified, sublevels_up);
|
||||
nodeHandleViewRule((Node **) (&(ref->refassgnexpr)),
|
||||
rtable, targetlist,
|
||||
rt_index, modified, sublevels_up);
|
||||
}
|
||||
break;
|
||||
case T_Var:
|
||||
{
|
||||
Var *var = (Var *) node;
|
||||
|
Reference in New Issue
Block a user