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 2cbec8e615..d5965f73ec 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 c915ed6ed7..a6650efecf 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 488fd2b9e3..3d3ad51c31 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 89665d8858..a8997d5a8a 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 64da8479d1..9d6d5e7d64 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 17aa34be07..fd1472a93c 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); -- 2.40.0