postgresql/src/backend/optimizer/util/tlist.c

243 lines
5.7 KiB
C
Raw Normal View History

/*-------------------------------------------------------------------------
*
* tlist.c
* 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.41 1999/08/26 05:09:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "nodes/makefuncs.h"
1999-07-16 07:00:38 +02:00
#include "nodes/nodeFuncs.h"
#include "optimizer/clauses.h"
#include "optimizer/tlist.h"
#include "optimizer/var.h"
/*****************************************************************************
* ---------- RELATION node target list routines ----------
*****************************************************************************/
/*
* tlistentry_member
* Finds the (first) member of the given tlist whose expression is
* equal() to the given expression. Result is NULL if no such member.
*/
TargetEntry *
tlistentry_member(Node *node, List *targetlist)
{
List *temp;
foreach(temp, targetlist)
{
TargetEntry *tlentry = (TargetEntry *) lfirst(temp);
if (equal(node, tlentry->expr))
return tlentry;
}
1998-09-01 05:29:17 +02:00
return NULL;
}
/*
* matching_tlist_expr
* Same as tlistentry_member(), except returns the tlist expression
* rather than its parent TargetEntry node.
*/
Node *
matching_tlist_expr(Node *node, List *targetlist)
{
TargetEntry *tlentry;
tlentry = tlistentry_member(node, targetlist);
if (tlentry)
return tlentry->expr;
return (Node *) NULL;
}
/*
* tlist_member
* Same as tlistentry_member(), except returns the Resdom node
* rather than its parent TargetEntry node.
*/
Resdom *
tlist_member(Node *node, List *targetlist)
{
TargetEntry *tlentry;
tlentry = tlistentry_member(node, targetlist);
if (tlentry)
return tlentry->resdom;
return (Resdom *) NULL;
}
/*
* add_var_to_tlist
* Creates a targetlist entry corresponding to the supplied var node
* 'var' and adds the new targetlist entry to the targetlist field of
* 'rel'. No entry is created if 'var' is already in the tlist.
*/
void
1999-05-26 00:43:53 +02:00
add_var_to_tlist(RelOptInfo *rel, Var *var)
{
if (! tlistentry_member((Node *) var, rel->targetlist))
{
/* XXX is copyObject necessary here? */
rel->targetlist = lappend(rel->targetlist,
create_tl_element((Var *) copyObject(var),
length(rel->targetlist) + 1));
}
}
/*
* create_tl_element
* Creates a target list entry node and its associated (resdom var) pair
* with its resdom number equal to 'resdomno'.
*/
TargetEntry *
create_tl_element(Var *var, int resdomno)
{
return makeTargetEntry(makeResdom(resdomno,
var->vartype,
var->vartypmod,
NULL,
(Index) 0,
(Oid) 0,
1999-05-17 19:03:51 +02:00
false),
(Node *) var);
}
/*****************************************************************************
* ---------- GENERAL target list routines ----------
*****************************************************************************/
/*
* new_unsorted_tlist
* 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_targetlist = (List *) copyObject((Node *) targetlist);
List *x;
foreach(x, new_targetlist)
{
TargetEntry *tle = (TargetEntry *) lfirst(x);
tle->resdom->reskey = 0;
tle->resdom->reskeyop = (Oid) 0;
}
1998-09-01 05:29:17 +02:00
return new_targetlist;
}
/*
* flatten_tlist
* Create a target list that only contains unique variables.
*
* Note that Vars with varlevelsup > 0 are not included in the output
* tlist. We expect that those will eventually be replaced with Params,
* but that probably has not happened at the time this routine is called.
*
* 'tlist' is the current target list
*
* Returns the "flattened" new target list.
*
* The result is entirely new structure sharing no nodes with the original.
* Copying the Var nodes is probably overkill, but be safe for now.
*/
List *
flatten_tlist(List *tlist)
{
List *vlist = pull_var_clause((Node *) tlist, false);
List *new_tlist;
new_tlist = add_to_flat_tlist(NIL, vlist);
freeList(vlist);
return new_tlist;
}
/*
* add_to_flat_tlist
* Add more vars to a flattened tlist (if they're not already in it)
*
* 'tlist' is the flattened tlist
* 'vars' is a list of var nodes
*
* Returns the extended tlist.
*/
List *
add_to_flat_tlist(List *tlist, List *vars)
{
int next_resdomno = length(tlist) + 1;
List *v;
foreach(v, vars)
{
Var *var = lfirst(v);
if (! tlistentry_member((Node *) var, tlist))
{
Resdom *r;
r = makeResdom(next_resdomno++,
var->vartype,
var->vartypmod,
NULL,
(Index) 0,
(Oid) 0,
false);
tlist = lappend(tlist,
makeTargetEntry(r, copyObject(var)));
}
}
return tlist;
}
Var *
get_expr(TargetEntry *tle)
{
Assert(tle != NULL);
Assert(tle->expr != NULL);
1998-09-01 05:29:17 +02:00
return (Var *) tle->expr;
}
/*
* get_sortgroupclause_expr
* Find the targetlist entry matching the given SortClause
* (or GroupClause) by ressortgroupref, and return its expression.
*
* Because GroupClause is typedef'd as SortClause, either kind of
* node can be passed without casting.
*/
Node *
get_sortgroupclause_expr(SortClause *sortClause, List *targetList)
{
Index refnumber = sortClause->tleSortGroupRef;
1999-05-25 18:15:34 +02:00
List *l;
foreach(l, targetList)
{
TargetEntry *tle = (TargetEntry *) lfirst(l);
if (tle->resdom->ressortgroupref == refnumber)
return tle->expr;
}
elog(ERROR, "get_sortgroupclause_expr: ORDER/GROUP BY expression not found in targetlist");
return NULL; /* keep compiler quiet */
}