diff options
Diffstat (limited to 'src/backend/optimizer/util/tlist.c')
-rw-r--r-- | src/backend/optimizer/util/tlist.c | 834 |
1 files changed, 438 insertions, 396 deletions
diff --git a/src/backend/optimizer/util/tlist.c b/src/backend/optimizer/util/tlist.c index c0f11ff3293..7e8563d31ab 100644 --- a/src/backend/optimizer/util/tlist.c +++ b/src/backend/optimizer/util/tlist.c @@ -1,13 +1,13 @@ /*------------------------------------------------------------------------- * * tlist.c-- - * Target list manipulation routines + * Target list manipulation routines * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/util/tlist.c,v 1.4 1997/08/20 14:53:47 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/util/tlist.c,v 1.5 1997/09/07 04:44:33 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -28,498 +28,538 @@ #include "nodes/makefuncs.h" #include "parser/catalog_utils.h" -static Node *flatten_tlistentry(Node *tlistentry, List *flat_tlist); +static Node *flatten_tlistentry(Node * tlistentry, List * flat_tlist); /***************************************************************************** - * ---------- RELATION node target list routines ---------- + * ---------- RELATION node target list routines ---------- *****************************************************************************/ -/* +/* * tlistentry-member-- - * + * * RETURNS: the leftmost member of sequence "targetlist" that satisfies - * the predicate "var_equal" + * the predicate "var_equal" * MODIFIES: nothing * REQUIRES: test = function which can operate on a lispval union - * var = valid var-node - * targetlist = valid sequence + * var = valid var-node + * targetlist = valid sequence */ -TargetEntry * -tlistentry_member(Var *var, List *targetlist) +TargetEntry * +tlistentry_member(Var * var, List * targetlist) { - if (var) { - List *temp = NIL; - - foreach (temp,targetlist) { - if (var_equal(var, - get_expr(lfirst(temp)))) - return((TargetEntry*)lfirst(temp)); + if (var) + { + List *temp = NIL; + + foreach(temp, targetlist) + { + if (var_equal(var, + get_expr(lfirst(temp)))) + return ((TargetEntry *) lfirst(temp)); + } } - } - return (NULL); + return (NULL); } -/* +/* * matching_tlvar-- - * + * * RETURNS: var node in a target list which is var_equal to 'var', - * if one exists. + * if one exists. * REQUIRES: "test" operates on lispval unions, - * + * */ -Expr * -matching_tlvar(Var *var, List *targetlist) +Expr * +matching_tlvar(Var * var, List * targetlist) { - TargetEntry *tlentry; + TargetEntry *tlentry; - tlentry = tlistentry_member(var,targetlist); - if (tlentry) - return((Expr*)get_expr (tlentry) ); + tlentry = tlistentry_member(var, targetlist); + if (tlentry) + return ((Expr *) get_expr(tlentry)); - return((Expr*) NULL); + return ((Expr *) NULL); } -/* +/* * add_tl_element-- - * Creates a targetlist entry corresponding to the supplied var node + * Creates a targetlist entry corresponding to the supplied var node * * 'var' and adds the new targetlist entry to the targetlist field of - * 'rel' - * + * 'rel' + * * RETURNS: nothing * MODIFIES: vartype and varid fields of leftmost varnode that matches - * argument "var" (sometimes). + * argument "var" (sometimes). * CREATES: new var-node iff no matching var-node exists in targetlist */ void -add_tl_element(Rel *rel, Var *var) +add_tl_element(Rel * rel, Var * var) { - Expr *oldvar = (Expr *)NULL; - - oldvar = matching_tlvar(var, rel->targetlist); - - /* - * If 'var' is not already in 'rel's target list, add a new node. - */ - if (oldvar==NULL) { - List *tlist = rel->targetlist; - Var *newvar = makeVar(var->varno, - var->varattno, - var->vartype, - var->varno, - var->varoattno); - - rel->targetlist = - lappend (tlist, - create_tl_element(newvar, - length(tlist) + 1)); - - } + Expr *oldvar = (Expr *) NULL; + + oldvar = matching_tlvar(var, rel->targetlist); + + /* + * If 'var' is not already in 'rel's target list, add a new node. + */ + if (oldvar == NULL) + { + List *tlist = rel->targetlist; + Var *newvar = makeVar(var->varno, + var->varattno, + var->vartype, + var->varno, + var->varoattno); + + rel->targetlist = + lappend(tlist, + create_tl_element(newvar, + length(tlist) + 1)); + + } } -/* +/* * create_tl_element-- - * Creates a target list entry node and its associated (resdom var) pair - * with its resdom number equal to 'resdomno' and the joinlist field set - * to 'joinlist'. - * + * Creates a target list entry node and its associated (resdom var) pair + * with its resdom number equal to 'resdomno' and the joinlist field set + * to 'joinlist'. + * * RETURNS: newly created tlist-entry * CREATES: new targetlist entry (always). */ -TargetEntry* -create_tl_element(Var *var, int resdomno) +TargetEntry * +create_tl_element(Var * var, int resdomno) { - TargetEntry *tlelement= makeNode(TargetEntry); - - tlelement->resdom = - makeResdom(resdomno, - var->vartype, - get_typlen(var->vartype), - NULL, - (Index)0, - (Oid)0, - 0); - tlelement->expr = (Node*)var; - - return(tlelement); + TargetEntry *tlelement = makeNode(TargetEntry); + + tlelement->resdom = + makeResdom(resdomno, + var->vartype, + get_typlen(var->vartype), + NULL, + (Index) 0, + (Oid) 0, + 0); + tlelement->expr = (Node *) var; + + return (tlelement); } -/* +/* * get-actual-tlist-- - * Returns the targetlist elements from a relation tlist. - * + * Returns the targetlist elements from a relation tlist. + * */ -List * -get_actual_tlist(List *tlist) +List * +get_actual_tlist(List * tlist) { - /* - * this function is not making sense. - ay 10/94 - */ -#if 0 - List *element = NIL; - List *result = NIL; - - if (tlist==NULL) { - elog(DEBUG,"calling get_actual_tlist with empty tlist"); - return(NIL); - } - /* XXX - it is unclear to me what exactly get_entry - should be doing, as it is unclear to me the exact - relationship between "TL" "TLE" and joinlists */ - - foreach(element,tlist) - result = lappend(result, lfirst((List*)lfirst(element))); - - return(result); + + /* + * this function is not making sense. - ay 10/94 + */ +#if 0 + List *element = NIL; + List *result = NIL; + + if (tlist == NULL) + { + elog(DEBUG, "calling get_actual_tlist with empty tlist"); + return (NIL); + } + + /* + * XXX - it is unclear to me what exactly get_entry should be doing, + * as it is unclear to me the exact relationship between "TL" "TLE" + * and joinlists + */ + + foreach(element, tlist) + result = lappend(result, lfirst((List *) lfirst(element))); + + return (result); #endif - return tlist; + return tlist; } /***************************************************************************** - * ---------- GENERAL target list routines ---------- + * ---------- GENERAL target list routines ---------- *****************************************************************************/ -/* +/* * tlist-member-- - * Determines whether a var node is already contained within a - * target list. - * + * Determines whether a var node is already contained within a + * target list. + * * 'var' is the var node * 'tlist' is the target list * 'dots' is t if we must match dotfields to determine uniqueness - * + * * Returns the resdom entry of the matching var node. - * + * */ -Resdom * -tlist_member(Var *var, List *tlist) +Resdom * +tlist_member(Var * var, List * tlist) { - List *i = NIL; - TargetEntry *temp_tle = (TargetEntry *)NULL; - TargetEntry *tl_elt = (TargetEntry *)NULL; - - if (var) { - foreach (i,tlist) { - temp_tle = (TargetEntry *)lfirst(i); - if (var_equal(var, get_expr(temp_tle))) { - tl_elt = temp_tle; - break; - } + List *i = NIL; + TargetEntry *temp_tle = (TargetEntry *) NULL; + TargetEntry *tl_elt = (TargetEntry *) NULL; + + if (var) + { + foreach(i, tlist) + { + temp_tle = (TargetEntry *) lfirst(i); + if (var_equal(var, get_expr(temp_tle))) + { + tl_elt = temp_tle; + break; + } + } + + if (tl_elt != NULL) + return (tl_elt->resdom); + else + return ((Resdom *) NULL); } - - if (tl_elt != NULL) - return(tl_elt->resdom); - else - return((Resdom*)NULL); - } - return ((Resdom*)NULL); + return ((Resdom *) NULL); } /* - * Routine to get the resdom out of a targetlist. + * Routine to get the resdom out of a targetlist. */ -Resdom * -tlist_resdom(List *tlist, Resdom *resnode) +Resdom * +tlist_resdom(List * tlist, Resdom * resnode) { - Resdom *resdom = (Resdom*)NULL; - List *i = NIL; - TargetEntry *temp_tle = (TargetEntry *)NULL; - - foreach(i,tlist) { - temp_tle = (TargetEntry *)lfirst(i); - resdom = temp_tle->resdom; - /* Since resnos are supposed to be unique */ - if (resnode->resno == resdom->resno) - return(resdom); - } - return((Resdom*)NULL); + Resdom *resdom = (Resdom *) NULL; + List *i = NIL; + TargetEntry *temp_tle = (TargetEntry *) NULL; + + foreach(i, tlist) + { + temp_tle = (TargetEntry *) lfirst(i); + resdom = temp_tle->resdom; + /* Since resnos are supposed to be unique */ + if (resnode->resno == resdom->resno) + return (resdom); + } + return ((Resdom *) NULL); } -/* +/* * match_varid-- - * Searches a target list for an entry with some desired varid. - * + * Searches a target list for an entry with some desired varid. + * * 'varid' is the desired id * 'tlist' is the target list that is searched - * + * * Returns the target list entry (resdom var) of the matching var. * * Now checks to make sure array references (in addition to range * table indices) are identical - retrieve (a.b[1],a.b[2]) should * not be turned into retrieve (a.b[1],a.b[1]). - * + * * [what used to be varid is now broken up into two fields varnoold and - * varoattno. Also, nested attnos are long gone. - ay 2/95] + * varoattno. Also, nested attnos are long gone. - ay 2/95] */ -TargetEntry * -match_varid(Var *test_var, List *tlist) +TargetEntry * +match_varid(Var * test_var, List * tlist) { - List *tl; - Oid type_var; + List *tl; + Oid type_var; - type_var = (Oid) test_var->vartype; + type_var = (Oid) test_var->vartype; - foreach (tl, tlist) { - TargetEntry *entry; - Var *tlvar; + foreach(tl, tlist) + { + TargetEntry *entry; + Var *tlvar; - entry = lfirst(tl); - tlvar = get_expr(entry); - - if ( !IsA (tlvar, Var) ) - continue; + entry = lfirst(tl); + tlvar = get_expr(entry); - /* - * we test the original varno (instead of varno which might - * be changed to INNER/OUTER. - */ - if (tlvar->varnoold == test_var->varnoold && - tlvar->varoattno == test_var->varoattno) { + if (!IsA(tlvar, Var)) + continue; + + /* + * we test the original varno (instead of varno which might be + * changed to INNER/OUTER. + */ + if (tlvar->varnoold == test_var->varnoold && + tlvar->varoattno == test_var->varoattno) + { - if (tlvar->vartype == type_var) - return(entry); + if (tlvar->vartype == type_var) + return (entry); + } } - } - return (NULL); + return (NULL); } -/* +/* * new-unsorted-tlist-- - * Creates a copy of a target list by creating new resdom nodes - * without sort information. - * + * Creates a copy of a target list by creating new resdom nodes + * without sort information. + * * 'targetlist' is the target list to be copied. - * + * * Returns the resulting target list. - * + * */ -List * -new_unsorted_tlist(List *targetlist) +List * +new_unsorted_tlist(List * targetlist) { - List *new_targetlist = (List*)copyObject ((Node*)targetlist); - List *x = NIL; - - foreach (x, new_targetlist) { - TargetEntry *tle = (TargetEntry *)lfirst(x); - tle->resdom->reskey = 0; - tle->resdom->reskeyop = (Oid)0; - } - return(new_targetlist); + List *new_targetlist = (List *) copyObject((Node *) targetlist); + List *x = NIL; + + foreach(x, new_targetlist) + { + TargetEntry *tle = (TargetEntry *) lfirst(x); + + tle->resdom->reskey = 0; + tle->resdom->reskeyop = (Oid) 0; + } + return (new_targetlist); } -/* +/* * copy-vars-- - * Replaces the var nodes in the first target list with those from - * the second target list. The two target lists are assumed to be - * identical except their actual resdoms and vars are different. - * + * Replaces the var nodes in the first target list with those from + * the second target list. The two target lists are assumed to be + * identical except their actual resdoms and vars are different. + * * 'target' is the target list to be replaced * 'source' is the target list to be copied - * + * * Returns a new target list. - * + * */ -List * -copy_vars(List *target, List *source) +List * +copy_vars(List * target, List * source) { - List *result = NIL; - List *src = NIL; - List *dest = NIL; - - for ( src = source, dest = target; src != NIL && - dest != NIL; src = lnext(src), dest = lnext(dest)) { - TargetEntry *temp = MakeTLE(((TargetEntry *)lfirst(dest))->resdom, - (Node*)get_expr(lfirst(src))); - result = lappend(result,temp); - } - return(result); + List *result = NIL; + List *src = NIL; + List *dest = NIL; + + for (src = source, dest = target; src != NIL && + dest != NIL; src = lnext(src), dest = lnext(dest)) + { + TargetEntry *temp = MakeTLE(((TargetEntry *) lfirst(dest))->resdom, + (Node *) get_expr(lfirst(src))); + + result = lappend(result, temp); + } + return (result); } -/* +/* * flatten-tlist-- - * Create a target list that only contains unique variables. + * Create a target list that only contains unique variables. * * * 'tlist' is the current target list - * + * * Returns the "flattened" new target list. - * + * */ -List * -flatten_tlist(List *tlist) +List * +flatten_tlist(List * tlist) { - int last_resdomno = 1; - List *new_tlist = NIL; - List *tlist_vars = NIL; - List *temp; - - foreach (temp, tlist) { - TargetEntry *temp_entry = NULL; - List *vars; - - temp_entry = lfirst(temp); - vars = pull_var_clause((Node*)get_expr(temp_entry)); - if(vars != NULL) { - tlist_vars = nconc(tlist_vars, vars); + int last_resdomno = 1; + List *new_tlist = NIL; + List *tlist_vars = NIL; + List *temp; + + foreach(temp, tlist) + { + TargetEntry *temp_entry = NULL; + List *vars; + + temp_entry = lfirst(temp); + vars = pull_var_clause((Node *) get_expr(temp_entry)); + if (vars != NULL) + { + tlist_vars = nconc(tlist_vars, vars); + } } - } - - foreach (temp, tlist_vars) { - Var *var = lfirst(temp); - if (!(tlist_member(var, new_tlist))) { - Resdom *r; - - r = makeResdom(last_resdomno, - var->vartype, - get_typlen(var->vartype), - NULL, - (Index)0, - (Oid)0, - 0); - last_resdomno++; - new_tlist = lappend(new_tlist, MakeTLE (r, (Node*)var)); + + foreach(temp, tlist_vars) + { + Var *var = lfirst(temp); + + if (!(tlist_member(var, new_tlist))) + { + Resdom *r; + + r = makeResdom(last_resdomno, + var->vartype, + get_typlen(var->vartype), + NULL, + (Index) 0, + (Oid) 0, + 0); + last_resdomno++; + new_tlist = lappend(new_tlist, MakeTLE(r, (Node *) var)); + } } - } - return new_tlist; + return new_tlist; } -/* +/* * flatten-tlist-vars-- - * Redoes the target list of a query with no nested attributes by - * replacing vars within computational expressions with vars from - * the 'flattened' target list of the query. - * + * Redoes the target list of a query with no nested attributes by + * replacing vars within computational expressions with vars from + * the 'flattened' target list of the query. + * * 'full-tlist' is the actual target list * 'flat-tlist' is the flattened (var-only) target list - * + * * Returns the modified actual target list. - * + * */ -List * -flatten_tlist_vars(List *full_tlist, List *flat_tlist) +List * +flatten_tlist_vars(List * full_tlist, List * flat_tlist) { - List *x = NIL; - List *result = NIL; - - foreach(x,full_tlist) { - TargetEntry *tle= lfirst(x); - result = - lappend(result, - MakeTLE(tle->resdom, - flatten_tlistentry((Node*)get_expr(tle), - flat_tlist))); - } - - return(result); + List *x = NIL; + List *result = NIL; + + foreach(x, full_tlist) + { + TargetEntry *tle = lfirst(x); + + result = + lappend(result, + MakeTLE(tle->resdom, + flatten_tlistentry((Node *) get_expr(tle), + flat_tlist))); + } + + return (result); } -/* +/* * flatten-tlistentry-- - * Replaces vars within a target list entry with vars from a flattened - * target list. - * + * Replaces vars within a target list entry with vars from a flattened + * target list. + * * 'tlistentry' is the target list entry to be modified * 'flat-tlist' is the flattened target list - * + * * Returns the (modified) target_list entry from the target list. - * + * */ -static Node * -flatten_tlistentry(Node *tlistentry, List *flat_tlist) +static Node * +flatten_tlistentry(Node * tlistentry, List * flat_tlist) { - if (tlistentry==NULL) { - - return NULL; - - } else if (IsA (tlistentry,Var)) { - - return - ((Node *)get_expr(match_varid((Var*)tlistentry, - flat_tlist))); - } else if (IsA (tlistentry,Iter)) { - - ((Iter*)tlistentry)->iterexpr = - flatten_tlistentry((Node*)((Iter*)tlistentry)->iterexpr, - flat_tlist); - return tlistentry; - - } else if (single_node(tlistentry)) { - - return tlistentry; - - } else if (is_funcclause (tlistentry)) { - Expr *expr = (Expr*)tlistentry; - List *temp_result = NIL; - List *elt = NIL; - - foreach(elt, expr->args) - temp_result = lappend(temp_result, - flatten_tlistentry(lfirst(elt),flat_tlist)); - - return - ((Node *)make_funcclause((Func*)expr->oper, temp_result)); - - } else if (IsA(tlistentry,Aggreg)) { - - return tlistentry; - - } else if (IsA(tlistentry,ArrayRef)) { - ArrayRef *aref = (ArrayRef *)tlistentry; - List *temp = NIL; - List *elt = NIL; - - foreach(elt, aref->refupperindexpr) - temp = lappend(temp, flatten_tlistentry(lfirst(elt), flat_tlist)); - aref->refupperindexpr = temp; - - temp = NIL; - foreach(elt, aref->reflowerindexpr) - temp = lappend(temp, flatten_tlistentry(lfirst(elt), flat_tlist)); - aref->reflowerindexpr = temp; - - aref->refexpr = - flatten_tlistentry(aref->refexpr, flat_tlist); - - aref->refassgnexpr = - flatten_tlistentry(aref->refassgnexpr, flat_tlist); - - return tlistentry; - } else { - Expr *expr = (Expr*)tlistentry; - Var *left = - (Var*)flatten_tlistentry((Node*)get_leftop(expr), - flat_tlist); - Var *right = - (Var*)flatten_tlistentry((Node*)get_rightop(expr), - flat_tlist); - - return((Node *) - make_opclause((Oper*)expr->oper, left, right)); - } + if (tlistentry == NULL) + { + + return NULL; + + } + else if (IsA(tlistentry, Var)) + { + + return + ((Node *) get_expr(match_varid((Var *) tlistentry, + flat_tlist))); + } + else if (IsA(tlistentry, Iter)) + { + + ((Iter *) tlistentry)->iterexpr = + flatten_tlistentry((Node *) ((Iter *) tlistentry)->iterexpr, + flat_tlist); + return tlistentry; + + } + else if (single_node(tlistentry)) + { + + return tlistentry; + + } + else if (is_funcclause(tlistentry)) + { + Expr *expr = (Expr *) tlistentry; + List *temp_result = NIL; + List *elt = NIL; + + foreach(elt, expr->args) + temp_result = lappend(temp_result, + flatten_tlistentry(lfirst(elt), flat_tlist)); + + return + ((Node *) make_funcclause((Func *) expr->oper, temp_result)); + + } + else if (IsA(tlistentry, Aggreg)) + { + + return tlistentry; + + } + else if (IsA(tlistentry, ArrayRef)) + { + ArrayRef *aref = (ArrayRef *) tlistentry; + List *temp = NIL; + List *elt = NIL; + + foreach(elt, aref->refupperindexpr) + temp = lappend(temp, flatten_tlistentry(lfirst(elt), flat_tlist)); + aref->refupperindexpr = temp; + + temp = NIL; + foreach(elt, aref->reflowerindexpr) + temp = lappend(temp, flatten_tlistentry(lfirst(elt), flat_tlist)); + aref->reflowerindexpr = temp; + + aref->refexpr = + flatten_tlistentry(aref->refexpr, flat_tlist); + + aref->refassgnexpr = + flatten_tlistentry(aref->refassgnexpr, flat_tlist); + + return tlistentry; + } + else + { + Expr *expr = (Expr *) tlistentry; + Var *left = + (Var *) flatten_tlistentry((Node *) get_leftop(expr), + flat_tlist); + Var *right = + (Var *) flatten_tlistentry((Node *) get_rightop(expr), + flat_tlist); + + return ((Node *) + make_opclause((Oper *) expr->oper, left, right)); + } } -TargetEntry * -MakeTLE(Resdom *resdom, Node *expr) +TargetEntry * +MakeTLE(Resdom * resdom, Node * expr) { - TargetEntry *rt = makeNode(TargetEntry); + TargetEntry *rt = makeNode(TargetEntry); - rt->resdom = resdom; - rt->expr = expr; - return rt; + rt->resdom = resdom; + rt->expr = expr; + return rt; } -Var * -get_expr(TargetEntry *tle) +Var * +get_expr(TargetEntry * tle) { - Assert(tle!=NULL); - Assert(tle->expr!=NULL); + Assert(tle != NULL); + Assert(tle->expr != NULL); - return ((Var *)tle->expr); + return ((Var *) tle->expr); } @@ -529,54 +569,56 @@ get_expr(TargetEntry *tle) /* * AddGroupAttrToTlist - - * append the group attribute to the target list if it's not already - * in there. + * append the group attribute to the target list if it's not already + * in there. */ #ifdef NOT_USED void -AddGroupAttrToTlist(List *tlist, List *grpCl) +AddGroupAttrToTlist(List * tlist, List * grpCl) { - List *gl; - int last_resdomno = length(tlist) + 1; - - foreach (gl, grpCl) { - GroupClause *gc = (GroupClause*)lfirst(gl); - Var *var = gc->grpAttr; - - if (!(tlist_member(var, tlist))) { - Resdom *r; - - r = makeResdom(last_resdomno, - var->vartype, - get_typlen(var->vartype), - NULL, - (Index)0, - (Oid)0, - 0); - last_resdomno++; - tlist = lappend(tlist, MakeTLE(r, (Node*)var)); + List *gl; + int last_resdomno = length(tlist) + 1; + + foreach(gl, grpCl) + { + GroupClause *gc = (GroupClause *) lfirst(gl); + Var *var = gc->grpAttr; + + if (!(tlist_member(var, tlist))) + { + Resdom *r; + + r = makeResdom(last_resdomno, + var->vartype, + get_typlen(var->vartype), + NULL, + (Index) 0, + (Oid) 0, + 0); + last_resdomno++; + tlist = lappend(tlist, MakeTLE(r, (Node *) var)); + } } - } } + #endif -/* was ExecTargetListLength() in execQual.c, +/* was ExecTargetListLength() in execQual.c, moved here to reduce dependencies on the executor module */ int -exec_tlist_length(List *targetlist) +exec_tlist_length(List * targetlist) { - int len; - List *tl; - TargetEntry *curTle; - - len = 0; - foreach (tl, targetlist) { - curTle = lfirst(tl); - - if (curTle->resdom != NULL) - len++; - } - return len; -} + int len; + List *tl; + TargetEntry *curTle; + len = 0; + foreach(tl, targetlist) + { + curTle = lfirst(tl); + if (curTle->resdom != NULL) + len++; + } + return len; +} |