1996-07-09 08:22:35 +02:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
1999-02-14 00:22:53 +01:00
|
|
|
* tlist.c
|
1997-09-07 07:04:48 +02:00
|
|
|
* Target list manipulation routines
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
2004-12-31 23:04:05 +01:00
|
|
|
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
2000-01-26 06:58:53 +01:00
|
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*
|
|
|
|
* IDENTIFICATION
|
2004-12-31 23:04:05 +01:00
|
|
|
* $PostgreSQL: pgsql/src/backend/optimizer/util/tlist.c,v 1.68 2004/12/31 22:00:23 pgsql Exp $
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
#include "postgres.h"
|
|
|
|
|
|
|
|
#include "nodes/makefuncs.h"
|
1999-07-16 07:00:38 +02:00
|
|
|
#include "optimizer/tlist.h"
|
|
|
|
#include "optimizer/var.h"
|
2004-06-05 03:55:05 +02:00
|
|
|
#include "parser/parse_expr.h"
|
1996-07-09 08:22:35 +02:00
|
|
|
|
2000-06-09 00:38:00 +02:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
/*****************************************************************************
|
2003-06-30 01:05:05 +02:00
|
|
|
* Target list creation and searching utilities
|
1996-07-09 08:22:35 +02:00
|
|
|
*****************************************************************************/
|
|
|
|
|
1997-09-07 07:04:48 +02:00
|
|
|
/*
|
1999-02-14 00:22:53 +01:00
|
|
|
* tlistentry_member
|
1999-08-09 07:34:13 +02:00
|
|
|
* Finds the (first) member of the given tlist whose expression is
|
2000-04-12 19:17:23 +02:00
|
|
|
* equal() to the given expression. Result is NULL if no such member.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
2001-01-09 04:48:51 +01:00
|
|
|
TargetEntry *
|
1999-08-22 22:15:04 +02:00
|
|
|
tlistentry_member(Node *node, List *targetlist)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2004-05-26 06:41:50 +02:00
|
|
|
ListCell *temp;
|
1999-08-22 22:15:04 +02:00
|
|
|
|
|
|
|
foreach(temp, targetlist)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2000-04-12 19:17:23 +02:00
|
|
|
TargetEntry *tlentry = (TargetEntry *) lfirst(temp);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1999-08-22 22:15:04 +02:00
|
|
|
if (equal(node, tlentry->expr))
|
|
|
|
return tlentry;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
1998-09-01 05:29:17 +02:00
|
|
|
return NULL;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
2000-06-09 00:38:00 +02:00
|
|
|
#ifdef NOT_USED
|
1997-09-07 07:04:48 +02:00
|
|
|
/*
|
1999-08-22 22:15:04 +02:00
|
|
|
* matching_tlist_expr
|
1999-08-09 07:34:13 +02:00
|
|
|
* Same as tlistentry_member(), except returns the tlist expression
|
|
|
|
* rather than its parent TargetEntry node.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
1999-08-22 22:15:04 +02:00
|
|
|
Node *
|
|
|
|
matching_tlist_expr(Node *node, List *targetlist)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
TargetEntry *tlentry;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1999-08-22 22:15:04 +02:00
|
|
|
tlentry = tlistentry_member(node, targetlist);
|
1997-09-07 07:04:48 +02:00
|
|
|
if (tlentry)
|
1999-08-22 22:15:04 +02:00
|
|
|
return tlentry->expr;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
2004-01-07 19:56:30 +01:00
|
|
|
return NULL;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
2000-06-09 00:38:00 +02:00
|
|
|
#endif
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1999-08-09 07:34:13 +02:00
|
|
|
/*
|
|
|
|
* tlist_member
|
|
|
|
* Same as tlistentry_member(), except returns the Resdom node
|
|
|
|
* rather than its parent TargetEntry node.
|
|
|
|
*/
|
|
|
|
Resdom *
|
1999-08-22 22:15:04 +02:00
|
|
|
tlist_member(Node *node, List *targetlist)
|
1999-08-09 07:34:13 +02:00
|
|
|
{
|
|
|
|
TargetEntry *tlentry;
|
|
|
|
|
1999-08-22 22:15:04 +02:00
|
|
|
tlentry = tlistentry_member(node, targetlist);
|
1999-08-09 07:34:13 +02:00
|
|
|
if (tlentry)
|
|
|
|
return tlentry->resdom;
|
|
|
|
|
2004-01-07 19:56:30 +01:00
|
|
|
return NULL;
|
1999-08-09 07:34:13 +02:00
|
|
|
}
|
|
|
|
|
1997-09-07 07:04:48 +02:00
|
|
|
/*
|
1999-02-14 00:22:53 +01:00
|
|
|
* create_tl_element
|
1997-09-07 07:04:48 +02:00
|
|
|
* Creates a target list entry node and its associated (resdom var) pair
|
1999-08-09 07:34:13 +02:00
|
|
|
* with its resdom number equal to 'resdomno'.
|
2004-06-05 03:55:05 +02:00
|
|
|
*
|
|
|
|
* Note: the argument is almost always a Var, but occasionally not.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
1997-09-08 04:41:22 +02:00
|
|
|
TargetEntry *
|
1997-09-08 23:56:23 +02:00
|
|
|
create_tl_element(Var *var, int resdomno)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2004-08-29 07:07:03 +02:00
|
|
|
Oid vartype;
|
|
|
|
int32 vartypmod;
|
2004-06-05 03:55:05 +02:00
|
|
|
|
|
|
|
if (IsA(var, Var))
|
|
|
|
{
|
|
|
|
vartype = var->vartype;
|
|
|
|
vartypmod = var->vartypmod;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
vartype = exprType((Node *) var);
|
|
|
|
vartypmod = exprTypmod((Node *) var);
|
|
|
|
}
|
1998-09-01 06:40:42 +02:00
|
|
|
return makeTargetEntry(makeResdom(resdomno,
|
2004-06-05 03:55:05 +02:00
|
|
|
vartype,
|
|
|
|
vartypmod,
|
1998-09-01 06:40:42 +02:00
|
|
|
NULL,
|
1999-05-17 19:03:51 +02:00
|
|
|
false),
|
2002-12-12 16:49:42 +01:00
|
|
|
(Expr *) var);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************
|
1997-09-07 07:04:48 +02:00
|
|
|
* ---------- GENERAL target list routines ----------
|
1996-07-09 08:22:35 +02:00
|
|
|
*****************************************************************************/
|
|
|
|
|
1997-09-07 07:04:48 +02:00
|
|
|
/*
|
1999-02-14 00:22:53 +01:00
|
|
|
* flatten_tlist
|
1997-09-07 07:04:48 +02:00
|
|
|
* Create a target list that only contains unique variables.
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
1999-08-26 07:09:06 +02:00
|
|
|
* 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.
|
|
|
|
*
|
1996-07-09 08:22:35 +02:00
|
|
|
* 'tlist' is the current target list
|
1997-09-07 07:04:48 +02:00
|
|
|
*
|
1996-07-09 08:22:35 +02:00
|
|
|
* Returns the "flattened" new target list.
|
1997-09-07 07:04:48 +02:00
|
|
|
*
|
1999-08-21 05:49:17 +02:00
|
|
|
* The result is entirely new structure sharing no nodes with the original.
|
|
|
|
* Copying the Var nodes is probably overkill, but be safe for now.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
1998-02-26 05:46:47 +01:00
|
|
|
List *
|
1997-09-08 23:56:23 +02:00
|
|
|
flatten_tlist(List *tlist)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1999-08-26 07:09:06 +02:00
|
|
|
List *vlist = pull_var_clause((Node *) tlist, false);
|
1999-08-21 05:49:17 +02:00
|
|
|
List *new_tlist;
|
|
|
|
|
|
|
|
new_tlist = add_to_flat_tlist(NIL, vlist);
|
2004-05-31 01:40:41 +02:00
|
|
|
list_free(vlist);
|
1999-08-21 05:49:17 +02:00
|
|
|
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)
|
|
|
|
{
|
2004-05-31 01:40:41 +02:00
|
|
|
int next_resdomno = list_length(tlist) + 1;
|
2004-05-26 06:41:50 +02:00
|
|
|
ListCell *v;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1999-08-21 05:49:17 +02:00
|
|
|
foreach(v, vars)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2004-05-26 06:41:50 +02:00
|
|
|
Var *var = (Var *) lfirst(v);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2000-04-12 19:17:23 +02:00
|
|
|
if (!tlistentry_member((Node *) var, tlist))
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
1999-08-10 05:00:15 +02:00
|
|
|
Resdom *r;
|
|
|
|
|
1999-08-21 05:49:17 +02:00
|
|
|
r = makeResdom(next_resdomno++,
|
1999-08-10 05:00:15 +02:00
|
|
|
var->vartype,
|
|
|
|
var->vartypmod,
|
|
|
|
NULL,
|
|
|
|
false);
|
1999-08-21 05:49:17 +02:00
|
|
|
tlist = lappend(tlist,
|
|
|
|
makeTargetEntry(r, copyObject(var)));
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
1999-08-21 05:49:17 +02:00
|
|
|
return tlist;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
1999-08-21 05:49:17 +02:00
|
|
|
/*
|
2000-01-27 19:11:50 +01:00
|
|
|
* get_sortgroupclause_tle
|
1999-08-21 05:49:17 +02:00
|
|
|
* Find the targetlist entry matching the given SortClause
|
2000-01-27 19:11:50 +01:00
|
|
|
* (or GroupClause) by ressortgroupref, and return it.
|
1999-08-21 05:49:17 +02:00
|
|
|
*
|
|
|
|
* Because GroupClause is typedef'd as SortClause, either kind of
|
|
|
|
* node can be passed without casting.
|
|
|
|
*/
|
2000-01-27 19:11:50 +01:00
|
|
|
TargetEntry *
|
|
|
|
get_sortgroupclause_tle(SortClause *sortClause,
|
|
|
|
List *targetList)
|
1999-05-12 17:02:39 +02:00
|
|
|
{
|
1999-08-21 05:49:17 +02:00
|
|
|
Index refnumber = sortClause->tleSortGroupRef;
|
2004-05-26 06:41:50 +02:00
|
|
|
ListCell *l;
|
1999-05-12 17:02:39 +02:00
|
|
|
|
|
|
|
foreach(l, targetList)
|
|
|
|
{
|
1999-08-09 07:34:13 +02:00
|
|
|
TargetEntry *tle = (TargetEntry *) lfirst(l);
|
1999-08-21 05:49:17 +02:00
|
|
|
|
|
|
|
if (tle->resdom->ressortgroupref == refnumber)
|
2000-01-27 19:11:50 +01:00
|
|
|
return tle;
|
1999-05-12 17:02:39 +02:00
|
|
|
}
|
|
|
|
|
2003-07-25 02:01:09 +02:00
|
|
|
elog(ERROR, "ORDER/GROUP BY expression not found in targetlist");
|
1999-08-21 05:49:17 +02:00
|
|
|
return NULL; /* keep compiler quiet */
|
1999-05-12 17:02:39 +02:00
|
|
|
}
|
2000-01-27 19:11:50 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* 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)
|
|
|
|
{
|
|
|
|
TargetEntry *tle = get_sortgroupclause_tle(sortClause, targetList);
|
|
|
|
|
2002-12-12 16:49:42 +01:00
|
|
|
return (Node *) tle->expr;
|
2000-01-27 19:11:50 +01:00
|
|
|
}
|
2003-01-20 19:55:07 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* get_sortgrouplist_exprs
|
|
|
|
* Given a list of SortClauses (or GroupClauses), build a list
|
|
|
|
* of the referenced targetlist expressions.
|
|
|
|
*/
|
|
|
|
List *
|
|
|
|
get_sortgrouplist_exprs(List *sortClauses, List *targetList)
|
|
|
|
{
|
2003-08-04 02:43:34 +02:00
|
|
|
List *result = NIL;
|
2004-05-26 06:41:50 +02:00
|
|
|
ListCell *l;
|
2003-01-20 19:55:07 +01:00
|
|
|
|
|
|
|
foreach(l, sortClauses)
|
|
|
|
{
|
|
|
|
SortClause *sortcl = (SortClause *) lfirst(l);
|
|
|
|
Node *sortexpr;
|
|
|
|
|
|
|
|
sortexpr = get_sortgroupclause_expr(sortcl, targetList);
|
|
|
|
result = lappend(result, sortexpr);
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|