From 4140c2f30e2814527f0975876956f446e326ae70 Mon Sep 17 00:00:00 2001 From: "Thomas G. Lockhart" Date: Mon, 14 Dec 1998 00:02:17 +0000 Subject: [PATCH] Add support for the CASE statement in the rewrite handling. Allows (at least some) rules and views. Still some trouble (crashes) with target CASE columns spanning tables, but lots now works. --- src/backend/nodes/outfuncs.c | 4 +- src/backend/nodes/readfuncs.c | 50 ++++++++++++++- src/backend/optimizer/plan/setrefs.c | 31 ++++++++- src/backend/rewrite/rewriteHandler.c | 94 +++++++++++++++++++++++++++- src/backend/rewrite/rewriteManip.c | 70 ++++++++++++++++++++- src/backend/rewrite/rewriteRemove.c | 14 +++-- 6 files changed, 250 insertions(+), 13 deletions(-) diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index 2cbec8e615b..d5965f73ecc 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.49 1998/12/04 15:33:33 thomas Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.50 1998/12/14 00:01:47 thomas Exp $ * * NOTES * Every (plan) node in POSTGRES has an associated "out" routine which @@ -1702,7 +1702,7 @@ _outCaseWhen(StringInfo str, CaseWhen *node) { char buf[500]; - sprintf(buf, " :when "); + sprintf(buf, " WHEN "); appendStringInfo(str, buf); _outNode(str, node->expr); sprintf(buf, " :then "); diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c index c915ed6ed74..a6650efecf1 100644 --- a/src/backend/nodes/readfuncs.c +++ b/src/backend/nodes/readfuncs.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.39 1998/11/22 10:48:40 vadim Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.40 1998/12/14 00:01:47 thomas Exp $ * * NOTES * Most of the read functions for plan nodes are tested. (In fact, they @@ -786,6 +786,50 @@ _readExpr() return local_node; } +/* ---------------- + * _readCaseExpr + * + * CaseExpr is a subclass of Node + * ---------------- + */ +static CaseExpr * +_readCaseExpr() +{ + CaseExpr *local_node; + char *token; + int length; + + local_node = makeNode(CaseExpr); + + local_node->args = nodeRead(true); + token = lsptok(NULL, &length); /* eat :default */ + local_node->defresult = nodeRead(true); + + return local_node; +} + +/* ---------------- + * _readCaseWhen + * + * CaseWhen is a subclass of Node + * ---------------- + */ +static CaseWhen * +_readCaseWhen() +{ + CaseWhen *local_node; + char *token; + int length; + + local_node = makeNode(CaseWhen); + + local_node->expr = nodeRead(true); + token = lsptok(NULL, &length); /* eat :then */ + local_node->result = nodeRead(true); + + return local_node; +} + /* ---------------- * _readVar * @@ -2037,6 +2081,10 @@ parsePlanString(void) return_value = _readSortClause(); else if (!strncmp(token, "GROUPCLAUSE", length)) return_value = _readGroupClause(); + else if (!strncmp(token, "CASE", length)) + return_value = _readCaseExpr(); + else if (!strncmp(token, "WHEN", length)) + return_value = _readCaseWhen(); else elog(ERROR, "badly formatted planstring \"%.10s\"...\n", token); diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c index 488fd2b9e37..3d3ad51c319 100644 --- a/src/backend/optimizer/plan/setrefs.c +++ b/src/backend/optimizer/plan/setrefs.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.28 1998/10/08 18:29:29 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.29 1998/12/14 00:02:10 thomas Exp $ * *------------------------------------------------------------------------- */ @@ -303,7 +303,7 @@ replace_clause_joinvar_refs(Expr *clause, { temp = (List *) replace_joinvar_refs((Var *) clause, outer_tlist, inner_tlist); - if (temp) + if (temp != NULL) return temp; else if (clause != NULL) return (List *) clause; @@ -402,6 +402,33 @@ replace_clause_joinvar_refs(Expr *clause, inner_tlist); return (List *) clause; } + else if (IsA(clause, CaseExpr)) + { + ((CaseExpr *) clause)->args = + (List *) replace_subclause_joinvar_refs(((CaseExpr *) clause)->args, + outer_tlist, + inner_tlist); + + ((CaseExpr *) clause)->defresult = + (Node *) replace_clause_joinvar_refs((Expr *) ((CaseExpr *) clause)->defresult, + outer_tlist, + inner_tlist); + return (List *) clause; + } + else if (IsA(clause, CaseWhen)) + { + ((CaseWhen *) clause)->expr = + (Node *) replace_clause_joinvar_refs((Expr *) ((CaseWhen *) clause)->expr, + outer_tlist, + inner_tlist); + + ((CaseWhen *) clause)->result = + (Node *) replace_clause_joinvar_refs((Expr *) ((CaseWhen *) clause)->result, + outer_tlist, + inner_tlist); + return (List *) clause; + } + /* shouldn't reach here */ elog(ERROR, "replace_clause_joinvar_refs: unsupported clause %d", nodeTag(clause)); diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c index 89665d88588..a8997d5a8ab 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.26 1998/12/04 15:34:36 thomas Exp $ + * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.27 1998/12/14 00:02:16 thomas Exp $ * *------------------------------------------------------------------------- */ @@ -1457,6 +1457,34 @@ apply_RIR_adjust_sublevel(Node *node, int sublevels_up) } break; + case T_CaseExpr: + { + CaseExpr *exp = (CaseExpr *)node; + + apply_RIR_adjust_sublevel( + (Node *)(exp->args), + sublevels_up); + + apply_RIR_adjust_sublevel( + (Node *)(exp->defresult), + sublevels_up); + } + break; + + case T_CaseWhen: + { + CaseWhen *exp = (CaseWhen *)node; + + apply_RIR_adjust_sublevel( + (Node *)(exp->expr), + sublevels_up); + + apply_RIR_adjust_sublevel( + (Node *)(exp->result), + sublevels_up); + } + break; + default: elog(NOTICE, "unknown node tag %d in attribute_used()", nodeTag(node)); elog(NOTICE, "Node is: %s", nodeToString(node)); @@ -1691,6 +1719,50 @@ apply_RIR_view(Node **nodePtr, int rt_index, RangeTblEntry *rte, List *tlist, in } break; + case T_CaseExpr: + { + CaseExpr *exp = (CaseExpr *)node; + + apply_RIR_view( + (Node **)(&(exp->args)), + rt_index, + rte, + tlist, + modified, + sublevels_up); + + apply_RIR_view( + (Node **)(&(exp->defresult)), + rt_index, + rte, + tlist, + modified, + sublevels_up); + } + break; + + case T_CaseWhen: + { + CaseWhen *exp = (CaseWhen *)node; + + apply_RIR_view( + (Node **)(&(exp->expr)), + rt_index, + rte, + tlist, + modified, + sublevels_up); + + apply_RIR_view( + (Node **)(&(exp->result)), + rt_index, + rte, + tlist, + modified, + sublevels_up); + } + break; + default: elog(NOTICE, "unknown node tag %d in apply_RIR_view()", nodeTag(node)); elog(NOTICE, "Node is: %s", nodeToString(node)); @@ -1885,7 +1957,27 @@ fireRIRonSubselect(Node *node) break; case T_CaseExpr: + { + CaseExpr *exp = (CaseExpr *)node; + + fireRIRonSubselect( + (Node *)(exp->args)); + + fireRIRonSubselect( + (Node *)(exp->defresult)); + } + break; + case T_CaseWhen: + { + CaseWhen *exp = (CaseWhen *)node; + + fireRIRonSubselect( + (Node *)(exp->expr)); + + fireRIRonSubselect( + (Node *)(exp->result)); + } break; case T_Query: diff --git a/src/backend/rewrite/rewriteManip.c b/src/backend/rewrite/rewriteManip.c index 64da8479d15..9d6d5e7d64d 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.22 1998/10/21 16:21:26 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteManip.c,v 1.23 1998/12/14 00:02:17 thomas Exp $ * *------------------------------------------------------------------------- */ @@ -191,6 +191,38 @@ OffsetVarNodes(Node *node, int offset, int sublevels_up) } break; + case T_CaseExpr: + { + CaseExpr *exp = (CaseExpr *)node; + + OffsetVarNodes( + (Node *)(exp->args), + offset, + sublevels_up); + + OffsetVarNodes( + (Node *)(exp->defresult), + offset, + sublevels_up); + } + break; + + case T_CaseWhen: + { + CaseWhen *exp = (CaseWhen *)node; + + OffsetVarNodes( + (Node *)(exp->expr), + offset, + sublevels_up); + + OffsetVarNodes( + (Node *)(exp->result), + offset, + sublevels_up); + } + break; + default: elog(NOTICE, "unknown node tag %d in OffsetVarNodes()", nodeTag(node)); elog(NOTICE, "Node is: %s", nodeToString(node)); @@ -377,6 +409,42 @@ ChangeVarNodes(Node *node, int rt_index, int new_index, int sublevels_up) } break; + case T_CaseExpr: + { + CaseExpr *exp = (CaseExpr *)node; + + ChangeVarNodes( + (Node *)(exp->args), + rt_index, + new_index, + sublevels_up); + + ChangeVarNodes( + (Node *)(exp->defresult), + rt_index, + new_index, + sublevels_up); + } + break; + + case T_CaseWhen: + { + CaseWhen *exp = (CaseWhen *)node; + + ChangeVarNodes( + (Node *)(exp->expr), + rt_index, + new_index, + sublevels_up); + + ChangeVarNodes( + (Node *)(exp->result), + rt_index, + new_index, + sublevels_up); + } + break; + default: elog(NOTICE, "unknown node tag %d in ChangeVarNodes()", nodeTag(node)); elog(NOTICE, "Node is: %s", nodeToString(node)); diff --git a/src/backend/rewrite/rewriteRemove.c b/src/backend/rewrite/rewriteRemove.c index 17aa34be07b..fd1472a93cf 100644 --- a/src/backend/rewrite/rewriteRemove.c +++ b/src/backend/rewrite/rewriteRemove.c @@ -7,11 +7,13 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteRemove.c,v 1.19 1998/11/27 19:52:17 vadim Exp $ + * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteRemove.c,v 1.20 1998/12/14 00:02:17 thomas Exp $ * *------------------------------------------------------------------------- */ +#include + #include "postgres.h" #include "fmgr.h" /* for F_NAMEEQ */ @@ -39,14 +41,14 @@ RewriteGetRuleEventRel(char *rulename) PointerGetDatum(rulename), 0, 0, 0); if (!HeapTupleIsValid(htup)) - elog(ERROR, "RewriteGetRuleEventRel: rule \"%s\" not found", - rulename); + elog(ERROR, "Rule or view '%s' not found", + ((!strncmp(rulename, "_RET", 4))? (rulename+4): rulename)); eventrel = ((Form_pg_rewrite) GETSTRUCT(htup))->ev_class; htup = SearchSysCacheTuple(RELOID, PointerGetDatum(eventrel), 0, 0, 0); if (!HeapTupleIsValid(htup)) - elog(ERROR, "RewriteGetRuleEventRel: class %d not found", + elog(ERROR, "Class '%d' not found", eventrel); return ((Form_pg_class) GETSTRUCT(htup))->relname.data; } @@ -94,7 +96,7 @@ RemoveRewriteRule(char *ruleName) if (!HeapTupleIsValid(tuple)) { heap_close(RewriteRelation); - elog(ERROR, "No rule with name = '%s' was found.\n", ruleName); + elog(ERROR, "Rule '%s' not found\n", ruleName); } /* @@ -110,7 +112,7 @@ RemoveRewriteRule(char *ruleName) { /* XXX strange!!! */ pfree(tuple); - elog(ERROR, "RemoveRewriteRule: null event target relation!"); + elog(ERROR, "RemoveRewriteRule: internal error; null event target relation!"); } eventRelationOid = DatumGetObjectId(eventRelationOidDatum);