diff options
Diffstat (limited to 'src/backend/rewrite')
| -rw-r--r-- | src/backend/rewrite/locks.c | 173 | ||||
| -rw-r--r-- | src/backend/rewrite/rewriteDefine.c | 399 | ||||
| -rw-r--r-- | src/backend/rewrite/rewriteHandler.c | 1066 | ||||
| -rw-r--r-- | src/backend/rewrite/rewriteManip.c | 707 | ||||
| -rw-r--r-- | src/backend/rewrite/rewriteRemove.c | 257 | ||||
| -rw-r--r-- | src/backend/rewrite/rewriteSupport.c | 428 |
6 files changed, 1586 insertions, 1444 deletions
diff --git a/src/backend/rewrite/locks.c b/src/backend/rewrite/locks.c index 3171d2c845..213fae9b32 100644 --- a/src/backend/rewrite/locks.c +++ b/src/backend/rewrite/locks.c @@ -6,7 +6,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/rewrite/Attic/locks.c,v 1.2 1996/11/10 03:01:50 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/rewrite/Attic/locks.c,v 1.3 1997/09/07 04:48:02 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -14,7 +14,7 @@ #include "utils/elog.h" /* for elog */ #include "nodes/pg_list.h" /* lisp support package */ #include "nodes/parsenodes.h" -#include "nodes/primnodes.h" /* Var node def */ +#include "nodes/primnodes.h" /* Var node def */ #include "utils/syscache.h" /* for SearchSysCache */ #include "rewrite/locks.h" /* for rewrite specific lock defns */ @@ -26,106 +26,115 @@ * if we find at least one such match, we return true * otherwise, we return false */ -static bool -nodeThisLockWasTriggered(Node *node, int varno, AttrNumber attnum) +static bool +nodeThisLockWasTriggered(Node * node, int varno, AttrNumber attnum) { - if (node==NULL) - return FALSE; - switch(nodeTag(node)) { - case T_Var: + if (node == NULL) + return FALSE; + switch (nodeTag(node)) { - Var *var = (Var *)node; - if (varno == var->varno && - (attnum == var->varattno || attnum == -1)) - return TRUE; - } - break; - case T_Expr: - { - Expr *expr = (Expr*)node; - return - nodeThisLockWasTriggered((Node*)expr->args, varno, attnum); - } - break; - case T_TargetEntry: - { - TargetEntry *tle = (TargetEntry *)node; - return - nodeThisLockWasTriggered(tle->expr, varno, attnum); - } - break; - case T_List: - { - List *l; + case T_Var: + { + Var *var = (Var *) node; + + if (varno == var->varno && + (attnum == var->varattno || attnum == -1)) + return TRUE; + } + break; + case T_Expr: + { + Expr *expr = (Expr *) node; + + return + nodeThisLockWasTriggered((Node *) expr->args, varno, attnum); + } + break; + case T_TargetEntry: + { + TargetEntry *tle = (TargetEntry *) node; + + return + nodeThisLockWasTriggered(tle->expr, varno, attnum); + } + break; + case T_List: + { + List *l; - foreach(l, (List*)node) { - if (nodeThisLockWasTriggered(lfirst(l), varno, attnum)) - return TRUE; - } - return FALSE; + foreach(l, (List *) node) + { + if (nodeThisLockWasTriggered(lfirst(l), varno, attnum)) + return TRUE; + } + return FALSE; + } + break; + default: + break; } - break; - default: - break; - } - return (FALSE); + return (FALSE); } /* * thisLockWasTriggered - - * walk the tree, if there we find a varnode, we check the varattno - * against the attnum if we find at least one such match, we return true - * otherwise, we return false + * walk the tree, if there we find a varnode, we check the varattno + * against the attnum if we find at least one such match, we return true + * otherwise, we return false */ -static bool +static bool thisLockWasTriggered(int varno, - AttrNumber attnum, - Query *parsetree) + AttrNumber attnum, + Query * parsetree) { - return + return (nodeThisLockWasTriggered(parsetree->qual, varno, attnum) || - nodeThisLockWasTriggered((Node*)parsetree->targetList, - varno, attnum)); + nodeThisLockWasTriggered((Node *) parsetree->targetList, + varno, attnum)); } /* * matchLocks - - * match the list of locks and returns the matching rules + * match the list of locks and returns the matching rules */ -List * +List * matchLocks(CmdType event, - RuleLock *rulelocks, - int varno, - Query *parsetree) + RuleLock * rulelocks, + int varno, + Query * parsetree) { - List *real_locks = NIL; - int nlocks; - int i; - - Assert(rulelocks != NULL); /* we get called iff there is some lock */ - Assert(parsetree != NULL); - - if (parsetree->commandType != CMD_SELECT) { - if (parsetree->resultRelation != varno) { - return ( NULL ); + List *real_locks = NIL; + int nlocks; + int i; + + Assert(rulelocks != NULL); /* we get called iff there is some lock */ + Assert(parsetree != NULL); + + if (parsetree->commandType != CMD_SELECT) + { + if (parsetree->resultRelation != varno) + { + return (NULL); + } } - } - - nlocks = rulelocks->numLocks; - - for (i = 0; i < nlocks; i++) { - RewriteRule *oneLock = rulelocks->rules[i]; - if (oneLock->event == event) { - if (parsetree->commandType != CMD_SELECT || - thisLockWasTriggered(varno, - oneLock->attrno, - parsetree)) { - real_locks = lappend(real_locks, oneLock); - } + nlocks = rulelocks->numLocks; + + for (i = 0; i < nlocks; i++) + { + RewriteRule *oneLock = rulelocks->rules[i]; + + if (oneLock->event == event) + { + if (parsetree->commandType != CMD_SELECT || + thisLockWasTriggered(varno, + oneLock->attrno, + parsetree)) + { + real_locks = lappend(real_locks, oneLock); + } + } } - } - - return (real_locks); -} + return (real_locks); +} diff --git a/src/backend/rewrite/rewriteDefine.c b/src/backend/rewrite/rewriteDefine.c index a9383fe53d..01b05c4cd0 100644 --- a/src/backend/rewrite/rewriteDefine.c +++ b/src/backend/rewrite/rewriteDefine.c @@ -1,13 +1,13 @@ /*------------------------------------------------------------------------- * * rewriteDefine.c-- - * routines for defining a rewrite rule + * routines for defining a rewrite rule * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.3 1997/07/24 20:13:33 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.4 1997/09/07 04:48:05 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -20,235 +20,252 @@ #include "utils/builtins.h" #include "utils/elog.h" /* for elog */ #include "utils/palloc.h" -#include "utils/lsyscache.h" /* for get_typlen */ +#include "utils/lsyscache.h" /* for get_typlen */ #include "nodes/pg_list.h" /* for Lisp support */ #include "nodes/parsenodes.h" #include "parser/catalog_utils.h" -#include "rewrite/locks.h" +#include "rewrite/locks.h" #include "rewrite/rewriteDefine.h" #include "rewrite/rewriteRemove.h" #include "rewrite/rewriteSupport.h" #include "tcop/tcopprot.h" -Oid LastOidProcessed = InvalidOid; +Oid LastOidProcessed = InvalidOid; /* * This is too small for many rule plans, but it'll have to do for now. * Rule plans, etc will eventually have to be large objects. - * + * * should this be smaller? */ -#define RULE_PLAN_SIZE 8192 +#define RULE_PLAN_SIZE 8192 static void strcpyq(char *dest, char *source) { - char *current=source,*destp= dest; - - for(current=source; *current; current++) { - if (*current == '\"') { - *destp = '\\'; - destp++; + char *current = source, + *destp = dest; + + for (current = source; *current; current++) + { + if (*current == '\"') + { + *destp = '\\'; + destp++; + } + *destp = *current; + destp++; } - *destp = *current; - destp++; - } - *destp = '\0'; + *destp = '\0'; } /* * InsertRule - - * takes the arguments and inserts them as attributes into the system - * relation "pg_rewrite" + * takes the arguments and inserts them as attributes into the system + * relation "pg_rewrite" * - * MODS : changes the value of LastOidProcessed as a side - * effect of inserting the rule tuple + * MODS : changes the value of LastOidProcessed as a side + * effect of inserting the rule tuple * - * ARGS : rulname - name of the rule - * evtype - one of RETRIEVE,REPLACE,DELETE,APPEND - * evobj - name of relation - * evslot - comma delimited list of slots - * if null => multi-attr rule - * evinstead - is an instead rule - * actiontree - parsetree(s) of rule action + * ARGS : rulname - name of the rule + * evtype - one of RETRIEVE,REPLACE,DELETE,APPEND + * evobj - name of relation + * evslot - comma delimited list of slots + * if null => multi-attr rule + * evinstead - is an instead rule + * actiontree - parsetree(s) of rule action */ -static Oid +static Oid InsertRule(char *rulname, - int evtype, - char *evobj, - char *evslot, - char *evqual, - bool evinstead, - char *actiontree) + int evtype, + char *evobj, + char *evslot, + char *evqual, + bool evinstead, + char *actiontree) { - static char rulebuf[RULE_PLAN_SIZE]; - static char actionbuf[RULE_PLAN_SIZE]; - static char qualbuf[RULE_PLAN_SIZE]; - Oid eventrel_oid = InvalidOid; - AttrNumber evslot_index = InvalidAttrNumber; - Relation eventrel = NULL; - char *is_instead = "f"; - extern void eval_as_new_xact(); - char *template; - - eventrel = heap_openr(evobj); - if (eventrel == NULL) { - elog(WARN, "rules cannot be defined on relations not in schema"); - } - eventrel_oid = RelationGetRelationId(eventrel); - - /* - * if the slotname is null, we know that this is a multi-attr - * rule - */ - if (evslot == NULL) - evslot_index = -1; - else - evslot_index = varattno(eventrel, (char*)evslot); - heap_close(eventrel); - - if (evinstead) - is_instead = "t"; - - if (evqual == NULL) - evqual = "nil"; - - if (IsDefinedRewriteRule(rulname)) - elog(WARN, "Attempt to insert rule '%s' failed: already exists", - rulname); - strcpyq(actionbuf,actiontree); - strcpyq(qualbuf, evqual); - - template = "INSERT INTO pg_rewrite \ + static char rulebuf[RULE_PLAN_SIZE]; + static char actionbuf[RULE_PLAN_SIZE]; + static char qualbuf[RULE_PLAN_SIZE]; + Oid eventrel_oid = InvalidOid; + AttrNumber evslot_index = InvalidAttrNumber; + Relation eventrel = NULL; + char *is_instead = "f"; + extern void eval_as_new_xact(); + char *template; + + eventrel = heap_openr(evobj); + if (eventrel == NULL) + { + elog(WARN, "rules cannot be defined on relations not in schema"); + } + eventrel_oid = RelationGetRelationId(eventrel); + + /* + * if the slotname is null, we know that this is a multi-attr rule + */ + if (evslot == NULL) + evslot_index = -1; + else + evslot_index = varattno(eventrel, (char *) evslot); + heap_close(eventrel); + + if (evinstead) + is_instead = "t"; + + if (evqual == NULL) + evqual = "nil"; + + if (IsDefinedRewriteRule(rulname)) + elog(WARN, "Attempt to insert rule '%s' failed: already exists", + rulname); + strcpyq(actionbuf, actiontree); + strcpyq(qualbuf, evqual); + + template = "INSERT INTO pg_rewrite \ (rulename, ev_type, ev_class, ev_attr, action, ev_qual, is_instead) VALUES \ ('%s', %d::char, %d::oid, %d::int2, '%s'::text, '%s'::text, \ '%s'::bool);"; - if (strlen(template) + strlen(rulname) + strlen(actionbuf) + - strlen(qualbuf) + 20 /* fudge fac */ > RULE_PLAN_SIZE) { - elog(WARN, "DefineQueryRewrite: rule plan string too big."); - } - sprintf(rulebuf, template, - rulname, evtype, eventrel_oid, evslot_index, actionbuf, - qualbuf, is_instead); - - pg_eval(rulebuf, (char **) NULL, (Oid *) NULL, 0); - - return (LastOidProcessed); + if (strlen(template) + strlen(rulname) + strlen(actionbuf) + + strlen(qualbuf) + 20 /* fudge fac */ > RULE_PLAN_SIZE) + { + elog(WARN, "DefineQueryRewrite: rule plan string too big."); + } + sprintf(rulebuf, template, + rulname, evtype, eventrel_oid, evslot_index, actionbuf, + qualbuf, is_instead); + + pg_eval(rulebuf, (char **) NULL, (Oid *) NULL, 0); + + return (LastOidProcessed); } /* - * for now, event_object must be a single attribute + * for now, event_object must be a single attribute */ static void ValidateRule(int event_type, - char *eobj_string, - char *eslot_string, - Node *event_qual, - List **action, - int is_instead, - Oid event_attype) + char *eobj_string, + char *eslot_string, + Node * event_qual, + List ** action, + int is_instead, + Oid event_attype) { - if (((event_type == CMD_INSERT) || (event_type == CMD_DELETE)) && - eslot_string) { - elog(WARN, - "rules not allowed for insert or delete events to an attribute"); - } - - if (event_qual && !*action && is_instead) - elog(WARN, - "event_quals on 'instead nothing' rules not currently supported"); - -#if 0 - /* on retrieve to class.attribute do instead nothing is converted - * to 'on retrieve to class.attribute do instead - * retrieve (attribute = NULL)' - * --- this is also a terrible hack that works well -- glass*/ - if (is_instead && !*action && eslot_string && event_type == CMD_SELECT) { - char *temp_buffer = (char *) palloc(strlen(template)+80); - sprintf(temp_buffer, template, event_attype, - get_typlen(event_attype), eslot_string, - event_attype); - - *action = (List*) stringToNode(temp_buffer); - - pfree(temp_buffer); - } -#endif + if (((event_type == CMD_INSERT) || (event_type == CMD_DELETE)) && + eslot_string) + { + elog(WARN, + "rules not allowed for insert or delete events to an attribute"); + } + + if (event_qual && !*action && is_instead) + elog(WARN, + "event_quals on 'instead nothing' rules not currently supported"); + +#if 0 + + /* + * on retrieve to class.attribute do instead nothing is converted to + * 'on retrieve to class.attribute do instead retrieve (attribute = + * NULL)' --- this is also a terrible hack that works well -- glass + */ + if (is_instead && !*action && eslot_string && event_type == CMD_SELECT) + { + char *temp_buffer = (char *) palloc(strlen(template) + 80); + + sprintf(temp_buffer, template, event_attype, + get_typlen(event_attype), eslot_string, + event_attype); + + *action = (List *) stringToNode(temp_buffer); + + pfree(temp_buffer); + } +#endif } void -DefineQueryRewrite(RuleStmt *stmt) +DefineQueryRewrite(RuleStmt * stmt) { - CmdType event_type = stmt->event; - Attr *event_obj = stmt->object; - Node *event_qual = stmt->whereClause; - bool is_instead = stmt->instead; - List *action = stmt->actions; - Relation event_relation = NULL ; - Oid ruleId; - Oid ev_relid = 0; - char *eslot_string = NULL; - int event_attno = 0; - Oid event_attype = 0; - char *actionP, *event_qualP; - - if (event_obj->attrs) - eslot_string = strVal(lfirst(event_obj->attrs)); - else - eslot_string = NULL; - - event_relation = heap_openr(event_obj->relname); - if ( event_relation == NULL ) { - elog(WARN, "virtual relations not supported yet"); - } - ev_relid = RelationGetRelationId(event_relation); - - if (eslot_string == NULL) { - event_attno = -1; - event_attype = -1; /* XXX - don't care */ - } else { - event_attno = varattno(event_relation, eslot_string); - event_attype = att_typeid(event_relation,event_attno); - } - heap_close(event_relation); - - /* fix bug about instead nothing */ - ValidateRule(event_type, event_obj->relname, - eslot_string, event_qual, &action, - is_instead,event_attype); - - if (action == NULL) { - if (!is_instead) return; /* doesn't do anything */ - - event_qualP = nodeToString(event_qual); - - ruleId = InsertRule(stmt->rulename, - event_type, - event_obj->relname, - eslot_string, - event_qualP, - true, - "nil"); - prs2_addToRelation(ev_relid, ruleId, event_type, event_attno, TRUE, - event_qual, NIL); - - } else { - event_qualP = nodeToString(event_qual); - actionP = nodeToString(action); - - ruleId = InsertRule(stmt->rulename, - event_type, - event_obj->relname, - eslot_string, - event_qualP, - is_instead, - actionP); - - /* what is the max size of type text? XXX -- glass */ - if (length(action) > 15 ) - elog(WARN,"max # of actions exceeded"); - prs2_addToRelation(ev_relid, ruleId, event_type, event_attno, - is_instead, event_qual, action); - } -} + CmdType event_type = stmt->event; + Attr *event_obj = stmt->object; + Node *event_qual = stmt->whereClause; + bool is_instead = stmt->instead; + List *action = stmt->actions; + Relation event_relation = NULL; + Oid ruleId; + Oid ev_relid = 0; + char *eslot_string = NULL; + int event_attno = 0; + Oid event_attype = 0; + char *actionP, + *event_qualP; + + if (event_obj->attrs) + eslot_string = strVal(lfirst(event_obj->attrs)); + else + eslot_string = NULL; + + event_relation = heap_openr(event_obj->relname); + if (event_relation == NULL) + { + elog(WARN, "virtual relations not supported yet"); + } + ev_relid = RelationGetRelationId(event_relation); + + if (eslot_string == NULL) + { + event_attno = -1; + event_attype = -1; /* XXX - don't care */ + } + else + { + event_attno = varattno(event_relation, eslot_string); + event_attype = att_typeid(event_relation, event_attno); + } + heap_close(event_relation); + /* fix bug about instead nothing */ + ValidateRule(event_type, event_obj->relname, + eslot_string, event_qual, &action, + is_instead, event_attype); + + if (action == NULL) + { + if (!is_instead) + return; /* doesn't do anything */ + + event_qualP = nodeToString(event_qual); + + ruleId = InsertRule(stmt->rulename, + event_type, + event_obj->relname, + eslot_string, + event_qualP, + true, + "nil"); + prs2_addToRelation(ev_relid, ruleId, event_type, event_attno, TRUE, + event_qual, NIL); + + } + else + { + event_qualP = nodeToString(event_qual); + actionP = nodeToString(action); + + ruleId = InsertRule(stmt->rulename, + event_type, + event_obj->relname, + eslot_string, + event_qualP, + is_instead, + actionP); + + /* what is the max size of type text? XXX -- glass */ + if (length(action) > 15) + elog(WARN, "max # of actions exceeded"); + prs2_addToRelation(ev_relid, ruleId, event_type, event_attno, + is_instead, event_qual, action); + } +} diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c index 093451655d..980956a480 100644 --- a/src/backend/rewrite/rewriteHandler.c +++ b/src/backend/rewrite/rewriteHandler.c @@ -6,7 +6,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.3 1997/08/12 22:53:41 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.4 1997/09/07 04:48:07 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -15,13 +15,13 @@ #include "utils/palloc.h" #include "utils/elog.h" #include "utils/rel.h" -#include "nodes/pg_list.h" +#include "nodes/pg_list.h" #include "nodes/primnodes.h" -#include "parser/parsetree.h" /* for parsetree manipulation */ +#include "parser/parsetree.h" /* for parsetree manipulation */ #include "nodes/parsenodes.h" -#include "rewrite/rewriteSupport.h" +#include "rewrite/rewriteSupport.h" #include "rewrite/rewriteHandler.h" #include "rewrite/rewriteManip.h" #include "rewrite/locks.h" @@ -29,529 +29,580 @@ #include "commands/creatinh.h" #include "access/heapam.h" -static void ApplyRetrieveRule(Query *parsetree, RewriteRule *rule, - int rt_index, int relation_level, int *modified); -static List *fireRules(Query *parsetree, int rt_index, CmdType event, - bool *instead_flag, List *locks, List **qual_products); -static List *deepRewriteQuery(Query *parsetree); +static void +ApplyRetrieveRule(Query * parsetree, RewriteRule * rule, + int rt_index, int relation_level, int *modified); +static List * +fireRules(Query * parsetree, int rt_index, CmdType event, + bool * instead_flag, List * locks, List ** qual_products); +static List *deepRewriteQuery(Query * parsetree); /* * gatherRewriteMeta - - * Gather meta information about parsetree, and rule. Fix rule body - * and qualifier so that they can be mixed with the parsetree and - * maintain semantic validity + * Gather meta information about parsetree, and rule. Fix rule body + * and qualifier so that they can be mixed with the parsetree and + * maintain semantic validity */ static RewriteInfo * -gatherRewriteMeta(Query *parsetree, - Query *rule_action, - Node *rule_qual, - int rt_index, - CmdType event, - bool *instead_flag) +gatherRewriteMeta(Query * parsetree, + Query * rule_action, + Node * rule_qual, + int rt_index, + CmdType event, + bool * instead_flag) { - RewriteInfo *info; - int rt_length; - int result_reln; - - info = (RewriteInfo *) palloc(sizeof(RewriteInfo)); - info->rt_index = rt_index; - info->event = event; - info->instead_flag = *instead_flag; - info->rule_action = (Query*)copyObject(rule_action); - info->rule_qual = (Node*)copyObject(rule_qual); - if (info->rule_action == NULL) info->nothing = TRUE; - else { - info->nothing = FALSE; - info->action = info->rule_action->commandType; - info->current_varno = rt_index; - info->rt = parsetree->rtable; - rt_length = length(info->rt); - info->rt = append(info->rt, info->rule_action->rtable); - - info->new_varno = PRS2_NEW_VARNO + rt_length; - OffsetVarNodes(info->rule_action->qual, rt_length); - OffsetVarNodes((Node*)info->rule_action->targetList, rt_length); - OffsetVarNodes(info->rule_qual, rt_length); - ChangeVarNodes((Node*)info->rule_action->qual, - PRS2_CURRENT_VARNO+rt_length, rt_index); - ChangeVarNodes((Node*)info->rule_action->targetList, - PRS2_CURRENT_VARNO+rt_length, rt_index); - ChangeVarNodes(info->rule_qual, - PRS2_CURRENT_VARNO+rt_length, rt_index); - - /* - * bug here about replace CURRENT -- sort of - * replace current is deprecated now so this code shouldn't really - * need to be so clutzy but..... - */ - if (info->action != CMD_SELECT) { /* i.e update XXXXX */ - int new_result_reln = 0; - result_reln = info->rule_action->resultRelation; - switch (result_reln) { - case PRS2_CURRENT_VARNO: new_result_reln = rt_index; - break; - case PRS2_NEW_VARNO: /* XXX */ - default: - new_result_reln = result_reln + rt_length; - break; - } - info->rule_action->resultRelation = new_result_reln; - } - } - return info; + RewriteInfo *info; + int rt_length; + int result_reln; + + info = (RewriteInfo *) palloc(sizeof(RewriteInfo)); + info->rt_index = rt_index; + info->event = event; + info->instead_flag = *instead_flag; + info->rule_action = (Query *) copyObject(rule_action); + info->rule_qual = (Node *) copyObject(rule_qual); + if (info->rule_action == NULL) + info->nothing = TRUE; + else + { + info->nothing = FALSE; + info->action = info->rule_action->commandType; + info->current_varno = rt_index; + info->rt = parsetree->rtable; + rt_length = length(info->rt); + info->rt = append(info->rt, info->rule_action->rtable); + + info->new_varno = PRS2_NEW_VARNO + rt_length; + OffsetVarNodes(info->rule_action->qual, rt_length); + OffsetVarNodes((Node *) info->rule_action->targetList, rt_length); + OffsetVarNodes(info->rule_qual, rt_length); + ChangeVarNodes((Node *) info->rule_action->qual, + PRS2_CURRENT_VARNO + rt_length, rt_index); + ChangeVarNodes((Node *) info->rule_action->targetList, + PRS2_CURRENT_VARNO + rt_length, rt_index); + ChangeVarNodes(info->rule_qual, + PRS2_CURRENT_VARNO + rt_length, rt_index); + + /* + * bug here about replace CURRENT -- sort of replace current is + * deprecated now so this code shouldn't really need to be so + * clutzy but..... + */ + if (info->action != CMD_SELECT) + { /* i.e update XXXXX */ + int new_result_reln = 0; + + result_reln = info->rule_action->resultRelation; + switch (result_reln) + { + case PRS2_CURRENT_VARNO: + new_result_reln = rt_index; + break; + case PRS2_NEW_VARNO: /* XXX */ + default: + new_result_reln = result_reln + rt_length; + break; + } + info->rule_action->resultRelation = new_result_reln; + } + } + return info; } -static List * -OptimizeRIRRules(List *locks) +static List * +OptimizeRIRRules(List * locks) { - List *attr_level = NIL, *i; - List *relation_level = NIL; - - foreach (i, locks) { - RewriteRule *rule_lock = lfirst(i); - - if (rule_lock->attrno == -1) - relation_level = lappend(relation_level, rule_lock); - else - attr_level = lappend(attr_level, rule_lock); - } - return nconc(relation_level, attr_level); + List *attr_level = NIL, + *i; + List *relation_level = NIL; + + foreach(i, locks) + { + RewriteRule *rule_lock = lfirst(i); + + if (rule_lock->attrno == -1) + relation_level = lappend(relation_level, rule_lock); + else + attr_level = lappend(attr_level, rule_lock); + } + return nconc(relation_level, attr_level); } /* * idea is to put instead rules before regular rules so that * excess semantically queasy queries aren't processed */ -static List * -orderRules(List *locks) +static List * +orderRules(List * locks) { - List *regular = NIL, *i; - List *instead_rules = NIL; - - foreach (i, locks) { - RewriteRule *rule_lock = (RewriteRule *)lfirst(i); - - if (rule_lock->isInstead) - instead_rules = lappend(instead_rules, rule_lock); - else - regular = lappend(regular, rule_lock); - } - return nconc(regular, instead_rules); + List *regular = NIL, + *i; + List *instead_rules = NIL; + + foreach(i, locks) + { + RewriteRule *rule_lock = (RewriteRule *) lfirst(i); + + if (rule_lock->isInstead) + instead_rules = lappend(instead_rules, rule_lock); + else + regular = lappend(regular, rule_lock); + } + return nconc(regular, instead_rules); } static int -AllRetrieve(List *actions) +AllRetrieve(List * actions) { - List *n; - - foreach(n, actions) { - Query *pt = lfirst(n); - - /* - * in the old postgres code, we check whether command_type is - * a consp of '('*'.commandType). but we've never supported transitive - * closures. Hence removed - ay 10/94. - */ - if (pt->commandType != CMD_SELECT) - return false; - } - return true; + List *n; + + foreach(n, actions) + { + Query *pt = lfirst(n); + + /* + * in the old postgres code, we check whether command_type is a + * consp of '('*'.commandType). but we've never supported + * transitive closures. Hence removed - ay 10/94. + */ + if (pt->commandType != CMD_SELECT) + return false; + } + return true; } -static List * -FireRetrieveRulesAtQuery(Query *parsetree, - int rt_index, - Relation relation, - bool *instead_flag, - int rule_flag) +static List * +FireRetrieveRulesAtQuery(Query * parsetree, + int rt_index, + Relation relation, + bool * instead_flag, + int rule_flag) { - List *i, *locks; - RuleLock *rt_entry_locks = NULL; - List *work = NIL; + List *i, + *locks; + RuleLock *rt_entry_locks = NULL; + List *work = NIL; - if ((rt_entry_locks = relation->rd_rules) == NULL) - return NIL; - - locks = matchLocks(CMD_SELECT, rt_entry_locks, rt_index, parsetree); - - /* find all retrieve instead */ - foreach (i, locks) { - RewriteRule *rule_lock = (RewriteRule *)lfirst(i); - - if (!rule_lock->isInstead) - continue; - work = lappend(work, rule_lock); - } - if (work != NIL) { - work = OptimizeRIRRules(locks); - foreach (i, work) { - RewriteRule *rule_lock = lfirst(i); - int relation_level; - int modified = FALSE; - - relation_level = (rule_lock->attrno == -1); - if (rule_lock->actions == NIL) { - *instead_flag = TRUE; + if ((rt_entry_locks = relation->rd_rules) == NULL) return NIL; - } - if (!rule_flag && - length(rule_lock->actions) >= 2 && - AllRetrieve(rule_lock->actions)) { - *instead_flag = TRUE; - return rule_lock->actions; - } - ApplyRetrieveRule(parsetree, rule_lock, rt_index, relation_level, - &modified); - if (modified) { - *instead_flag = TRUE; - FixResdomTypes(parsetree->targetList); - return lcons(parsetree,NIL); - } + + locks = matchLocks(CMD_SELECT, rt_entry_locks, rt_index, parsetree); + + /* find all retrieve instead */ + foreach(i, locks) + { + RewriteRule *rule_lock = (RewriteRule *) lfirst(i); + + if (!rule_lock->isInstead) + continue; + work = lappend(work, rule_lock); + } + if (work != NIL) + { + work = OptimizeRIRRules(locks); + foreach(i, work) + { + RewriteRule *rule_lock = lfirst(i); + int relation_level; + int modified = FALSE; + + relation_level = (rule_lock->attrno == -1); + if (rule_lock->actions == NIL) + { + *instead_flag = TRUE; + return NIL; + } + if (!rule_flag && + length(rule_lock->actions) >= 2 && + AllRetrieve(rule_lock->actions)) + { + *instead_flag = TRUE; + return rule_lock->actions; + } + ApplyRetrieveRule(parsetree, rule_lock, rt_index, relation_level, + &modified); + if (modified) + { + *instead_flag = TRUE; + FixResdomTypes(parsetree->targetList); + return lcons(parsetree, NIL); + } + } } - } - return NIL; -} + return NIL; +} /* Idea is like this: * * retrieve-instead-retrieve rules have different semantics than update nodes - * Separate RIR rules from others. Pass others to FireRules. + * Separate RIR rules from others. Pass others to FireRules. * Order RIR rules and process. * * side effect: parsetree's rtable field might be changed */ static void -ApplyRetrieveRule(Query *parsetree, - RewriteRule *rule, - int rt_index, - int relation_level, - int *modified) +ApplyRetrieveRule(Query * parsetree, + RewriteRule * rule, + int rt_index, + int relation_level, + int *modified) { - Query *rule_action = NULL; - Node *rule_qual; - List *rtable, *rt; - int nothing, rt_length; - int badsql= FALSE; - - rule_qual = rule->qual; - if (rule->actions) { - if (length(rule->actions) > 1) /* ??? because we don't handle rules - with more than one action? -ay */ - return; - rule_action = copyObject(lfirst(rule->actions)); - nothing = FALSE; - } else { - nothing = TRUE; - } - - rtable = copyObject(parsetree->rtable); - foreach (rt, rtable) { - RangeTblEntry *rte = lfirst(rt); - /* - * this is to prevent add_missing_vars_to_base_rels() from - * adding a bogus entry to the new target list. - */ - rte->inFromCl = false; - } - rt_length = length(rtable); - rtable = nconc(rtable, copyObject(rule_action->rtable)); - parsetree->rtable = rtable; - - rule_action->rtable = rtable; - OffsetVarNodes(rule_action->qual, rt_length); - OffsetVarNodes((Node*)rule_action->targetList, rt_length); - OffsetVarNodes(rule_qual, rt_length); - ChangeVarNodes(rule_action->qual, - PRS2_CURRENT_VARNO+rt_length, rt_index); - ChangeVarNodes((Node*)rule_action->targetList, - PRS2_CURRENT_VARNO+rt_length, rt_index); - ChangeVarNodes(rule_qual, PRS2_CURRENT_VARNO+rt_length, rt_index); - if (relation_level) { - HandleViewRule(parsetree, rtable, rule_action->targetList, rt_index, - modified); - } else { - HandleRIRAttributeRule(parsetree, rtable, rule_action->targetList, - rt_index, rule->attrno, modified, &badsql); - } - if (*modified && !badsql) - AddQual(parsetree, rule_action->qual); + Query *rule_action = NULL; + Node *rule_qual; + List *rtable, + *rt; + int nothing, + rt_length; + int badsql = FALSE; + + rule_qual = rule->qual; + if (rule->actions) + { + if (length(rule->actions) > 1) /* ??? because we don't handle + * rules with more than one + * action? -ay */ + return; + rule_action = copyObject(lfirst(rule->actions)); + nothing = FALSE; + } + else + { + nothing = TRUE; + } + + rtable = copyObject(parsetree->rtable); + foreach(rt, rtable) + { + RangeTblEntry *rte = lfirst(rt); + + /* + * this is to prevent add_missing_vars_to_base_rels() from adding + * a bogus entry to the new target list. + */ + rte->inFromCl = false; + } + rt_length = length(rtable); + rtable = nconc(rtable, copyObject(rule_action->rtable)); + parsetree->rtable = rtable; + + rule_action->rtable = rtable; + OffsetVarNodes(rule_action->qual, rt_length); + OffsetVarNodes((Node *) rule_action->targetList, rt_length); + OffsetVarNodes(rule_qual, rt_length); + ChangeVarNodes(rule_action->qual, + PRS2_CURRENT_VARNO + rt_length, rt_index); + ChangeVarNodes((Node *) rule_action->targetList, + PRS2_CURRENT_VARNO + rt_length, rt_index); + ChangeVarNodes(rule_qual, PRS2_CURRENT_VARNO + rt_length, rt_index); + if (relation_level) + { + HandleViewRule(parsetree, rtable, rule_action->targetList, rt_index, + modified); + } + else + { + HandleRIRAttributeRule(parsetree, rtable, rule_action->targetList, + rt_index, rule->attrno, modified, &badsql); + } + if (*modified && !badsql) + AddQual(parsetree, rule_action->qual); } -static List * -ProcessRetrieveQuery(Query *parsetree, - List *rtable, - bool *instead_flag, - bool rule) +static List * +ProcessRetrieveQuery(Query * parsetree, + List * rtable, + bool * instead_flag, + bool rule) { - List *rt; - List *product_queries = NIL; - int rt_index = 0; - - foreach (rt, rtable) { - RangeTblEntry *rt_entry = lfirst(rt); - Relation rt_entry_relation = NULL; - List *result = NIL; - - rt_index++; - rt_entry_relation = heap_openr(rt_entry->relname); - - if (rt_entry_relation->rd_rules != NULL) { - result = - FireRetrieveRulesAtQuery(parsetree, - rt_index, - rt_entry_relation, - instead_flag, - rule); + List *rt; + List *product_queries = NIL; + int rt_index = 0; + + foreach(rt, rtable) + { + RangeTblEntry *rt_entry = lfirst(rt); + Relation rt_entry_relation = NULL; + List *result = NIL; + + rt_index++; + rt_entry_relation = heap_openr(rt_entry->relname); + + if (rt_entry_relation->rd_rules != NULL) + { + result = + FireRetrieveRulesAtQuery(parsetree, + rt_index, + rt_entry_relation, + instead_flag, + rule); + } + heap_close(rt_entry_relation); + if (*instead_flag) + return result; } - heap_close(rt_entry_relation); - if (*instead_flag) - return result; - } - if (rule) - return NIL; + if (rule) + return NIL; - foreach (rt, rtable) { - RangeTblEntry *rt_entry = lfirst(rt); - Relation rt_entry_relation = NULL; - RuleLock *rt_entry_locks = NULL; - List *result = NIL; - List *locks = NIL; - List *dummy_products; - - rt_index++; - rt_entry_relation = heap_openr(rt_entry->relname); - rt_entry_locks = rt_entry_relation->rd_rules; - heap_close(rt_entry_relation); - - if (rt_entry_locks) { - locks = - matchLocks(CMD_SELECT, rt_entry_locks, rt_index, parsetree); + foreach(rt, rtable) + { + RangeTblEntry *rt_entry = lfirst(rt); + Relation rt_entry_relation = NULL; + RuleLock *rt_entry_locks = NULL; + List *result = NIL; + List *locks = NIL; + List *dummy_products; + + rt_index++; + rt_entry_relation = heap_openr(rt_entry->relname); + rt_entry_locks = rt_entry_relation->rd_rules; + heap_close(rt_entry_relation); + + if (rt_entry_locks) + { + locks = + matchLocks(CMD_SELECT, rt_entry_locks, rt_index, parsetree); + } + if (locks != NIL) + { + result = fireRules(parsetree, rt_index, CMD_SELECT, + instead_flag, locks, &dummy_products); + if (*instead_flag) + return lappend(NIL, result); + if (result != NIL) + product_queries = nconc(product_queries, result); + } } - if (locks != NIL) { - result = fireRules(parsetree, rt_index, CMD_SELECT, - instead_flag, locks, &dummy_products); - if (*instead_flag) - return lappend(NIL, result); - if (result != NIL) - product_queries = nconc(product_queries, result); - } - } - return product_queries; + return product_queries; } -static Query * -CopyAndAddQual(Query *parsetree, - List *actions, - Node *rule_qual, - int rt_index, - CmdType event) +static Query * +CopyAndAddQual(Query * parsetree, + List * actions, + Node * rule_qual, + int rt_index, + CmdType event) { - Query *new_tree = (Query *) copyObject(parsetree); - Node *new_qual = NULL; - Query *rule_action = NULL; - - if (actions) - rule_action = lfirst(actions); - if (rule_qual != NULL) - new_qual = (Node *)copyObject(rule_qual); - if (rule_action != NULL) { - List *rtable; - int rt_length; - - rtable = new_tree->rtable; - rt_length = length(rtable); - rtable = append(rtable,listCopy(rule_action->rtable)); - new_tree->rtable = rtable; - OffsetVarNodes(new_qual, rt_length); - ChangeVarNodes(new_qual, PRS2_CURRENT_VARNO+rt_length, rt_index); - } - /* XXX -- where current doesn't work for instead nothing.... yet*/ - AddNotQual(new_tree, new_qual); - - return new_tree; + Query *new_tree = (Query *) copyObject(parsetree); + Node *new_qual = NULL; + Query *rule_action = NULL; + + if (actions) + rule_action = lfirst(actions); + if (rule_qual != NULL) + new_qual = (Node *) copyObject(rule_qual); + if (rule_action != NULL) + { + List *rtable; + int rt_length; + + rtable = new_tree->rtable; + rt_length = length(rtable); + rtable = append(rtable, listCopy(rule_action->rtable)); + new_tree->rtable = rtable; + OffsetVarNodes(new_qual, rt_length); + ChangeVarNodes(new_qual, PRS2_CURRENT_VARNO + rt_length, rt_index); + } + /* XXX -- where current doesn't work for instead nothing.... yet */ + AddNotQual(new_tree, new_qual); + + return new_tree; } /* - * fireRules - - * Iterate through rule locks applying rules. After an instead rule - * rule has been applied, return just new parsetree and let RewriteQuery - * start the process all over again. The locks are reordered to maintain - * sensible semantics. remember: reality is for dead birds -- glass + * fireRules - + * Iterate through rule locks applying rules. After an instead rule + * rule has been applied, return just new parsetree and let RewriteQuery + * start the process all over again. The locks are reordered to maintain + * sensible semantics. remember: reality is for dead birds -- glass * */ -static List * -fireRules(Query *parsetree, - int rt_index, - CmdType event, - bool *instead_flag, - List *locks, - List **qual_products) +static List * +fireRules(Query * parsetree, + int rt_index, + CmdType event, + bool * instead_flag, + List * locks, + List ** qual_products) { - RewriteInfo *info; - List *results = NIL; - List *i; - - /* choose rule to fire from list of rules */ - if (locks == NIL) { - ProcessRetrieveQuery(parsetree, - parsetree->rtable, - instead_flag, TRUE); - if (*instead_flag) - return lappend(NIL, parsetree); - else - return NIL; - } - - locks = orderRules(locks); /* instead rules first */ - foreach (i, locks) { - RewriteRule *rule_lock = (RewriteRule *)lfirst(i); - Node *qual, *event_qual; - List *actions; - List *r; - bool orig_instead_flag = *instead_flag; - - /* multiple rule action time */ - *instead_flag = rule_lock->isInstead; - event_qual = rule_lock->qual; - actions = rule_lock->actions; - if (event_qual != NULL && *instead_flag) - *qual_products = - lappend(*qual_products, - CopyAndAddQual(parsetree, actions, event_qual, - rt_index, event)); - foreach (r, actions) { - Query *rule_action = lfirst(r); - Node *rule_qual = copyObject(event_qual); - - /*-------------------------------------------------- - * Step 1: - * Rewrite current.attribute or current to tuple variable - * this appears to be done in parser? - *-------------------------------------------------- - */ - info = gatherRewriteMeta(parsetree, rule_action, rule_qual, - rt_index,event,instead_flag); - - /* handle escapable cases, or those handled by other code */ - if (info->nothing) { + RewriteInfo *info; + List *results = NIL; + List *i; + + /* choose rule to fire from list of rules */ + if (locks == NIL) + { + ProcessRetrieveQuery(parsetree, + parsetree->rtable, + instead_flag, TRUE); if (*instead_flag) - return NIL; + return lappend(NIL, parsetree); else - continue; - } - - if (info->action == info->event && - info->event == CMD_SELECT) - continue; - - /* - * Event Qualification forces copying of parsetree --- XXX - * and splitting into two queries one w/rule_qual, one - * w/NOT rule_qual. Also add user query qual onto rule action - */ - qual = parsetree->qual; - AddQual(info->rule_action, qual); - - if (info->rule_qual != NULL) - AddQual(info->rule_action, info->rule_qual); - - /*-------------------------------------------------- - * Step 2: - * Rewrite new.attribute w/ right hand side of target-list - * entry for appropriate field name in insert/update - *-------------------------------------------------- - */ - if ((info->event == CMD_INSERT) || (info->event == CMD_UPDATE)) { - FixNew(info, parsetree); - } - - /*-------------------------------------------------- - * Step 3: - * rewriting due to retrieve rules - *-------------------------------------------------- - */ - info->rule_action->rtable = info->rt; - ProcessRetrieveQuery(info->rule_action, info->rt, - &orig_instead_flag, TRUE); - - /*-------------------------------------------------- - * Step 4 - * Simplify? hey, no algorithm for simplification... let - * the planner do it. - *-------------------------------------------------- - */ - results = lappend(results, info->rule_action); - - pfree(info); + return NIL; } - if (*instead_flag) break; - } - return results; + + locks = orderRules(locks); /* instead rules first */ + foreach(i, locks) + { + RewriteRule *rule_lock = (RewriteRule *) lfirst(i); + Node *qual, + *event_qual; + List *actions; + List *r; + bool orig_instead_flag = *instead_flag; + + /* multiple rule action time */ + *instead_flag = rule_lock->isInstead; + event_qual = rule_lock->qual; + actions = rule_lock->actions; + if (event_qual != NULL && *instead_flag) + *qual_products = + lappend(*qual_products, + CopyAndAddQual(parsetree, actions, event_qual, + rt_index, event)); + foreach(r, actions) + { + Query *rule_action = lfirst(r); + Node *rule_qual = copyObject(event_qual); + + /*-------------------------------------------------- + * Step 1: + * Rewrite current.attribute or current to tuple variable + * this appears to be done in parser? + *-------------------------------------------------- + */ + info = gatherRewriteMeta(parsetree, rule_action, rule_qual, + rt_index, event, instead_flag); + + /* handle escapable cases, or those handled by other code */ + if (info->nothing) + { + if (*instead_flag) + return NIL; + else + continue; + } + + if (info->action == info->event && + info->event == CMD_SELECT) + continue; + + /* + * Event Qualification forces copying of parsetree --- XXX and + * splitting into two queries one w/rule_qual, one w/NOT + * rule_qual. Also add user query qual onto rule action + */ + qual = parsetree->qual; + AddQual(info->rule_action, qual); + + if (info->rule_qual != NULL) + AddQual(info->rule_action, info->rule_qual); + + /*-------------------------------------------------- + * Step 2: + * Rewrite new.attribute w/ right hand side of target-list + * entry for appropriate field name in insert/update + *-------------------------------------------------- + */ + if ((info->event == CMD_INSERT) || (info->event == CMD_UPDATE)) + { + FixNew(info, parsetree); + } + + /*-------------------------------------------------- + * Step 3: + * rewriting due to retrieve rules + *-------------------------------------------------- + */ + info->rule_action->rtable = info->rt; + ProcessRetrieveQuery(info->rule_action, info->rt, + &orig_instead_flag, TRUE); + + /*-------------------------------------------------- + * Step 4 + * Simplify? hey, no algorithm for simplification... let + * the planner do it. + *-------------------------------------------------- + */ + results = lappend(results, info->rule_action); + + pfree(info); + } + if (*instead_flag) + break; + } + return results; } -static List * -RewriteQuery(Query *parsetree, bool *instead_flag, List **qual_products) +static List * +RewriteQuery(Query * parsetree, bool * instead_flag, List ** qual_products) { - CmdType event; - List *product_queries = NIL; - int result_relation = 0; - - Assert(parsetree != NULL); - - event = parsetree->commandType; - - if (event == CMD_UTILITY) - return NIL; + CmdType event; + List *product_queries = NIL; + int result_relation = 0; - /* - * only for a delete may the targetlist be NULL - */ - if (event != CMD_DELETE) { - Assert(parsetree->targetList != NULL); - } - - result_relation = parsetree->resultRelation; + Assert(parsetree != NULL); + + event = parsetree->commandType; + + if (event == CMD_UTILITY) + return NIL; - if (event != CMD_SELECT) { /* - * the statement is an update, insert or delete + * only for a delete may the targetlist be NULL */ - RangeTblEntry *rt_entry; - Relation rt_entry_relation = NULL; - RuleLock *rt_entry_locks = NULL; - - rt_entry = rt_fetch(result_relation, parsetree->rtable); - rt_entry_relation = heap_openr(rt_entry->relname); - rt_entry_locks = rt_entry_relation->rd_rules; - heap_close(rt_entry_relation); - - if (rt_entry_locks != NULL) { - List *locks = - matchLocks(event, rt_entry_locks, result_relation, parsetree); - - product_queries = - fireRules(parsetree, - result_relation, - event, - instead_flag, - locks, - qual_products); + if (event != CMD_DELETE) + { + Assert(parsetree->targetList != NULL); + } + + result_relation = parsetree->resultRelation; + + if (event != CMD_SELECT) + { + + /* + * the statement is an update, insert or delete + */ + RangeTblEntry *rt_entry; + Relation rt_entry_relation = NULL; + RuleLock *rt_entry_locks = NULL; + + rt_entry = rt_fetch(result_relation, parsetree->rtable); + rt_entry_relation = heap_openr(rt_entry->relname); + rt_entry_locks = rt_entry_relation->rd_rules; + heap_close(rt_entry_relation); + + if (rt_entry_locks != NULL) + { + List *locks = + matchLocks(event, rt_entry_locks, result_relation, parsetree); + + product_queries = + fireRules(parsetree, + result_relation, + event, + instead_flag, + locks, + qual_products); + } + return product_queries; + } + else + { + + /* + * the statement is a select + */ + Query *other; + + other = copyObject(parsetree); /* ApplyRetrieveRule changes the + * range table */ + return + ProcessRetrieveQuery(other, parsetree->rtable, + instead_flag, FALSE); } - return product_queries; - }else { - /* - * the statement is a select - */ - Query *other; - - other = copyObject(parsetree); /* ApplyRetrieveRule changes the - range table */ - return - ProcessRetrieveQuery(other, parsetree->rtable, - instead_flag, FALSE); - } } /* @@ -559,61 +610,62 @@ RewriteQuery(Query *parsetree, bool *instead_flag, List **qual_products) * can be rewritten. Detecting cycles is left for the reader as an excercise. */ #ifndef REWRITE_INVOKE_MAX -#define REWRITE_INVOKE_MAX 10 +#define REWRITE_INVOKE_MAX 10 #endif -static int numQueryRewriteInvoked = 0; +static int numQueryRewriteInvoked = 0; /* * QueryRewrite - - * rewrite one query via QueryRewrite system, possibly returning 0, or many - * queries - */ -List * -QueryRewrite(Query *parsetree) + * rewrite one query via QueryRewrite system, possibly returning 0, or many + * queries + */ +List * +QueryRewrite(Query * parsetree) { - numQueryRewriteInvoked = 0; + numQueryRewriteInvoked = 0; - /* - * take a deep breath and apply all the rewrite rules - ay - */ - return deepRewriteQuery(parsetree); + /* + * take a deep breath and apply all the rewrite rules - ay + */ + return deepRewriteQuery(parsetree); } /* * deepRewriteQuery - - * rewrites the query and apply the rules again on the queries rewritten + * rewrites the query and apply the rules again on the queries rewritten */ -static List * -deepRewriteQuery(Query *parsetree) +static List * +deepRewriteQuery(Query * parsetree) { - List *n; - List *rewritten = NIL; - List *result = NIL; - bool instead; - List *qual_products = NIL; - - if (++numQueryRewriteInvoked > REWRITE_INVOKE_MAX) { - elog(WARN, "query rewritten %d times, may contain cycles", - numQueryRewriteInvoked-1); - } - - instead = FALSE; - result = RewriteQuery(parsetree, &instead, &qual_products); - if (!instead) - rewritten = lcons(parsetree, NIL); - - foreach(n, result) { - Query *pt = lfirst(n); - List *newstuff = NIL; - - newstuff = deepRewriteQuery(pt); - if (newstuff != NIL) - rewritten = nconc(rewritten, newstuff); - } - if (qual_products != NIL) - rewritten = nconc(rewritten, qual_products); - - return rewritten; -} + List *n; + List *rewritten = NIL; + List *result = NIL; + bool instead; + List *qual_products = NIL; + + if (++numQueryRewriteInvoked > REWRITE_INVOKE_MAX) + { + elog(WARN, "query rewritten %d times, may contain cycles", + numQueryRewriteInvoked - 1); + } + + instead = FALSE; + result = RewriteQuery(parsetree, &instead, &qual_products); + if (!instead) + rewritten = lcons(parsetree, NIL); + foreach(n, result) + { + Query *pt = lfirst(n); + List *newstuff = NIL; + + newstuff = deepRewriteQuery(pt); + if (newstuff != NIL) + rewritten = nconc(rewritten, newstuff); + } + if (qual_products != NIL) + rewritten = nconc(rewritten, qual_products); + + return rewritten; +} diff --git a/src/backend/rewrite/rewriteManip.c b/src/backend/rewrite/rewriteManip.c index 01fad29f77..b8b39b3328 100644 --- a/src/backend/rewrite/rewriteManip.c +++ b/src/backend/rewrite/rewriteManip.c @@ -6,7 +6,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteManip.c,v 1.4 1996/11/10 03:02:04 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteManip.c,v 1.5 1997/09/07 04:48:09 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -17,7 +17,7 @@ #include "nodes/nodes.h" #include "nodes/relation.h" #include "nodes/primnodes.h" -#include "parser/parsetree.h" /* for getrelid() */ +#include "parser/parsetree.h" /* for getrelid() */ #include "utils/lsyscache.h" #include "utils/builtins.h" #include "rewrite/rewriteHandler.h" @@ -28,410 +28,463 @@ #include "nodes/plannodes.h" #include "optimizer/clauses.h" -static void ResolveNew(RewriteInfo *info, List *targetlist, Node **node); +static void ResolveNew(RewriteInfo * info, List * targetlist, Node ** node); void -OffsetVarNodes(Node *node, int offset) +OffsetVarNodes(Node * node, int offset) { - if (node==NULL) - return; - switch (nodeTag(node)) { - case T_TargetEntry: + if (node == NULL) + return; + switch (nodeTag(node)) { - TargetEntry *tle = (TargetEntry *)node; - OffsetVarNodes(tle->expr, offset); - } - break; - case T_Expr: - { - Expr *expr = (Expr*)node; - OffsetVarNodes((Node*)expr->args, offset); - } - break; - case T_Var: - { - Var *var = (Var*)node; - var->varno += offset; - var->varnoold += offset; - } - break; - case T_List: - { - List *l; + case T_TargetEntry: + { + TargetEntry *tle = (TargetEntry *) node; + + OffsetVarNodes(tle->expr, offset); + } + break; + case T_Expr: + { + Expr *expr = (Expr *) node; - foreach(l, (List*)node) { - OffsetVarNodes(lfirst(l), offset); - } + OffsetVarNodes((Node *) expr->args, offset); + } + break; + case T_Var: + { + Var *var = (Var *) node; + + var->varno += offset; + var->varnoold += offset; + } + break; + case T_List: + { + List *l; + + foreach(l, (List *) node) + { + OffsetVarNodes(lfirst(l), offset); + } + } + break; + default: + /* ignore the others */ + break; } - break; - default: - /* ignore the others */ - break; - } } void -ChangeVarNodes(Node *node, int old_varno, int new_varno) +ChangeVarNodes(Node * node, int old_varno, int new_varno) { - if (node==NULL) - return; - switch (nodeTag(node)) { - case T_TargetEntry: - { - TargetEntry *tle = (TargetEntry *)node; - ChangeVarNodes(tle->expr, old_varno, new_varno); - } - break; - case T_Expr: - { - Expr *expr = (Expr*)node; - ChangeVarNodes((Node*)expr->args, old_varno, new_varno); - } - break; - case T_Var: + if (node == NULL) + return; + switch (nodeTag(node)) { - Var *var = (Var*)node; - if (var->varno == old_varno) { - var->varno = new_varno; - var->varnoold = new_varno; - } - } - break; - case T_List: - { - List *l; - foreach (l, (List*)node) { - ChangeVarNodes(lfirst(l), old_varno, new_varno); - } + case T_TargetEntry: + { + TargetEntry *tle = (TargetEntry *) node; + + ChangeVarNodes(tle->expr, old_varno, new_varno); + } + break; + case T_Expr: + { + Expr *expr = (Expr *) node; + + ChangeVarNodes((Node *) expr->args, old_varno, new_varno); + } + break; + case T_Var: + { + Var *var = (Var *) node; + + if (var->varno == old_varno) + { + var->varno = new_varno; + var->varnoold = new_varno; + } + } + break; + case T_List: + { + List *l; + + foreach(l, (List *) node) + { + ChangeVarNodes(lfirst(l), old_varno, new_varno); + } + } + break; + default: + /* ignore the others */ + break; } - break; - default: - /* ignore the others */ - break; - } } void -AddQual(Query *parsetree, Node *qual) +AddQual(Query * parsetree, Node * qual) { - Node *copy, *old; - - if (qual == NULL) - return; - - copy = copyObject(qual); - old = parsetree->qual; - if (old == NULL) - parsetree->qual = copy; - else - parsetree->qual = - (Node*)make_andclause(makeList(parsetree->qual, copy, -1)); + Node *copy, + *old; + + if (qual == NULL) + return; + + copy = copyObject(qual); + old = parsetree->qual; + if (old == NULL) + parsetree->qual = copy; + else + parsetree->qual = + (Node *) make_andclause(makeList(parsetree->qual, copy, -1)); } void -AddNotQual(Query *parsetree, Node *qual) +AddNotQual(Query * parsetree, Node * qual) { - Node *copy; - - if (qual == NULL) return; - - copy = (Node*)make_notclause(copyObject(qual)); + Node *copy; - AddQual(parsetree,copy); + if (qual == NULL) + return; + + copy = (Node *) make_notclause(copyObject(qual)); + + AddQual(parsetree, copy); } -static Node * +static Node * make_null(Oid type) { - Const *c = makeNode(Const); - - c->consttype = type; - c->constlen = get_typlen(type); - c->constvalue = PointerGetDatum(NULL); - c->constisnull = true; - c->constbyval = get_typbyval(type); - return (Node*)c; + Const *c = makeNode(Const); + + c->consttype = type; + c->constlen = get_typlen(type); + c->constvalue = PointerGetDatum(NULL); + c->constisnull = true; + c->constbyval = get_typbyval(type); + return (Node *) c; } void -FixResdomTypes (List *tlist) +FixResdomTypes(List * tlist) { - List *i; + List *i; - foreach (i, tlist) { - TargetEntry *tle = lfirst(i); + foreach(i, tlist) + { + TargetEntry *tle = lfirst(i); - if (nodeTag(tle->expr) == T_Var) { - Var *var = (Var*)tle->expr; + if (nodeTag(tle->expr) == T_Var) + { + Var *var = (Var *) tle->expr; - tle->resdom->restype = var->vartype; - tle->resdom->reslen = get_typlen(var->vartype); + tle->resdom->restype = var->vartype; + tle->resdom->reslen = get_typlen(var->vartype); + } } - } } -static Node * -FindMatchingNew(List *tlist, int attno) +static Node * +FindMatchingNew(List * tlist, int attno) { - List *i; - - foreach (i, tlist ) { - TargetEntry *tle = lfirst(i); + List *i; - if (tle->resdom->resno == attno ) { - return (tle->expr); + foreach(i, tlist) + { + TargetEntry *tle = lfirst(i); + + if (tle->resdom->resno == attno) + { + return (tle->expr); + } } - } - return NULL; + return NULL; } -static Node * -FindMatchingTLEntry(List *tlist, char *e_attname) +static Node * +FindMatchingTLEntry(List * tlist, char *e_attname) { - List *i; - - foreach (i, tlist) { - TargetEntry *tle = lfirst(i); - char *resname; - - resname = tle->resdom->resname; - if (!strcmp(e_attname, resname)) - return (tle->expr); - } - return NULL; + List *i; + + foreach(i, tlist) + { + TargetEntry *tle = lfirst(i); + char *resname; + + resname = tle->resdom->resname; + if (!strcmp(e_attname, resname)) + return (tle->expr); + } + return NULL; } static void -ResolveNew(RewriteInfo *info, List *targetlist, Node **nodePtr) +ResolveNew(RewriteInfo * info, List * targetlist, Node ** nodePtr) { - Node *node = *nodePtr; - - if (node == NULL) - return; - - switch(nodeTag(node)) { - case T_TargetEntry: - ResolveNew(info, targetlist, &((TargetEntry*)node)->expr); - break; - case T_Expr: - ResolveNew(info, targetlist, (Node**)(&(((Expr*)node)->args))); - break; - case T_Var: { - int this_varno = (int)((Var*)node)->varno; - Node *n; - - if (this_varno == info->new_varno) { - n = FindMatchingNew(targetlist, - ((Var*)node)->varattno); - if (n == NULL) { - if (info->event == CMD_UPDATE) { - ((Var*)node)->varno = info->current_varno; - ((Var*)node)->varnoold = info->current_varno; - } else { - *nodePtr = make_null(((Var*)node)->vartype); + Node *node = *nodePtr; + + if (node == NULL) + return; + + switch (nodeTag(node)) + { + case T_TargetEntry: + ResolveNew(info, targetlist, &((TargetEntry *) node)->expr); + break; + case T_Expr: + ResolveNew(info, targetlist, (Node **) (&(((Expr *) node)->args))); + break; + case T_Var: + { + int this_varno = (int) ((Var *) node)->varno; + Node *n; + + if (this_varno == info->new_varno) + { + n = FindMatchingNew(targetlist, + ((Var *) node)->varattno); + if (n == NULL) + { + if (info->event == CMD_UPDATE) + { + ((Var *) node)->varno = info->current_varno; + ((Var *) node)->varnoold = info->current_varno; + } + else + { + *nodePtr = make_null(((Var *) node)->vartype); + } + } + else + { + *nodePtr = n; + } + } + break; } - } else { - *nodePtr = n; - } - } - break; - } - case T_List: { - List *l; - foreach(l, (List*)node) { - ResolveNew(info, targetlist, (Node**)&(lfirst(l))); + case T_List: + { + List *l; + + foreach(l, (List *) node) + { + ResolveNew(info, targetlist, (Node **) & (lfirst(l))); + } + break; + } + default: + /* ignore the others */ + break; } - break; - } - default: - /* ignore the others */ - break; - } } void -FixNew(RewriteInfo* info, Query *parsetree) +FixNew(RewriteInfo * info, Query * parsetree) { - ResolveNew(info, parsetree->targetList, - (Node**)&(info->rule_action->targetList)); - ResolveNew(info, parsetree->targetList, &info->rule_action->qual); + ResolveNew(info, parsetree->targetList, + (Node **) & (info->rule_action->targetList)); + ResolveNew(info, parsetree->targetList, &info->rule_action->qual); } static void -nodeHandleRIRAttributeRule(Node **nodePtr, - List *rtable, - List *targetlist, - int rt_index, - int attr_num, - int *modified, - int *badsql) +nodeHandleRIRAttributeRule(Node ** nodePtr, + List * rtable, + List * targetlist, + int rt_index, + int attr_num, + int *modified, + int *badsql) { - Node *node = *nodePtr; + Node *node = *nodePtr; - if (node == NULL) - return; - switch (nodeTag(node)) { - case T_List: - { - List *i; - foreach(i, (List*)node) { - nodeHandleRIRAttributeRule((Node**)(&(lfirst(i))), rtable, - targetlist, rt_index, attr_num, - modified, badsql); - } - } - break; - case T_TargetEntry: - { - TargetEntry *tle = (TargetEntry *)node; - nodeHandleRIRAttributeRule(&tle->expr, rtable, targetlist, - rt_index, attr_num, modified, badsql); - } - break; - case T_Expr: - { - Expr *expr = (Expr *)node; - nodeHandleRIRAttributeRule((Node**)(&(expr->args)), rtable, - targetlist, rt_index, attr_num, - modified, badsql); - } - break; - case T_Var: + if (node == NULL) + return; + switch (nodeTag(node)) { - int this_varno = (int) ((Var*)node)->varno; - NameData name_to_look_for; - memset(name_to_look_for.data, 0, NAMEDATALEN); - - if (this_varno == rt_index && - ((Var*) node)->varattno == attr_num) { - if (((Var*)node)->vartype == 32) { /* HACK */ - *nodePtr = make_null(((Var*)node)->vartype); - *modified = TRUE; - *badsql = TRUE; - break; - } else { - namestrcpy(&name_to_look_for, - (char *)get_attname(getrelid(this_varno, - rtable), - attr_num)); + case T_List: + { + List *i; + + foreach(i, (List *) node) + { + nodeHandleRIRAttributeRule((Node **) (&(lfirst(i))), rtable, + targetlist, rt_index, attr_num, + modified, badsql); + } } - } - if (name_to_look_for.data[0]) { - Node *n; - - n = FindMatchingTLEntry(targetlist, (char *)&name_to_look_for); - if (n == NULL) { - *nodePtr = make_null(((Var*) node)->vartype); - } else { - *nodePtr = n; + break; + case T_TargetEntry: + { + TargetEntry *tle = (TargetEntry *) node; + + nodeHandleRIRAttributeRule(&tle->expr, rtable, targetlist, + rt_index, attr_num, modified, badsql); } - *modified = TRUE; - } + break; + case T_Expr: + { + Expr *expr = (Expr *) node; + + nodeHandleRIRAttributeRule((Node **) (&(expr->args)), rtable, + targetlist, rt_index, attr_num, + modified, badsql); + } + break; + case T_Var: + { + int this_varno = (int) ((Var *) node)->varno; + NameData name_to_look_for; + + memset(name_to_look_for.data, 0, NAMEDATALEN); + + if (this_varno == rt_index && + ((Var *) node)->varattno == attr_num) + { + if (((Var *) node)->vartype == 32) + { /* HACK */ + *nodePtr = make_null(((Var *) node)->vartype); + *modified = TRUE; + *badsql = TRUE; + break; + } + else + { + namestrcpy(&name_to_look_for, + (char *) get_attname(getrelid(this_varno, + rtable), + attr_num)); + } + } + if (name_to_look_for.data[0]) + { + Node *n; + + n = FindMatchingTLEntry(targetlist, (char *) &name_to_look_for); + if (n == NULL) + { + *nodePtr = make_null(((Var *) node)->vartype); + } + else + { + *nodePtr = n; + } + *modified = TRUE; + } + } + break; + default: + /* ignore the others */ + break; } - break; - default: - /* ignore the others */ - break; - } } -/* +/* * Handles 'on retrieve to relation.attribute - * do instead retrieve (attribute = expression) w/qual' + * do instead retrieve (attribute = expression) w/qual' */ void -HandleRIRAttributeRule(Query *parsetree, - List *rtable, - List *targetlist, - int rt_index, - int attr_num, - int *modified, - int *badsql) +HandleRIRAttributeRule(Query * parsetree, + List * rtable, + List * targetlist, + int rt_index, + int attr_num, + int *modified, + int *badsql) { - nodeHandleRIRAttributeRule((Node**)(&(parsetree->targetList)), rtable, - targetlist, rt_index, attr_num, - modified, badsql); - nodeHandleRIRAttributeRule(&parsetree->qual, rtable, targetlist, - rt_index, attr_num, modified, badsql); + nodeHandleRIRAttributeRule((Node **) (&(parsetree->targetList)), rtable, + targetlist, rt_index, attr_num, + modified, badsql); + nodeHandleRIRAttributeRule(&parsetree->qual, rtable, targetlist, + rt_index, attr_num, modified, badsql); } static void -nodeHandleViewRule(Node **nodePtr, - List *rtable, - List *targetlist, - int rt_index, - int *modified) +nodeHandleViewRule(Node ** nodePtr, + List * rtable, + List * targetlist, + int rt_index, + int *modified) { - Node *node = *nodePtr; - - if (node == NULL) - return; + Node *node = *nodePtr; - switch (nodeTag(node)) { - case T_List: - { - List *l; - foreach (l, (List*)node) { - nodeHandleViewRule((Node**) (&(lfirst(l))), - rtable, targetlist, - rt_index, modified); - } - } - break; - case T_TargetEntry: - { - TargetEntry *tle = (TargetEntry *)node; - nodeHandleViewRule(&(tle->expr), rtable, targetlist, - rt_index, modified); - } - break; - case T_Expr: - { - Expr *expr = (Expr*)node; - nodeHandleViewRule((Node**)(&(expr->args)), - rtable, targetlist, - rt_index, modified); - } - break; - case T_Var: + if (node == NULL) + return; + + switch (nodeTag(node)) { - Var *var = (Var*)node; - int this_varno = var->varno; - Node *n; - - if (this_varno == rt_index) { - n = FindMatchingTLEntry(targetlist, - get_attname(getrelid(this_varno, - rtable), - var->varattno)); - if (n == NULL) { - *nodePtr = make_null(((Var*) node)->vartype); - } else { - *nodePtr = n; + case T_List: + { + List *l; + + foreach(l, (List *) node) + { + nodeHandleViewRule((Node **) (&(lfirst(l))), + rtable, targetlist, + rt_index, modified); + } + } + break; + case T_TargetEntry: + { + TargetEntry *tle = (TargetEntry *) node; + + nodeHandleViewRule(&(tle->expr), rtable, targetlist, + rt_index, modified); + } + break; + case T_Expr: + { + Expr *expr = (Expr *) node; + + nodeHandleViewRule((Node **) (&(expr->args)), + rtable, targetlist, + rt_index, modified); } - *modified = TRUE; - } - break; + break; + case T_Var: + { + Var *var = (Var *) node; + int this_varno = var->varno; + Node *n; + + if (this_varno == rt_index) + { + n = FindMatchingTLEntry(targetlist, + get_attname(getrelid(this_varno, + rtable), + var->varattno)); + if (n == NULL) + { + *nodePtr = make_null(((Var *) node)->vartype); + } + else + { + *nodePtr = n; + } + *modified = TRUE; + } + break; + } + default: + /* ignore the others */ + break; } - default: - /* ignore the others */ - break; - } } void -HandleViewRule(Query *parsetree, - List *rtable, - List *targetlist, - int rt_index, - int *modified) +HandleViewRule(Query * parsetree, + List * rtable, + List * targetlist, + int rt_index, + int *modified) { - nodeHandleViewRule(&parsetree->qual, rtable, targetlist, rt_index, - modified); - nodeHandleViewRule((Node**)(&(parsetree->targetList)), rtable, targetlist, - rt_index, modified); + nodeHandleViewRule(&parsetree->qual, rtable, targetlist, rt_index, + modified); + nodeHandleViewRule((Node **) (&(parsetree->targetList)), rtable, targetlist, + rt_index, modified); } - diff --git a/src/backend/rewrite/rewriteRemove.c b/src/backend/rewrite/rewriteRemove.c index 3052a59a0d..58ccc5865b 100644 --- a/src/backend/rewrite/rewriteRemove.c +++ b/src/backend/rewrite/rewriteRemove.c @@ -1,13 +1,13 @@ /*------------------------------------------------------------------------- * * rewriteRemove.c-- - * routines for removing rewrite rules + * routines for removing rewrite rules * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteRemove.c,v 1.2 1996/11/03 04:51:51 scrappy Exp $ + * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteRemove.c,v 1.3 1997/09/07 04:48:10 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -18,37 +18,37 @@ #include "catalog/pg_rewrite.h" #include "catalog/catname.h" /* for RewriteRelationName */ #include "utils/syscache.h" -#include "utils/elog.h" /* for elog stuff */ +#include "utils/elog.h" /* for elog stuff */ #include "utils/palloc.h" -#include "utils/tqual.h" /* 'NowTimeQual' defined here.. */ -#include "access/heapam.h" /* heap AM calls defined here */ -#include "fmgr.h" /* for CHAR_16_EQ */ +#include "utils/tqual.h" /* 'NowTimeQual' defined here.. */ +#include "access/heapam.h" /* heap AM calls defined here */ +#include "fmgr.h" /* for CHAR_16_EQ */ -#include "rewrite/rewriteRemove.h" /* where the decls go */ +#include "rewrite/rewriteRemove.h" /* where the decls go */ #include "rewrite/rewriteSupport.h" /*----------------------------------------------------------------------- * RewriteGetRuleEventRel *----------------------------------------------------------------------- */ -char* +char * RewriteGetRuleEventRel(char *rulename) { - HeapTuple htp; - Oid eventrel; - - htp = SearchSysCacheTuple(REWRITENAME, PointerGetDatum(rulename), - 0,0,0); - if (!HeapTupleIsValid(htp)) - elog(WARN, "RewriteGetRuleEventRel: rule \"%s\" not found", - rulename); - eventrel = ((Form_pg_rewrite) GETSTRUCT(htp))->ev_class; - htp = SearchSysCacheTuple(RELOID, PointerGetDatum(eventrel), - 0,0,0); - if (!HeapTupleIsValid(htp)) - elog(WARN, "RewriteGetRuleEventRel: class %d not found", - eventrel); - return ((Form_pg_class) GETSTRUCT(htp))->relname.data; + HeapTuple htp; + Oid eventrel; + + htp = SearchSysCacheTuple(REWRITENAME, PointerGetDatum(rulename), + 0, 0, 0); + if (!HeapTupleIsValid(htp)) + elog(WARN, "RewriteGetRuleEventRel: rule \"%s\" not found", + rulename); + eventrel = ((Form_pg_rewrite) GETSTRUCT(htp))->ev_class; + htp = SearchSysCacheTuple(RELOID, PointerGetDatum(eventrel), + 0, 0, 0); + if (!HeapTupleIsValid(htp)) + elog(WARN, "RewriteGetRuleEventRel: class %d not found", + eventrel); + return ((Form_pg_class) GETSTRUCT(htp))->relname.data; } /* ---------------------------------------------------------------- @@ -58,10 +58,10 @@ RewriteGetRuleEventRel(char *rulename) * Delete a rule given its rulename. * * There are three steps. - * 1) Find the corresponding tuple in 'pg_rewrite' relation. - * Find the rule Id (i.e. the Oid of the tuple) and finally delete - * the tuple. - * 3) Delete the locks from the 'pg_class' relation. + * 1) Find the corresponding tuple in 'pg_rewrite' relation. + * Find the rule Id (i.e. the Oid of the tuple) and finally delete + * the tuple. + * 3) Delete the locks from the 'pg_class' relation. * * * ---------------------------------------------------------------- @@ -69,116 +69,119 @@ RewriteGetRuleEventRel(char *rulename) void RemoveRewriteRule(char *ruleName) { - Relation RewriteRelation = NULL; - HeapScanDesc scanDesc = NULL; - ScanKeyData scanKeyData; - HeapTuple tuple = NULL; - Oid ruleId = (Oid)0; - Oid eventRelationOid = (Oid)NULL; - Datum eventRelationOidDatum = (Datum)NULL; - Buffer buffer = (Buffer)NULL; - bool isNull = false; - - /* - * Open the pg_rewrite relation. - */ - RewriteRelation = heap_openr(RewriteRelationName); - - /* - * Scan the RuleRelation ('pg_rewrite') until we find a tuple - */ - ScanKeyEntryInitialize(&scanKeyData, 0, Anum_pg_rewrite_rulename, - F_CHAR16EQ, NameGetDatum(ruleName)); - scanDesc = heap_beginscan(RewriteRelation, - 0, NowTimeQual, 1, &scanKeyData); - - tuple = heap_getnext(scanDesc, 0, (Buffer *)NULL); - - /* - * complain if no rule with such name existed - */ - if (!HeapTupleIsValid(tuple)) { + Relation RewriteRelation = NULL; + HeapScanDesc scanDesc = NULL; + ScanKeyData scanKeyData; + HeapTuple tuple = NULL; + Oid ruleId = (Oid) 0; + Oid eventRelationOid = (Oid) NULL; + Datum eventRelationOidDatum = (Datum) NULL; + Buffer buffer = (Buffer) NULL; + bool isNull = false; + + /* + * Open the pg_rewrite relation. + */ + RewriteRelation = heap_openr(RewriteRelationName); + + /* + * Scan the RuleRelation ('pg_rewrite') until we find a tuple + */ + ScanKeyEntryInitialize(&scanKeyData, 0, Anum_pg_rewrite_rulename, + F_CHAR16EQ, NameGetDatum(ruleName)); + scanDesc = heap_beginscan(RewriteRelation, + 0, NowTimeQual, 1, &scanKeyData); + + tuple = heap_getnext(scanDesc, 0, (Buffer *) NULL); + + /* + * complain if no rule with such name existed + */ + if (!HeapTupleIsValid(tuple)) + { + heap_close(RewriteRelation); + elog(WARN, "No rule with name = '%s' was found.\n", ruleName); + } + + /* + * Store the OID of the rule (i.e. the tuple's OID) and the event + * relation's OID + */ + ruleId = tuple->t_oid; + eventRelationOidDatum = + PointerGetDatum(heap_getattr(tuple, + buffer, + Anum_pg_rewrite_ev_class, + RelationGetTupleDescriptor(RewriteRelation), + &isNull)); + if (isNull) + { + /* XXX strange!!! */ + elog(WARN, "RemoveRewriteRule: null event target relation!"); + } + eventRelationOid = DatumGetObjectId(eventRelationOidDatum); + + /* + * Now delete the relation level locks from the updated relation. + * (Make sure we do this before we remove the rule from pg_rewrite. + * Otherwise, heap_openr on eventRelationOid which reads pg_rwrite for + * the rules will fail.) + */ + prs2_deleteFromRelation(eventRelationOid, ruleId); + + /* + * Now delete the tuple... + */ + heap_delete(RewriteRelation, &(tuple->t_ctid)); heap_close(RewriteRelation); - elog(WARN, "No rule with name = '%s' was found.\n", ruleName); - } - - /* - * Store the OID of the rule (i.e. the tuple's OID) - * and the event relation's OID - */ - ruleId = tuple->t_oid; - eventRelationOidDatum = - PointerGetDatum(heap_getattr(tuple, - buffer, - Anum_pg_rewrite_ev_class, - RelationGetTupleDescriptor(RewriteRelation), - &isNull)); - if (isNull) { - /* XXX strange!!! */ - elog(WARN, "RemoveRewriteRule: null event target relation!"); - } - eventRelationOid = DatumGetObjectId(eventRelationOidDatum); - - /* - * Now delete the relation level locks from the updated relation. - * (Make sure we do this before we remove the rule from pg_rewrite. - * Otherwise, heap_openr on eventRelationOid which reads pg_rwrite - * for the rules will fail.) - */ - prs2_deleteFromRelation(eventRelationOid, ruleId); - - /* - * Now delete the tuple... - */ - heap_delete(RewriteRelation, &(tuple->t_ctid)); - heap_close(RewriteRelation); - heap_endscan(scanDesc); + heap_endscan(scanDesc); } /* * RelationRemoveRules - - * removes all rules associated with the relation when the relation is - * being removed. + * removes all rules associated with the relation when the relation is + * being removed. */ void RelationRemoveRules(Oid relid) { - Relation RewriteRelation = NULL; - HeapScanDesc scanDesc = NULL; - ScanKeyData scanKeyData; - HeapTuple tuple = NULL; - - /* - * Open the pg_rewrite relation. - */ - RewriteRelation = heap_openr(RewriteRelationName); - - /* - * Scan the RuleRelation ('pg_rewrite') for all the tuples that - * has 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, NowTimeQual, 1, &scanKeyData); - - for(;;) { - tuple = heap_getnext(scanDesc, 0, (Buffer *)NULL); - - if (!HeapTupleIsValid(tuple)) { - break; /* we're done */ - } - + Relation RewriteRelation = NULL; + HeapScanDesc scanDesc = NULL; + ScanKeyData scanKeyData; + HeapTuple tuple = NULL; + /* - * delete the tuple... + * Open the pg_rewrite relation. */ - heap_delete(RewriteRelation, &(tuple->t_ctid)); - } + RewriteRelation = heap_openr(RewriteRelationName); - heap_endscan(scanDesc); - heap_close(RewriteRelation); -} + /* + * Scan the RuleRelation ('pg_rewrite') for all the tuples that has + * 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, NowTimeQual, 1, &scanKeyData); + + for (;;) + { + tuple = heap_getnext(scanDesc, 0, (Buffer *) NULL); + + if (!HeapTupleIsValid(tuple)) + { + break; /* we're done */ + } + /* + * delete the tuple... + */ + heap_delete(RewriteRelation, &(tuple->t_ctid)); + } + + heap_endscan(scanDesc); + heap_close(RewriteRelation); +} diff --git a/src/backend/rewrite/rewriteSupport.c b/src/backend/rewrite/rewriteSupport.c index 54a8f0c7f9..8d3beb1c10 100644 --- a/src/backend/rewrite/rewriteSupport.c +++ b/src/backend/rewrite/rewriteSupport.c @@ -1,13 +1,13 @@ /*------------------------------------------------------------------------- * * rewriteSupport.c-- - * + * * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteSupport.c,v 1.6 1997/08/12 22:53:43 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteSupport.c,v 1.7 1997/09/07 04:48:11 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -19,7 +19,7 @@ #include "nodes/parsenodes.h" #include "utils/builtins.h" /* for textout */ #include "utils/rel.h" /* for Relation, RelationData ... */ -#include "utils/elog.h" /* for elog */ +#include "utils/elog.h" /* for elog */ #include "storage/buf.h" /* for InvalidBuffer */ #include "rewrite/rewriteSupport.h" #include "access/heapam.h" @@ -31,242 +31,250 @@ #include "utils/palloc.h" #include "fmgr.h" -/* +/* * RuleIdGetActionInfo - - * given a rule oid, look it up and return the rule-event-qual and - * list of parsetrees for the rule (in parseTrees) + * given a rule oid, look it up and return the rule-event-qual and + * list of parsetrees for the rule (in parseTrees) */ #ifdef NOT_USED -static Node * -RuleIdGetActionInfo(Oid ruleoid, bool *instead_flag, Query **parseTrees) +static Node * +RuleIdGetActionInfo(Oid ruleoid, bool * instead_flag, Query ** parseTrees) { - HeapTuple ruletuple; - char *ruleaction = NULL; - bool action_is_null = false; - bool instead_is_null = false; - Relation ruleRelation = NULL; - TupleDesc ruleTupdesc = NULL; - Query *ruleparse = NULL; - char *rule_evqual_string = NULL; - Node *rule_evqual = NULL; - - ruleRelation = heap_openr (RewriteRelationName); - ruleTupdesc = RelationGetTupleDescriptor(ruleRelation); - ruletuple = SearchSysCacheTuple (RULOID, - ObjectIdGetDatum(ruleoid), - 0,0,0); - if (ruletuple == NULL) - elog(WARN, "rule %u isn't in rewrite system relation", ruleoid); - - ruleaction = heap_getattr(ruletuple, - InvalidBuffer, - Anum_pg_rewrite_action, - ruleTupdesc, - &action_is_null ) ; - rule_evqual_string = heap_getattr(ruletuple, InvalidBuffer, - Anum_pg_rewrite_ev_qual, - ruleTupdesc, &action_is_null) ; - *instead_flag = !!heap_getattr(ruletuple, InvalidBuffer, - Anum_pg_rewrite_is_instead, - ruleTupdesc, &instead_is_null) ; - - if (action_is_null || instead_is_null) { - elog(WARN, "internal error: rewrite rule not properly set up"); - } - - ruleaction = textout((struct varlena *)ruleaction); - rule_evqual_string = textout((struct varlena *)rule_evqual_string); - - ruleparse = (Query*)stringToNode(ruleaction); - rule_evqual = (Node*)stringToNode(rule_evqual_string); - - heap_close(ruleRelation); - - *parseTrees = ruleparse; - return rule_evqual; + HeapTuple ruletuple; + char *ruleaction = NULL; + bool action_is_null = false; + bool instead_is_null = false; + Relation ruleRelation = NULL; + TupleDesc ruleTupdesc = NULL; + Query *ruleparse = NULL; + char *rule_evqual_string = NULL; + Node *rule_evqual = NULL; + + ruleRelation = heap_openr(RewriteRelationName); + ruleTupdesc = RelationGetTupleDescriptor(ruleRelation); + ruletuple = SearchSysCacheTuple(RULOID, + ObjectIdGetDatum(ruleoid), + 0, 0, 0); + if (ruletuple == NULL) + elog(WARN, "rule %u isn't in rewrite system relation", ruleoid); + + ruleaction = heap_getattr(ruletuple, + InvalidBuffer, + Anum_pg_rewrite_action, + ruleTupdesc, + &action_is_null); + rule_evqual_string = heap_getattr(ruletuple, InvalidBuffer, + Anum_pg_rewrite_ev_qual, + ruleTupdesc, &action_is_null); + *instead_flag = !!heap_getattr(ruletuple, InvalidBuffer, + Anum_pg_rewrite_is_instead, + ruleTupdesc, &instead_is_null); + + if (action_is_null || instead_is_null) + { + elog(WARN, "internal error: rewrite rule not properly set up"); + } + + ruleaction = textout((struct varlena *) ruleaction); + rule_evqual_string = textout((struct varlena *) rule_evqual_string); + + ruleparse = (Query *) stringToNode(ruleaction); + rule_evqual = (Node *) stringToNode(rule_evqual_string); + + heap_close(ruleRelation); + + *parseTrees = ruleparse; + return rule_evqual; } + #endif int IsDefinedRewriteRule(char *ruleName) { - Relation RewriteRelation = NULL; - HeapScanDesc scanDesc = NULL; - ScanKeyData scanKey; - HeapTuple tuple = NULL; - - - /* - * Open the pg_rewrite relation. - */ - RewriteRelation = heap_openr(RewriteRelationName); - - /* - * Scan the RuleRelation ('pg_rewrite') until we find a tuple - */ - ScanKeyEntryInitialize(&scanKey, 0, Anum_pg_rewrite_rulename, - NameEqualRegProcedure, PointerGetDatum(ruleName)); - scanDesc = heap_beginscan(RewriteRelation, - 0, NowTimeQual, 1, &scanKey); - - tuple = heap_getnext(scanDesc, 0, (Buffer *)NULL); - - /* - * return whether or not the rewrite rule existed - */ - heap_close(RewriteRelation); - heap_endscan(scanDesc); - return (HeapTupleIsValid(tuple)); + Relation RewriteRelation = NULL; + HeapScanDesc scanDesc = NULL; + ScanKeyData scanKey; + HeapTuple tuple = NULL; + + + /* + * Open the pg_rewrite relation. + */ + RewriteRelation = heap_openr(RewriteRelationName); + + /* + * Scan the RuleRelation ('pg_rewrite') until we find a tuple + */ + ScanKeyEntryInitialize(&scanKey, 0, Anum_pg_rewrite_rulename, + NameEqualRegProcedure, PointerGetDatum(ruleName)); + scanDesc = heap_beginscan(RewriteRelation, + 0, NowTimeQual, 1, &scanKey); + + tuple = heap_getnext(scanDesc, 0, (Buffer *) NULL); + + /* + * return whether or not the rewrite rule existed + */ + heap_close(RewriteRelation); + heap_endscan(scanDesc); + return (HeapTupleIsValid(tuple)); } static void setRelhasrulesInRelation(Oid relationId, bool relhasrules) { - Relation relationRelation; - HeapTuple tuple; - HeapTuple newTuple; - Relation idescs[Num_pg_class_indices]; - Form_pg_class relp; - - /* - * Lock a relation given its Oid. - * Go to the RelationRelation (i.e. pg_relation), find the - * appropriate tuple, and add the specified lock to it. - */ - relationRelation = heap_openr(RelationRelationName); - tuple = ClassOidIndexScan(relationRelation, relationId); - - /* - * Create a new tuple (i.e. a copy of the old tuple - * with its rule lock field changed and replace the old - * tuple in the RelationRelation - * NOTE: XXX ??? do we really need to make that copy ???? - */ - newTuple = heap_copytuple(tuple); - - relp = (Form_pg_class) GETSTRUCT(newTuple); - relp->relhasrules = relhasrules; - - heap_replace(relationRelation, &(tuple->t_ctid), newTuple); - - /* keep the catalog indices up to date */ - CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, idescs); - CatalogIndexInsert(idescs, Num_pg_class_indices, relationRelation, - newTuple); - CatalogCloseIndices(Num_pg_class_indices, idescs); - - /* be tidy */ - pfree(tuple); - pfree(newTuple); - - heap_close(relationRelation); + Relation relationRelation; + HeapTuple tuple; + HeapTuple newTuple; + Relation idescs[Num_pg_class_indices]; + Form_pg_class relp; + + /* + * Lock a relation given its Oid. Go to the RelationRelation (i.e. + * pg_relation), find the appropriate tuple, and add the specified + * lock to it. + */ + relationRelation = heap_openr(RelationRelationName); + tuple = ClassOidIndexScan(relationRelation, relationId); + + /* + * Create a new tuple (i.e. a copy of the old tuple with its rule lock + * field changed and replace the old tuple in the RelationRelation + * NOTE: XXX ??? do we really need to make that copy ???? + */ + newTuple = heap_copytuple(tuple); + + relp = (Form_pg_class) GETSTRUCT(newTuple); + relp->relhasrules = relhasrules; + + heap_replace(relationRelation, &(tuple->t_ctid), newTuple); + + /* keep the catalog indices up to date */ + CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, idescs); + CatalogIndexInsert(idescs, Num_pg_class_indices, relationRelation, + newTuple); + CatalogCloseIndices(Num_pg_class_indices, idescs); + + /* be tidy */ + pfree(tuple); + pfree(newTuple); + + heap_close(relationRelation); } void prs2_addToRelation(Oid relid, - Oid ruleId, - CmdType event_type, - AttrNumber attno, - bool isInstead, - Node *qual, - List *actions) + Oid ruleId, + CmdType event_type, + AttrNumber attno, + bool isInstead, + Node * qual, + List * actions) { - Relation relation; - RewriteRule *thisRule; - RuleLock *rulelock; - MemoryContext oldcxt; - - /* - * create an in memory RewriteRule data structure which is cached by - * every Relation descriptor. (see utils/cache/relcache.c) - */ - oldcxt = MemoryContextSwitchTo((MemoryContext)CacheCxt); - thisRule = (RewriteRule *)palloc(sizeof(RewriteRule)); - MemoryContextSwitchTo(oldcxt); - - thisRule->ruleId = ruleId; - thisRule->event = event_type; - thisRule->attrno = attno; - thisRule->qual = qual; - thisRule->actions = actions; - thisRule->isInstead = isInstead; - - relation = heap_open(relid); - - /* - * modify or create a RuleLock cached by Relation - */ - if (relation->rd_rules == NULL) { - - oldcxt = MemoryContextSwitchTo((MemoryContext)CacheCxt); - rulelock = (RuleLock *)palloc(sizeof(RuleLock)); - rulelock->numLocks = 1; - rulelock->rules = (RewriteRule **)palloc(sizeof(RewriteRule*)); - rulelock->rules[0] = thisRule; - relation->rd_rules = rulelock; - MemoryContextSwitchTo(oldcxt); + Relation relation; + RewriteRule *thisRule; + RuleLock *rulelock; + MemoryContext oldcxt; /* - * the fact that relation->rd_rules is NULL means the relhasrules - * attribute of the tuple of this relation in pg_class is false. We - * need to set it to true. + * create an in memory RewriteRule data structure which is cached by + * every Relation descriptor. (see utils/cache/relcache.c) */ - setRelhasrulesInRelation(relid, TRUE); - } else { - int numlock; - - rulelock = relation->rd_rules; - numlock = rulelock->numLocks; - /* expand, for safety reasons */ - oldcxt = MemoryContextSwitchTo((MemoryContext)CacheCxt); - rulelock->rules = - (RewriteRule **)repalloc(rulelock->rules, - sizeof(RewriteRule*)*(numlock+1)); + oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt); + thisRule = (RewriteRule *) palloc(sizeof(RewriteRule)); MemoryContextSwitchTo(oldcxt); - rulelock->rules[numlock] = thisRule; - rulelock->numLocks++; - } - heap_close(relation); + thisRule->ruleId = ruleId; + thisRule->event = event_type; + thisRule->attrno = attno; + thisRule->qual = qual; + thisRule->actions = actions; + thisRule->isInstead = isInstead; + + relation = heap_open(relid); + + /* + * modify or create a RuleLock cached by Relation + */ + if (relation->rd_rules == NULL) + { + + oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt); + rulelock = (RuleLock *) palloc(sizeof(RuleLock)); + rulelock->numLocks = 1; + rulelock->rules = (RewriteRule **) palloc(sizeof(RewriteRule *)); + rulelock->rules[0] = thisRule; + relation->rd_rules = rulelock; + MemoryContextSwitchTo(oldcxt); - return; + /* + * the fact that relation->rd_rules is NULL means the relhasrules + * attribute of the tuple of this relation in pg_class is false. + * We need to set it to true. + */ + setRelhasrulesInRelation(relid, TRUE); + } + else + { + int numlock; + + rulelock = relation->rd_rules; + numlock = rulelock->numLocks; + /* expand, for safety reasons */ + oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt); + rulelock->rules = + (RewriteRule **) repalloc(rulelock->rules, + sizeof(RewriteRule *) * (numlock + 1)); + MemoryContextSwitchTo(oldcxt); + rulelock->rules[numlock] = thisRule; + rulelock->numLocks++; + } + + heap_close(relation); + + return; } void prs2_deleteFromRelation(Oid relid, Oid ruleId) { - RuleLock *rulelock; - Relation relation; - int numlock; - int i; - MemoryContext oldcxt; - - relation = heap_open(relid); - rulelock = relation->rd_rules; - Assert(rulelock != NULL); - - numlock = rulelock->numLocks; - for(i=0; i < numlock; i++) { - if (rulelock->rules[i]->ruleId == ruleId) - break; - } - Assert(i<numlock); - oldcxt = MemoryContextSwitchTo((MemoryContext)CacheCxt); - pfree(rulelock->rules[i]); - MemoryContextSwitchTo(oldcxt); - if (numlock==1) { - relation->rd_rules = NULL; - /* - * we don't have rules any more, flag the relhasrules attribute of - * the tuple of this relation in pg_class false. - */ - setRelhasrulesInRelation(relid, FALSE); - } else { - rulelock->rules[i] = rulelock->rules[numlock-1]; - rulelock->rules[numlock-1] = NULL; - rulelock->numLocks--; - } - - heap_close(relation); -} + RuleLock *rulelock; + Relation relation; + int numlock; + int i; + MemoryContext oldcxt; + relation = heap_open(relid); + rulelock = relation->rd_rules; + Assert(rulelock != NULL); + + numlock = rulelock->numLocks; + for (i = 0; i < numlock; i++) + { + if (rulelock->rules[i]->ruleId == ruleId) + break; + } + Assert(i < numlock); + oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt); + pfree(rulelock->rules[i]); + MemoryContextSwitchTo(oldcxt); + if (numlock == 1) + { + relation->rd_rules = NULL; + + /* + * we don't have rules any more, flag the relhasrules attribute of + * the tuple of this relation in pg_class false. + */ + setRelhasrulesInRelation(relid, FALSE); + } + else + { + rulelock->rules[i] = rulelock->rules[numlock - 1]; + rulelock->rules[numlock - 1] = NULL; + rulelock->numLocks--; + } + + heap_close(relation); +} |
