* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/common/printtup.c,v 1.87 2005/03/16 21:38:04 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/access/common/printtup.c,v 1.88 2005/04/06 16:34:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
{
/* Do we have a non-resjunk tlist item? */
while (tlist_item &&
- ((TargetEntry *) lfirst(tlist_item))->resdom->resjunk)
+ ((TargetEntry *) lfirst(tlist_item))->resjunk)
tlist_item = lnext(tlist_item);
if (tlist_item)
{
- Resdom *res = ((TargetEntry *) lfirst(tlist_item))->resdom;
+ TargetEntry *tle = (TargetEntry *) lfirst(tlist_item);
- pq_sendint(&buf, res->resorigtbl, 4);
- pq_sendint(&buf, res->resorigcol, 2);
+ pq_sendint(&buf, tle->resorigtbl, 4);
+ pq_sendint(&buf, tle->resorigcol, 2);
tlist_item = lnext(tlist_item);
}
else
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/view.c,v 1.87 2005/02/02 06:36:00 neilc Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/view.c,v 1.88 2005/04/06 16:34:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "miscadmin.h"
#include "nodes/makefuncs.h"
#include "optimizer/clauses.h"
+#include "parser/parse_expr.h"
#include "parser/parse_relation.h"
#include "rewrite/rewriteDefine.h"
#include "rewrite/rewriteManip.h"
attrList = NIL;
foreach(t, tlist)
{
- TargetEntry *entry = lfirst(t);
- Resdom *res = entry->resdom;
+ TargetEntry *tle = lfirst(t);
- if (!res->resjunk)
+ if (!tle->resjunk)
{
ColumnDef *def = makeNode(ColumnDef);
TypeName *typename = makeNode(TypeName);
- def->colname = pstrdup(res->resname);
+ def->colname = pstrdup(tle->resname);
- typename->typeid = res->restype;
- typename->typmod = res->restypmod;
+ typename->typeid = exprType((Node *) tle->expr);
+ typename->typmod = exprTypmod((Node *) tle->expr);
def->typename = typename;
def->inhcount = 0;
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/execJunk.c,v 1.48 2005/03/16 21:38:06 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/execJunk.c,v 1.49 2005/04/06 16:34:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* of some system attributes like "ctid" or rule locks.
*
* The general idea is the following: A target list consists of a list of
- * Resdom nodes & expression pairs. Each Resdom node has an attribute
- * called 'resjunk'. If the value of this attribute is true then the
+ * TargetEntry nodes containing expressions. Each TargetEntry has a field
+ * called 'resjunk'. If the value of this field is true then the
* corresponding attribute is a "junk" attribute.
*
* When we initialize a plan we call 'ExecInitJunkFilter' to create
foreach(t, targetList)
{
TargetEntry *tle = lfirst(t);
- Resdom *resdom = tle->resdom;
- if (!resdom->resjunk)
+ if (!tle->resjunk)
{
- cleanMap[cleanResno - 1] = resdom->resno;
+ cleanMap[cleanResno - 1] = tle->resno;
cleanResno++;
}
}
for (;;)
{
TargetEntry *tle = lfirst(t);
- Resdom *resdom = tle->resdom;
t = lnext(t);
- if (!resdom->resjunk)
+ if (!tle->resjunk)
{
- cleanMap[i] = resdom->resno;
+ cleanMap[i] = tle->resno;
break;
}
}
foreach(t, junkfilter->jf_targetList)
{
TargetEntry *tle = lfirst(t);
- Resdom *resdom = tle->resdom;
- if (resdom->resjunk && resdom->resname &&
- (strcmp(resdom->resname, attrName) == 0))
+ if (tle->resjunk && tle->resname &&
+ (strcmp(tle->resname, attrName) == 0))
{
/* We found it ! */
- *value = slot_getattr(slot, resdom->resno, isNull);
+ *value = slot_getattr(slot, tle->resno, isNull);
return true;
}
}
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.244 2005/03/25 21:57:58 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.245 2005/04/06 16:34:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
{
TargetEntry *tle = (TargetEntry *) lfirst(tlist);
- if (tle->resdom->resjunk)
+ if (tle->resjunk)
{
junk_filter_needed = true;
break;
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.175 2005/03/29 00:16:59 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.176 2005/04/06 16:34:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
TargetEntry *curTle = (TargetEntry *) lfirst(tl);
Assert(IsA(curTle, TargetEntry));
- if (!curTle->resdom->resjunk)
+ if (!curTle->resjunk)
len++;
}
return len;
{
GenericExprState *gstate = (GenericExprState *) lfirst(tl);
TargetEntry *tle = (TargetEntry *) gstate->xprstate.expr;
- AttrNumber resind = tle->resdom->resno - 1;
+ AttrNumber resind = tle->resno - 1;
values[resind] = ExecEvalExpr(gstate->arg,
econtext,
{
GenericExprState *gstate = (GenericExprState *) lfirst(tl);
TargetEntry *tle = (TargetEntry *) gstate->xprstate.expr;
- AttrNumber resind = tle->resdom->resno - 1;
+ AttrNumber resind = tle->resno - 1;
if (itemIsDone[resind] == ExprEndResult)
{
{
GenericExprState *gstate = (GenericExprState *) lfirst(tl);
TargetEntry *tle = (TargetEntry *) gstate->xprstate.expr;
- AttrNumber resind = tle->resdom->resno - 1;
+ AttrNumber resind = tle->resno - 1;
while (itemIsDone[resind] == ExprMultipleResult)
{
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/execTuples.c,v 1.86 2005/03/17 15:25:51 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/execTuples.c,v 1.87 2005/04/06 16:34:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
foreach(l, targetList)
{
TargetEntry *tle = lfirst(l);
- Resdom *resdom = tle->resdom;
- if (skipjunk && resdom->resjunk)
+ if (skipjunk && tle->resjunk)
continue;
TupleDescInitEntry(typeInfo,
cur_resno++,
- resdom->resname,
- resdom->restype,
- resdom->restypmod,
+ tle->resname,
+ exprType((Node *) tle->expr),
+ exprTypmod((Node *) tle->expr),
0);
}
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/execUtils.c,v 1.119 2005/03/21 01:24:03 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/execUtils.c,v 1.120 2005/04/06 16:34:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
Var *variable = (Var *) gstate->arg->expr;
AttrNumber attnum = variable->varattno;
TargetEntry *tle = (TargetEntry *) gstate->xprstate.expr;
- AttrNumber resind = tle->resdom->resno - 1;
+ AttrNumber resind = tle->resno - 1;
Assert(resind >= 0 && resind < len);
varNumbers[resind] = attnum;
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.95 2005/03/31 22:46:08 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.96 2005/04/06 16:34:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
format_type_be(rettype)),
errdetail("Final SELECT must return exactly one column.")));
- restype = ((TargetEntry *) linitial(tlist))->resdom->restype;
+ restype = exprType((Node *) ((TargetEntry *) linitial(tlist))->expr);
if (!IsBinaryCoercible(restype, rettype))
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
*/
if (tlistlen == 1)
{
- restype = ((TargetEntry *) linitial(tlist))->resdom->restype;
+ restype = exprType((Node *) ((TargetEntry *) linitial(tlist))->expr);
if (IsBinaryCoercible(restype, rettype))
return false; /* NOT returning whole tuple */
}
Oid tletype;
Oid atttype;
- if (tle->resdom->resjunk)
+ if (tle->resjunk)
continue;
do
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/nodeSubplan.c,v 1.67 2005/03/16 21:38:08 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/nodeSubplan.c,v 1.68 2005/04/06 16:34:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
/* Process lefthand argument */
exstate = (ExprState *) linitial(fstate->args);
expr = exstate->expr;
- tle = makeTargetEntry(makeResdom(i,
- exprType((Node *) expr),
- exprTypmod((Node *) expr),
- NULL,
- false),
- expr);
+ tle = makeTargetEntry(expr,
+ i,
+ NULL,
+ false);
tlestate = makeNode(GenericExprState);
tlestate->xprstate.expr = (Expr *) tle;
tlestate->xprstate.evalfunc = NULL;
/* Process righthand argument */
exstate = (ExprState *) lsecond(fstate->args);
expr = exstate->expr;
- tle = makeTargetEntry(makeResdom(i,
- exprType((Node *) expr),
- exprTypmod((Node *) expr),
- NULL,
- false),
- expr);
+ tle = makeTargetEntry(expr,
+ i,
+ NULL,
+ false);
tlestate = makeNode(GenericExprState);
tlestate->xprstate.expr = (Expr *) tle;
tlestate->xprstate.evalfunc = NULL;
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.299 2005/03/29 17:58:50 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.300 2005/04/06 16:34:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* ****************************************************************
*/
-/*
- * _copyResdom
- */
-static Resdom *
-_copyResdom(Resdom *from)
-{
- Resdom *newnode = makeNode(Resdom);
-
- COPY_SCALAR_FIELD(resno);
- COPY_SCALAR_FIELD(restype);
- COPY_SCALAR_FIELD(restypmod);
- COPY_STRING_FIELD(resname);
- COPY_SCALAR_FIELD(ressortgroupref);
- COPY_SCALAR_FIELD(resorigtbl);
- COPY_SCALAR_FIELD(resorigcol);
- COPY_SCALAR_FIELD(resjunk);
-
- return newnode;
-}
-
/*
* _copyAlias
*/
{
TargetEntry *newnode = makeNode(TargetEntry);
- COPY_NODE_FIELD(resdom);
COPY_NODE_FIELD(expr);
+ COPY_SCALAR_FIELD(resno);
+ COPY_STRING_FIELD(resname);
+ COPY_SCALAR_FIELD(ressortgroupref);
+ COPY_SCALAR_FIELD(resorigtbl);
+ COPY_SCALAR_FIELD(resorigcol);
+ COPY_SCALAR_FIELD(resjunk);
return newnode;
}
/*
* PRIMITIVE NODES
*/
- case T_Resdom:
- retval = _copyResdom(from);
- break;
case T_Alias:
retval = _copyAlias(from);
break;
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.238 2005/03/29 17:58:50 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.239 2005/04/06 16:34:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* Stuff from primnodes.h
*/
-static bool
-_equalResdom(Resdom *a, Resdom *b)
-{
- COMPARE_SCALAR_FIELD(resno);
- COMPARE_SCALAR_FIELD(restype);
- COMPARE_SCALAR_FIELD(restypmod);
- COMPARE_STRING_FIELD(resname);
- COMPARE_SCALAR_FIELD(ressortgroupref);
- COMPARE_SCALAR_FIELD(resorigtbl);
- COMPARE_SCALAR_FIELD(resorigcol);
- COMPARE_SCALAR_FIELD(resjunk);
-
- return true;
-}
-
static bool
_equalAlias(Alias *a, Alias *b)
{
static bool
_equalTargetEntry(TargetEntry *a, TargetEntry *b)
{
- COMPARE_NODE_FIELD(resdom);
COMPARE_NODE_FIELD(expr);
+ COMPARE_SCALAR_FIELD(resno);
+ COMPARE_STRING_FIELD(resname);
+ COMPARE_SCALAR_FIELD(ressortgroupref);
+ COMPARE_SCALAR_FIELD(resorigtbl);
+ COMPARE_SCALAR_FIELD(resorigcol);
+ COMPARE_SCALAR_FIELD(resjunk);
return true;
}
/*
* PRIMITIVE NODES
*/
- case T_Resdom:
- retval = _equalResdom(a, b);
- break;
case T_Alias:
retval = _equalAlias(a, b);
break;
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/nodes/makefuncs.c,v 1.46 2004/12/31 21:59:55 pgsql Exp $
+ * $PostgreSQL: pgsql/src/backend/nodes/makefuncs.c,v 1.47 2005/04/06 16:34:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
/*
* makeTargetEntry -
- * creates a TargetEntry node (contains a Resdom)
+ * creates a TargetEntry node
*/
TargetEntry *
-makeTargetEntry(Resdom *resdom, Expr *expr)
+makeTargetEntry(Expr *expr,
+ AttrNumber resno,
+ char *resname,
+ bool resjunk)
{
- TargetEntry *rt = makeNode(TargetEntry);
+ TargetEntry *tle = makeNode(TargetEntry);
- rt->resdom = resdom;
- rt->expr = expr;
- return rt;
-}
-
-/*
- * makeResdom -
- * creates a Resdom (Result Domain) node
- */
-Resdom *
-makeResdom(AttrNumber resno,
- Oid restype,
- int32 restypmod,
- char *resname,
- bool resjunk)
-{
- Resdom *resdom = makeNode(Resdom);
-
- resdom->resno = resno;
- resdom->restype = restype;
- resdom->restypmod = restypmod;
- resdom->resname = resname;
+ tle->expr = expr;
+ tle->resno = resno;
+ tle->resname = resname;
/*
* We always set these fields to 0. If the caller wants to change them
* he must do so explicitly. Few callers do that, so omitting these
* arguments reduces the chance of error.
*/
- resdom->ressortgroupref = 0;
- resdom->resorigtbl = InvalidOid;
- resdom->resorigcol = 0;
+ tle->ressortgroupref = 0;
+ tle->resorigtbl = InvalidOid;
+ tle->resorigcol = 0;
+
+ tle->resjunk = resjunk;
- resdom->resjunk = resjunk;
+ return tle;
+}
+
+/*
+ * flatCopyTargetEntry -
+ * duplicate a TargetEntry, but don't copy substructure
+ *
+ * This is commonly used when we just want to modify the resno or substitute
+ * a new expression.
+ */
+TargetEntry *
+flatCopyTargetEntry(TargetEntry *src_tle)
+{
+ TargetEntry *tle = makeNode(TargetEntry);
- return resdom;
+ Assert(IsA(src_tle, TargetEntry));
+ memcpy(tle, src_tle, sizeof(TargetEntry));
+ return tle;
}
/*
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.245 2004/12/31 21:59:55 pgsql Exp $
+ * $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.246 2005/04/06 16:34:05 tgl Exp $
*
* NOTES
* Every node type that can appear in stored rules' parsetrees *must*
*
*****************************************************************************/
-static void
-_outResdom(StringInfo str, Resdom *node)
-{
- WRITE_NODE_TYPE("RESDOM");
-
- WRITE_INT_FIELD(resno);
- WRITE_OID_FIELD(restype);
- WRITE_INT_FIELD(restypmod);
- WRITE_STRING_FIELD(resname);
- WRITE_UINT_FIELD(ressortgroupref);
- WRITE_OID_FIELD(resorigtbl);
- WRITE_INT_FIELD(resorigcol);
- WRITE_BOOL_FIELD(resjunk);
-}
-
static void
_outAlias(StringInfo str, Alias *node)
{
{
WRITE_NODE_TYPE("TARGETENTRY");
- WRITE_NODE_FIELD(resdom);
WRITE_NODE_FIELD(expr);
+ WRITE_INT_FIELD(resno);
+ WRITE_STRING_FIELD(resname);
+ WRITE_UINT_FIELD(ressortgroupref);
+ WRITE_OID_FIELD(resorigtbl);
+ WRITE_INT_FIELD(resorigcol);
+ WRITE_BOOL_FIELD(resjunk);
}
static void
case T_Hash:
_outHash(str, obj);
break;
- case T_Resdom:
- _outResdom(str, obj);
- break;
case T_Alias:
_outAlias(str, obj);
break;
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/nodes/print.c,v 1.73 2005/03/16 21:38:08 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/nodes/print.c,v 1.74 2005/04/06 16:34:05 tgl Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
{
TargetEntry *tle = (TargetEntry *) lfirst(tl);
- printf("\t%d %s\t", tle->resdom->resno,
- tle->resdom->resname ? tle->resdom->resname : "<null>");
- if (tle->resdom->ressortgroupref != 0)
- printf("(%u):\t", tle->resdom->ressortgroupref);
+ printf("\t%d %s\t", tle->resno,
+ tle->resname ? tle->resname : "<null>");
+ if (tle->ressortgroupref != 0)
+ printf("(%u):\t", tle->ressortgroupref);
else
printf(" :\t");
print_expr((Node *) tle->expr, rtable);
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.175 2004/12/31 21:59:55 pgsql Exp $
+ * $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.176 2005/04/06 16:34:05 tgl Exp $
*
* NOTES
* Path and Plan nodes do not have any readfuncs support, because we
* Stuff from primnodes.h.
*/
-/*
- * _readResdom
- */
-static Resdom *
-_readResdom(void)
-{
- READ_LOCALS(Resdom);
-
- READ_INT_FIELD(resno);
- READ_OID_FIELD(restype);
- READ_INT_FIELD(restypmod);
- READ_STRING_FIELD(resname);
- READ_UINT_FIELD(ressortgroupref);
- READ_OID_FIELD(resorigtbl);
- READ_INT_FIELD(resorigcol);
- READ_BOOL_FIELD(resjunk);
-
- READ_DONE();
-}
-
static Alias *
_readAlias(void)
{
{
READ_LOCALS(TargetEntry);
- READ_NODE_FIELD(resdom);
READ_NODE_FIELD(expr);
+ READ_INT_FIELD(resno);
+ READ_STRING_FIELD(resname);
+ READ_UINT_FIELD(ressortgroupref);
+ READ_OID_FIELD(resorigtbl);
+ READ_INT_FIELD(resorigcol);
+ READ_BOOL_FIELD(resjunk);
READ_DONE();
}
return_value = _readGroupClause();
else if (MATCH("SETOPERATIONSTMT", 16))
return_value = _readSetOperationStmt();
- else if (MATCH("RESDOM", 6))
- return_value = _readResdom();
else if (MATCH("ALIAS", 5))
return_value = _readAlias();
else if (MATCH("RANGEVAR", 8))
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/path/allpaths.c,v 1.124 2005/03/10 23:21:21 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/path/allpaths.c,v 1.125 2005/04/06 16:34:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "optimizer/var.h"
#include "parser/parsetree.h"
#include "parser/parse_clause.h"
+#include "parser/parse_expr.h"
#include "rewrite/rewriteManip.h"
{
TargetEntry *tle = (TargetEntry *) lfirst(l);
- if (tle->resdom->resjunk)
+ if (tle->resjunk)
continue; /* ignore resjunk columns */
if (colType == NULL)
elog(ERROR, "wrong number of tlist entries");
- if (tle->resdom->restype != lfirst_oid(colType))
- differentTypes[tle->resdom->resno] = true;
+ if (exprType((Node *) tle->expr) != lfirst_oid(colType))
+ differentTypes[tle->resno] = true;
colType = lnext(colType);
}
if (colType != NULL)
/* Must find the tlist element referenced by the Var */
tle = get_tle_by_resno(subquery->targetList, var->varattno);
Assert(tle != NULL);
- Assert(!tle->resdom->resjunk);
+ Assert(!tle->resjunk);
/* If subquery uses DISTINCT or DISTINCT ON, check point 3 */
if (subquery->distinctClause != NIL &&
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/path/pathkeys.c,v 1.65 2005/03/27 06:29:36 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/path/pathkeys.c,v 1.66 2005/04/06 16:34:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
{
TargetEntry *tle = (TargetEntry *) lfirst(k);
- if (!tle->resdom->resjunk &&
+ if (!tle->resjunk &&
equal(tle->expr, sub_key))
{
/* Found a representation for this sub_key */
int score;
outer_var = makeVar(rel->relid,
- tle->resdom->resno,
- tle->resdom->restype,
- tle->resdom->restypmod,
+ tle->resno,
+ exprType((Node *) tle->expr),
+ exprTypmod((Node *) tle->expr),
0);
outer_item = makePathKeyItem((Node *) outer_var,
sub_item->sortop,
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.177 2005/03/27 06:29:38 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.178 2005/04/06 16:34:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
build_relation_tlist(RelOptInfo *rel)
{
List *tlist = NIL;
- int resdomno = 1;
+ int resno = 1;
ListCell *v;
foreach(v, rel->reltargetlist)
/* Do we really need to copy here? Not sure */
Var *var = (Var *) copyObject(lfirst(v));
- tlist = lappend(tlist, create_tl_element(var, resdomno));
- resdomno++;
+ tlist = lappend(tlist, makeTargetEntry((Expr *) var,
+ resno,
+ NULL,
+ false));
+ resno++;
}
return tlist;
}
Node *uniqexpr = lfirst(l);
TargetEntry *tle;
- tle = tlistentry_member(uniqexpr, newtlist);
+ tle = tlist_member(uniqexpr, newtlist);
if (!tle)
{
- tle = makeTargetEntry(makeResdom(nextresno,
- exprType(uniqexpr),
- exprTypmod(uniqexpr),
- NULL,
- false),
- (Expr *) uniqexpr);
+ tle = makeTargetEntry((Expr *) uniqexpr,
+ nextresno,
+ NULL,
+ false);
newtlist = lappend(newtlist, tle);
nextresno++;
newitems = true;
}
- groupColIdx[groupColPos++] = tle->resdom->resno;
+ groupColIdx[groupColPos++] = tle->resno;
}
if (newitems)
{
List *keysublist = (List *) lfirst(i);
PathKeyItem *pathkey = NULL;
- Resdom *resdom = NULL;
+ TargetEntry *tle = NULL;
ListCell *j;
/*
{
pathkey = (PathKeyItem *) lfirst(j);
Assert(IsA(pathkey, PathKeyItem));
- resdom = tlist_member(pathkey->key, tlist);
- if (resdom)
+ tle = tlist_member(pathkey->key, tlist);
+ if (tle)
break;
}
- if (!resdom)
+ if (!tle)
{
/* No matching Var; look for a computable expression */
foreach(j, keysublist)
/*
* Add resjunk entry to input's tlist
*/
- resdom = makeResdom(list_length(tlist) + 1,
- exprType(pathkey->key),
- exprTypmod(pathkey->key),
- NULL,
- true);
- tlist = lappend(tlist,
- makeTargetEntry(resdom,
- (Expr *) pathkey->key));
+ tle = makeTargetEntry((Expr *) pathkey->key,
+ list_length(tlist) + 1,
+ NULL,
+ true);
+ tlist = lappend(tlist, tle);
lefttree->targetlist = tlist; /* just in case NIL before */
}
* scenarios where multiple mergejoinable clauses mention the same
* var, for example.) So enter it only once in the sort arrays.
*/
- numsortkeys = add_sort_column(resdom->resno, pathkey->sortop,
+ numsortkeys = add_sort_column(tle->resno, pathkey->sortop,
numsortkeys, sortColIdx, sortOperators);
}
* parser should have removed 'em, but no point in sorting
* redundantly.
*/
- numsortkeys = add_sort_column(tle->resdom->resno, sortcl->sortop,
+ numsortkeys = add_sort_column(tle->resno, sortcl->sortop,
numsortkeys, sortColIdx, sortOperators);
}
* parser should have removed 'em, but no point in sorting
* redundantly.
*/
- numsortkeys = add_sort_column(tle->resdom->resno, grpcl->sortop,
+ numsortkeys = add_sort_column(tle->resno, grpcl->sortop,
numsortkeys, sortColIdx, sortOperators);
grpno++;
}
SortClause *sortcl = (SortClause *) lfirst(slitem);
TargetEntry *tle = get_sortgroupclause_tle(sortcl, plan->targetlist);
- uniqColIdx[keyno++] = tle->resdom->resno;
+ uniqColIdx[keyno++] = tle->resno;
}
node->numCols = numCols;
SortClause *sortcl = (SortClause *) lfirst(slitem);
TargetEntry *tle = get_sortgroupclause_tle(sortcl, plan->targetlist);
- dupColIdx[keyno++] = tle->resdom->resno;
+ dupColIdx[keyno++] = tle->resno;
}
node->cmd = cmd;
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.181 2005/03/28 00:58:23 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.182 2005/04/06 16:34:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
Operator optup;
bool oprcanhash;
- optup = equality_oper(tle->resdom->restype, true);
+ optup = equality_oper(exprType((Node *) tle->expr), true);
if (!optup)
return false;
oprcanhash = ((Form_pg_operator) GETSTRUCT(optup))->oprcanhash;
}
if (!sl)
{
- te = makeTargetEntry(makeResdom(list_length(sub_tlist) + 1,
- exprType(groupexpr),
- exprTypmod(groupexpr),
- NULL,
- false),
- (Expr *) groupexpr);
+ te = makeTargetEntry((Expr *) groupexpr,
+ list_length(sub_tlist) + 1,
+ NULL,
+ false);
sub_tlist = lappend(sub_tlist, te);
*need_tlist_eval = true; /* it's not flat anymore */
}
/* and save its resno */
- grpColIdx[keyno++] = te->resdom->resno;
+ grpColIdx[keyno++] = te->resno;
}
}
if (!sl)
elog(ERROR, "failed to locate grouping columns");
- groupColIdx[keyno++] = te->resdom->resno;
+ groupColIdx[keyno++] = te->resno;
}
}
TargetEntry *orig_tle;
/* ignore resjunk columns in setop result */
- if (new_tle->resdom->resjunk)
+ if (new_tle->resjunk)
continue;
Assert(orig_tlist_item != NULL);
orig_tle = (TargetEntry *) lfirst(orig_tlist_item);
orig_tlist_item = lnext(orig_tlist_item);
- if (orig_tle->resdom->resjunk) /* should not happen */
+ if (orig_tle->resjunk) /* should not happen */
elog(ERROR, "resjunk output columns are not implemented");
- Assert(new_tle->resdom->resno == orig_tle->resdom->resno);
- Assert(new_tle->resdom->restype == orig_tle->resdom->restype);
- new_tle->resdom->ressortgroupref = orig_tle->resdom->ressortgroupref;
+ Assert(new_tle->resno == orig_tle->resno);
+ new_tle->ressortgroupref = orig_tle->ressortgroupref;
}
if (orig_tlist_item != NULL)
elog(ERROR, "resjunk output columns are not implemented");
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/plan/setrefs.c,v 1.105 2004/12/31 22:00:09 pgsql Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/plan/setrefs.c,v 1.106 2005/04/06 16:34:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "optimizer/planmain.h"
#include "optimizer/tlist.h"
#include "optimizer/var.h"
+#include "parser/parse_expr.h"
#include "parser/parsetree.h"
#include "utils/lsyscache.h"
subvarno,
subplan_targetlist,
tlist_has_non_vars);
- output_targetlist = lappend(output_targetlist,
- makeTargetEntry(tle->resdom,
- (Expr *) newexpr));
+ tle = flatCopyTargetEntry(tle);
+ tle->expr = (Expr *) newexpr;
+ output_targetlist = lappend(output_targetlist, tle);
}
plan->targetlist = output_targetlist;
if (IsA(node, Var))
{
Var *var = (Var *) node;
- Resdom *resdom;
+ TargetEntry *tle;
/* First look for the var in the input tlists */
- resdom = tlist_member((Node *) var, context->outer_tlist);
- if (resdom)
+ tle = tlist_member((Node *) var, context->outer_tlist);
+ if (tle)
{
Var *newvar = (Var *) copyObject(var);
newvar->varno = OUTER;
- newvar->varattno = resdom->resno;
+ newvar->varattno = tle->resno;
return (Node *) newvar;
}
- resdom = tlist_member((Node *) var, context->inner_tlist);
- if (resdom)
+ tle = tlist_member((Node *) var, context->inner_tlist);
+ if (tle)
{
Var *newvar = (Var *) copyObject(var);
newvar->varno = INNER;
- newvar->varattno = resdom->resno;
+ newvar->varattno = tle->resno;
return (Node *) newvar;
}
/* Try matching more complex expressions too, if tlists have any */
if (context->tlists_have_non_vars)
{
- Resdom *resdom;
+ TargetEntry *tle;
- resdom = tlist_member(node, context->outer_tlist);
- if (resdom)
+ tle = tlist_member(node, context->outer_tlist);
+ if (tle)
{
/* Found a matching subplan output expression */
Var *newvar;
newvar = makeVar(OUTER,
- resdom->resno,
- resdom->restype,
- resdom->restypmod,
+ tle->resno,
+ exprType((Node *) tle->expr),
+ exprTypmod((Node *) tle->expr),
0);
newvar->varnoold = 0; /* wasn't ever a plain Var */
newvar->varoattno = 0;
return (Node *) newvar;
}
- resdom = tlist_member(node, context->inner_tlist);
- if (resdom)
+ tle = tlist_member(node, context->inner_tlist);
+ if (tle)
{
/* Found a matching subplan output expression */
Var *newvar;
newvar = makeVar(INNER,
- resdom->resno,
- resdom->restype,
- resdom->restypmod,
+ tle->resno,
+ exprType((Node *) tle->expr),
+ exprTypmod((Node *) tle->expr),
0);
newvar->varnoold = 0; /* wasn't ever a plain Var */
newvar->varoattno = 0;
if (IsA(node, Var))
{
Var *var = (Var *) node;
- Resdom *resdom;
+ TargetEntry *tle;
Var *newvar;
- resdom = tlist_member((Node *) var, context->subplan_targetlist);
- if (!resdom)
+ tle = tlist_member((Node *) var, context->subplan_targetlist);
+ if (!tle)
elog(ERROR, "variable not found in subplan target list");
newvar = (Var *) copyObject(var);
newvar->varno = context->subvarno;
- newvar->varattno = resdom->resno;
+ newvar->varattno = tle->resno;
return (Node *) newvar;
}
/* Try matching more complex expressions too, if tlist has any */
if (context->tlist_has_non_vars)
{
- Resdom *resdom;
+ TargetEntry *tle;
- resdom = tlist_member(node, context->subplan_targetlist);
- if (resdom)
+ tle = tlist_member(node, context->subplan_targetlist);
+ if (tle)
{
/* Found a matching subplan output expression */
Var *newvar;
newvar = makeVar(context->subvarno,
- resdom->resno,
- resdom->restype,
- resdom->restypmod,
+ tle->resno,
+ exprType((Node *) tle->expr),
+ exprTypmod((Node *) tle->expr),
0);
newvar->varnoold = 0; /* wasn't ever a plain Var */
newvar->varoattno = 0;
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.94 2004/12/31 22:00:09 pgsql Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.95 2005/04/06 16:34:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
TargetEntry *te = linitial(plan->targetlist);
Param *prm;
- Assert(!te->resdom->resjunk);
- prm = generate_new_param(te->resdom->restype, te->resdom->restypmod);
+ Assert(!te->resjunk);
+ prm = generate_new_param(exprType((Node *) te->expr),
+ exprTypmod((Node *) te->expr));
node->setParam = list_make1_int(prm->paramid);
PlannerInitPlan = lappend(PlannerInitPlan, node);
result = (Node *) prm;
Oid arraytype;
Param *prm;
- Assert(!te->resdom->resjunk);
- arraytype = get_array_type(te->resdom->restype);
+ Assert(!te->resjunk);
+ arraytype = get_array_type(exprType((Node *) te->expr));
if (!OidIsValid(arraytype))
elog(ERROR, "could not find array type for datatype %s",
- format_type_be(te->resdom->restype));
+ format_type_be(exprType((Node *) te->expr)));
prm = generate_new_param(arraytype, -1);
node->setParam = list_make1_int(prm->paramid);
PlannerInitPlan = lappend(PlannerInitPlan, node);
Node *rightop;
Operator tup;
- Assert(!te->resdom->resjunk);
+ Assert(!te->resjunk);
if (rtindex)
{
/* Make the Var node representing the subplan's result */
rightop = (Node *) makeVar(rtindex,
- te->resdom->resno,
- te->resdom->restype,
- te->resdom->restypmod,
+ te->resno,
+ exprType((Node *) te->expr),
+ exprTypmod((Node *) te->expr),
0);
/*
/* Make the Param node representing the subplan's result */
Param *prm;
- prm = generate_new_param(te->resdom->restype,
- te->resdom->restypmod);
+ prm = generate_new_param(exprType((Node *) te->expr),
+ exprTypmod((Node *) te->expr));
/* Record its ID */
*righthandIds = lappend_int(*righthandIds, prm->paramid);
rightop = (Node *) prm;
leftop,
rightop,
exprType(leftop),
- te->resdom->restype));
+ exprType((Node *) te->expr)));
ReleaseSysCache(tup);
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/prep/prepjointree.c,v 1.25 2004/12/31 22:00:20 pgsql Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/prep/prepjointree.c,v 1.26 2005/04/06 16:34:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
TargetEntry *tle = (TargetEntry *) lfirst(l);
/* ignore resjunk columns */
- if (tle->resdom->resjunk)
+ if (tle->resjunk)
continue;
/* Must contain a Var of current level */
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/prep/preptlist.c,v 1.73 2005/03/17 23:44:52 neilc Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/prep/preptlist.c,v 1.74 2005/04/06 16:34:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
*/
if (command_type == CMD_UPDATE || command_type == CMD_DELETE)
{
- Resdom *resdom;
+ TargetEntry *tle;
Var *var;
- resdom = makeResdom(list_length(tlist) + 1,
- TIDOID,
- -1,
- pstrdup("ctid"),
- true);
-
var = makeVar(result_relation, SelfItemPointerAttributeNumber,
TIDOID, -1, 0);
+ tle = makeTargetEntry((Expr *) var,
+ list_length(tlist) + 1,
+ pstrdup("ctid"),
+ true);
+
/*
* For an UPDATE, expand_targetlist already created a fresh tlist.
* For DELETE, better do a listCopy so that we don't destructively
if (command_type == CMD_DELETE)
tlist = list_copy(tlist);
- tlist = lappend(tlist, makeTargetEntry(resdom, (Expr *) var));
+ tlist = lappend(tlist, tle);
}
/*
foreach(l, parse->rowMarks)
{
Index rti = lfirst_int(l);
- char *resname;
- Resdom *resdom;
Var *var;
- TargetEntry *ctid;
-
- resname = (char *) palloc(32);
- snprintf(resname, 32, "ctid%u", rti);
- resdom = makeResdom(list_length(tlist) + 1,
- TIDOID,
- -1,
- resname,
- true);
+ char *resname;
+ TargetEntry *tle;
var = makeVar(rti,
SelfItemPointerAttributeNumber,
-1,
0);
- ctid = makeTargetEntry(resdom, (Expr *) var);
- tlist = lappend(tlist, ctid);
+ resname = (char *) palloc(32);
+ snprintf(resname, 32, "ctid%u", rti);
+
+ tle = makeTargetEntry((Expr *) var,
+ list_length(tlist) + 1,
+ resname,
+ true);
+
+ tlist = lappend(tlist, tle);
}
}
if (tlist_item != NULL)
{
TargetEntry *old_tle = (TargetEntry *) lfirst(tlist_item);
- Resdom *resdom = old_tle->resdom;
- if (!resdom->resjunk && resdom->resno == attrno)
+ if (!old_tle->resjunk && old_tle->resno == attrno)
{
new_tle = old_tle;
tlist_item = lnext(tlist_item);
(Datum) 0,
true, /* isnull */
true /* byval */ );
- /* label resdom with INT4, too */
- atttype = INT4OID;
- atttypmod = -1;
}
break;
case CMD_UPDATE:
(Datum) 0,
true, /* isnull */
true /* byval */ );
- /* label resdom with INT4, too */
- atttype = INT4OID;
- atttypmod = -1;
}
break;
default:
break;
}
- new_tle = makeTargetEntry(makeResdom(attrno,
- atttype,
- atttypmod,
+ new_tle = makeTargetEntry((Expr *) new_expr,
+ attrno,
pstrdup(NameStr(att_tup->attname)),
- false),
- (Expr *) new_expr);
+ false);
}
new_tlist = lappend(new_tlist, new_tle);
while (tlist_item)
{
TargetEntry *old_tle = (TargetEntry *) lfirst(tlist_item);
- Resdom *resdom = old_tle->resdom;
- if (!resdom->resjunk)
+ if (!old_tle->resjunk)
elog(ERROR, "targetlist is not sorted correctly");
/* Get the resno right, but don't copy unnecessarily */
- if (resdom->resno != attrno)
+ if (old_tle->resno != attrno)
{
- resdom = (Resdom *) copyObject((Node *) resdom);
- resdom->resno = attrno;
- old_tle = makeTargetEntry(resdom, old_tle->expr);
+ old_tle = flatCopyTargetEntry(old_tle);
+ old_tle->resno = attrno;
}
new_tlist = lappend(new_tlist, old_tle);
attrno++;
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/prep/prepunion.c,v 1.119 2004/12/31 22:00:20 pgsql Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/prep/prepunion.c,v 1.120 2005/04/06 16:34:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "optimizer/tlist.h"
#include "parser/parse_clause.h"
#include "parser/parse_coerce.h"
+#include "parser/parse_expr.h"
#include "parser/parsetree.h"
#include "utils/lsyscache.h"
ListCell *i,
*j,
*k;
- Resdom *resdom;
+ TargetEntry *tle;
Node *expr;
j = list_head(input_tlist);
Oid colType = lfirst_oid(i);
TargetEntry *inputtle = (TargetEntry *) lfirst(j);
TargetEntry *reftle = (TargetEntry *) lfirst(k);
- int32 colTypmod;
- Assert(inputtle->resdom->resno == resno);
- Assert(reftle->resdom->resno == resno);
- Assert(!inputtle->resdom->resjunk);
- Assert(!reftle->resdom->resjunk);
+ Assert(inputtle->resno == resno);
+ Assert(reftle->resno == resno);
+ Assert(!inputtle->resjunk);
+ Assert(!reftle->resjunk);
/*
* Generate columns referencing input columns and having
expr = (Node *) inputtle->expr;
else
expr = (Node *) makeVar(0,
- inputtle->resdom->resno,
- inputtle->resdom->restype,
- inputtle->resdom->restypmod,
+ inputtle->resno,
+ exprType((Node *) inputtle->expr),
+ exprTypmod((Node *) inputtle->expr),
0);
- if (inputtle->resdom->restype == colType)
- {
- /* no coercion needed, and believe the input typmod */
- colTypmod = inputtle->resdom->restypmod;
- }
- else
+ if (exprType(expr) != colType)
{
expr = coerce_to_common_type(NULL, /* no UNKNOWNs here */
expr,
colType,
"UNION/INTERSECT/EXCEPT");
- colTypmod = -1;
}
- resdom = makeResdom((AttrNumber) resno++,
- colType,
- colTypmod,
- pstrdup(reftle->resdom->resname),
- false);
- tlist = lappend(tlist, makeTargetEntry(resdom, (Expr *) expr));
+ tle = makeTargetEntry((Expr *) expr,
+ (AttrNumber) resno++,
+ pstrdup(reftle->resname),
+ false);
+ tlist = lappend(tlist, tle);
+
j = lnext(j);
k = lnext(k);
}
if (flag >= 0)
{
/* Add a resjunk flag column */
- resdom = makeResdom((AttrNumber) resno++,
- INT4OID,
- -1,
- pstrdup("flag"),
- true);
/* flag value is the given constant */
expr = (Node *) makeConst(INT4OID,
sizeof(int4),
Int32GetDatum(flag),
false,
true);
- tlist = lappend(tlist, makeTargetEntry(resdom, (Expr *) expr));
+ tle = makeTargetEntry((Expr *) expr,
+ (AttrNumber) resno++,
+ pstrdup("flag"),
+ true);
+ tlist = lappend(tlist, tle);
}
return tlist;
ListCell *curColType;
ListCell *ref_tl_item;
int colindex;
- Resdom *resdom;
+ TargetEntry *tle;
Node *expr;
ListCell *planl;
int32 *colTypmods;
{
TargetEntry *subtle = (TargetEntry *) lfirst(subtlist);
- if (subtle->resdom->resjunk)
+ if (subtle->resjunk)
continue;
Assert(curColType != NULL);
- if (subtle->resdom->restype == lfirst_oid(curColType))
+ if (exprType((Node *) subtle->expr) == lfirst_oid(curColType))
{
/* If first subplan, copy the typmod; else compare */
+ int32 subtypmod = exprTypmod((Node *) subtle->expr);
+
if (planl == list_head(input_plans))
- colTypmods[colindex] = subtle->resdom->restypmod;
- else if (subtle->resdom->restypmod != colTypmods[colindex])
+ colTypmods[colindex] = subtypmod;
+ else if (subtypmod != colTypmods[colindex])
colTypmods[colindex] = -1;
}
else
int32 colTypmod = colTypmods[colindex++];
TargetEntry *reftle = (TargetEntry *) lfirst(ref_tl_item);
- Assert(reftle->resdom->resno == resno);
- Assert(!reftle->resdom->resjunk);
+ Assert(reftle->resno == resno);
+ Assert(!reftle->resjunk);
expr = (Node *) makeVar(0,
resno,
colType,
colTypmod,
0);
- resdom = makeResdom((AttrNumber) resno++,
- colType,
- colTypmod,
- pstrdup(reftle->resdom->resname),
- false);
- tlist = lappend(tlist, makeTargetEntry(resdom, (Expr *) expr));
+ tle = makeTargetEntry((Expr *) expr,
+ (AttrNumber) resno++,
+ pstrdup(reftle->resname),
+ false);
+ tlist = lappend(tlist, tle);
}
if (flag)
{
/* Add a resjunk flag column */
- resdom = makeResdom((AttrNumber) resno++,
- INT4OID,
- -1,
- pstrdup("flag"),
- true);
/* flag value is shown as copied up from subplan */
expr = (Node *) makeVar(0,
- resdom->resno,
+ resno,
INT4OID,
-1,
0);
- tlist = lappend(tlist, makeTargetEntry(resdom, (Expr *) expr));
+ tle = makeTargetEntry((Expr *) expr,
+ (AttrNumber) resno++,
+ pstrdup("flag"),
+ true);
+ tlist = lappend(tlist, tle);
}
pfree(colTypmods);
{
TargetEntry *tle = (TargetEntry *) lfirst(l);
- if (tle->resdom->resjunk)
+ if (tle->resjunk)
{
if (!junkOK)
return false;
{
if (curColType == NULL)
return false;
- if (tle->resdom->restype != lfirst_oid(curColType))
+ if (exprType((Node *) tle->expr) != lfirst_oid(curColType))
return false;
curColType = lnext(curColType);
}
*
* The given tlist has already been through expression_tree_mutator;
* therefore the TargetEntry nodes are fresh copies that it's okay to
- * scribble on. But the Resdom nodes have not been copied; make new ones
- * if we need to change them!
+ * scribble on.
*
* Note that this is not needed for INSERT because INSERT isn't inheritable.
*/
foreach(tl, tlist)
{
TargetEntry *tle = (TargetEntry *) lfirst(tl);
- Resdom *resdom = tle->resdom;
- if (resdom->resjunk)
+ if (tle->resjunk)
continue; /* ignore junk items */
- attrno = translate_inherited_attnum(resdom->resno, context);
+ attrno = translate_inherited_attnum(tle->resno, context);
- if (resdom->resno != attrno)
+ if (tle->resno != attrno)
{
- resdom = (Resdom *) copyObject((Node *) resdom);
- resdom->resno = attrno;
- tle->resdom = resdom;
+ tle->resno = attrno;
changed_it = true;
}
}
foreach(tl, tlist)
{
TargetEntry *tle = (TargetEntry *) lfirst(tl);
- Resdom *resdom = tle->resdom;
- if (resdom->resjunk)
+ if (tle->resjunk)
continue; /* ignore junk items */
- if (resdom->resno == attrno)
+ if (tle->resno == attrno)
new_tlist = lappend(new_tlist, tle);
- else if (resdom->resno > attrno)
+ else if (tle->resno > attrno)
more = true;
}
}
foreach(tl, tlist)
{
TargetEntry *tle = (TargetEntry *) lfirst(tl);
- Resdom *resdom = tle->resdom;
- if (!resdom->resjunk)
+ if (!tle->resjunk)
continue; /* here, ignore non-junk items */
- if (resdom->resno != attrno)
- {
- resdom = (Resdom *) copyObject((Node *) resdom);
- resdom->resno = attrno;
- tle->resdom = resdom;
- }
+ tle->resno = attrno;
new_tlist = lappend(new_tlist, tle);
attrno++;
}
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.192 2005/03/31 22:46:09 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.193 2005/04/06 16:34:06 tgl Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
{
TargetEntry *tle = (TargetEntry *) lfirst(l);
- if (tle->resdom->ressortgroupref == 0)
+ if (tle->ressortgroupref == 0)
{
- if (tle->resdom->resjunk)
+ if (tle->resjunk)
continue; /* we can ignore unsorted junk cols */
return true; /* definitely not in DISTINCT list */
}
if (targetIsInSortList(tle, query->distinctClause))
{
- if (tle->resdom->resjunk)
+ if (tle->resjunk)
return true; /* junk TLE in DISTINCT means DISTINCT ON */
/* else this TLE is okay, keep looking */
}
else
{
/* This TLE is not in DISTINCT list */
- if (!tle->resdom->resjunk)
+ if (!tle->resjunk)
return true; /* non-junk, non-DISTINCT, so DISTINCT ON */
if (targetIsInSortList(tle, query->sortClause))
return true; /* sorted, non-distinct junk */
break;
case T_TargetEntry:
{
- /*
- * We mutate the expression, but not the resdom, by
- * default.
- */
TargetEntry *targetentry = (TargetEntry *) node;
TargetEntry *newnode;
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/util/pathnode.c,v 1.114 2005/03/27 06:29:42 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/util/pathnode.c,v 1.115 2005/04/06 16:34:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
TargetEntry *tle = get_sortgroupclause_tle(grpcl,
query->targetList);
- if (tle->resdom->resjunk)
+ if (tle->resjunk)
break;
}
if (!gl) /* got to the end? */
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/util/plancat.c,v 1.103 2005/03/29 00:17:02 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/util/plancat.c,v 1.104 2005/04/06 16:34:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
for (attrno = 1; attrno <= numattrs; attrno++)
{
Form_pg_attribute att_tup = relation->rd_att->attrs[attrno - 1];
+ Var *var;
if (att_tup->attisdropped)
{
break;
}
+ var = makeVar(varno,
+ attrno,
+ att_tup->atttypid,
+ att_tup->atttypmod,
+ 0);
+
tlist = lappend(tlist,
- create_tl_element(makeVar(varno,
- attrno,
- att_tup->atttypid,
- att_tup->atttypmod,
- 0),
- attrno));
+ makeTargetEntry((Expr *) var,
+ attrno,
+ NULL,
+ false));
}
heap_close(relation, AccessShareLock);
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/util/tlist.c,v 1.68 2004/12/31 22:00:23 pgsql Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/util/tlist.c,v 1.69 2005/04/06 16:34:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
*****************************************************************************/
/*
- * tlistentry_member
+ * tlist_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)
+tlist_member(Node *node, List *targetlist)
{
ListCell *temp;
return NULL;
}
-#ifdef NOT_USED
-/*
- * 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 NULL;
-}
-#endif
-
-/*
- * 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 NULL;
-}
-
-/*
- * create_tl_element
- * Creates a target list entry node and its associated (resdom var) pair
- * with its resdom number equal to 'resdomno'.
- *
- * Note: the argument is almost always a Var, but occasionally not.
- */
-TargetEntry *
-create_tl_element(Var *var, int resdomno)
-{
- Oid vartype;
- int32 vartypmod;
-
- if (IsA(var, Var))
- {
- vartype = var->vartype;
- vartypmod = var->vartypmod;
- }
- else
- {
- vartype = exprType((Node *) var);
- vartypmod = exprTypmod((Node *) var);
- }
- return makeTargetEntry(makeResdom(resdomno,
- vartype,
- vartypmod,
- NULL,
- false),
- (Expr *) var);
-}
-
-/*****************************************************************************
- * ---------- GENERAL target list routines ----------
- *****************************************************************************/
-
/*
* flatten_tlist
* Create a target list that only contains unique variables.
List *
add_to_flat_tlist(List *tlist, List *vars)
{
- int next_resdomno = list_length(tlist) + 1;
+ int next_resno = list_length(tlist) + 1;
ListCell *v;
foreach(v, vars)
{
Var *var = (Var *) lfirst(v);
- if (!tlistentry_member((Node *) var, tlist))
+ if (!tlist_member((Node *) var, tlist))
{
- Resdom *r;
-
- r = makeResdom(next_resdomno++,
- var->vartype,
- var->vartypmod,
- NULL,
- false);
- tlist = lappend(tlist,
- makeTargetEntry(r, copyObject(var)));
+ TargetEntry *tle;
+
+ tle = makeTargetEntry(copyObject(var), /* copy needed?? */
+ next_resno++,
+ NULL,
+ false);
+ tlist = lappend(tlist, tle);
}
}
return tlist;
{
TargetEntry *tle = (TargetEntry *) lfirst(l);
- if (tle->resdom->ressortgroupref == refnumber)
+ if (tle->ressortgroupref == refnumber)
return tle;
}
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.316 2005/03/10 23:21:23 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.317 2005/04/06 16:34:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
foreach(targetList, stmt->query->targetList)
{
TargetEntry *te = (TargetEntry *) lfirst(targetList);
- Resdom *rd;
Assert(IsA(te, TargetEntry));
- rd = te->resdom;
- Assert(IsA(rd, Resdom));
/* junk columns don't get aliases */
- if (rd->resjunk)
+ if (te->resjunk)
continue;
- rd->resname = pstrdup(strVal(lfirst(alist_item)));
+ te->resname = pstrdup(strVal(lfirst(alist_item)));
alist_item = lnext(alist_item);
if (alist_item == NULL)
break; /* done assigning aliases */
{
Query *qry = makeNode(Query);
Query *selectQuery = NULL;
- bool copy_up_hack = false;
List *sub_rtable;
List *sub_namespace;
List *icolumns;
* separate from the subquery's tlist because we may add columns,
* insert datatype coercions, etc.)
*
- * HACK: unknown-type constants and params in the INSERT's targetlist
+ * HACK: unknown-type constants and params in the SELECT's targetlist
* are copied up as-is rather than being referenced as subquery
* outputs. This is to ensure that when we try to coerce them to
* the target column's datatype, the right things happen (see
foreach(tl, selectQuery->targetList)
{
TargetEntry *tle = (TargetEntry *) lfirst(tl);
- Resdom *resnode = tle->resdom;
Expr *expr;
- if (resnode->resjunk)
+ if (tle->resjunk)
continue;
if (tle->expr &&
(IsA(tle->expr, Const) || IsA(tle->expr, Param)) &&
exprType((Node *) tle->expr) == UNKNOWNOID)
- {
expr = tle->expr;
- copy_up_hack = true;
- }
else
expr = (Expr *) makeVar(rtr->rtindex,
- resnode->resno,
- resnode->restype,
- resnode->restypmod,
+ tle->resno,
+ exprType((Node *) tle->expr),
+ exprTypmod((Node *) tle->expr),
0);
- resnode = copyObject(resnode);
- resnode->resno = (AttrNumber) pstate->p_next_resno++;
- qry->targetList = lappend(qry->targetList,
- makeTargetEntry(resnode, expr));
+ tle = makeTargetEntry(expr,
+ (AttrNumber) pstate->p_next_resno++,
+ tle->resname,
+ false);
+ qry->targetList = lappend(qry->targetList, tle);
}
}
else
col = (ResTarget *) lfirst(icols);
Assert(IsA(col, ResTarget));
- Assert(!tle->resdom->resjunk);
+ Assert(!tle->resjunk);
updateTargetListEntry(pstate, tle, col->name, lfirst_int(attnos),
col->indirection);
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("INSERT has more target columns than expressions")));
- /*
- * If we copied up any unknown Params (see HACK above) then their
- * resolved types need to be propagated into the Resdom nodes of
- * the sub-INSERT's tlist. One hack begets another :-(
- */
- if (copy_up_hack)
- {
- foreach(tl, selectQuery->targetList)
- {
- TargetEntry *tle = (TargetEntry *) lfirst(tl);
- Resdom *resnode = tle->resdom;
-
- if (resnode->resjunk)
- continue;
- if (resnode->restype == UNKNOWNOID)
- {
- resnode->restype = exprType((Node *) tle->expr);
- resnode->restypmod = exprTypmod((Node *) tle->expr);
- }
- }
- }
-
/* done building the range table and jointree */
qry->rtable = pstate->p_rtable;
qry->jointree = makeFromExpr(pstate->p_joinlist, NULL);
foreach(dtlist, sostmt->colTypes)
{
Oid colType = lfirst_oid(dtlist);
- Resdom *leftResdom;
+ TargetEntry *lefttle = (TargetEntry *) lfirst(left_tlist);
char *colName;
- Resdom *resdom;
+ TargetEntry *tle;
Expr *expr;
- leftResdom = ((TargetEntry *) lfirst(left_tlist))->resdom;
- Assert(!leftResdom->resjunk);
- colName = pstrdup(leftResdom->resname);
- resdom = makeResdom((AttrNumber) pstate->p_next_resno++,
- colType,
- -1,
- colName,
- false);
+ Assert(!lefttle->resjunk);
+ colName = pstrdup(lefttle->resname);
expr = (Expr *) makeVar(leftmostRTI,
- leftResdom->resno,
+ lefttle->resno,
colType,
-1,
0);
- qry->targetList = lappend(qry->targetList,
- makeTargetEntry(resdom, expr));
+ tle = makeTargetEntry(expr,
+ (AttrNumber) pstate->p_next_resno++,
+ colName,
+ false);
+ qry->targetList = lappend(qry->targetList, tle);
targetvars = lappend(targetvars, expr);
targetnames = lappend(targetnames, makeString(colName));
left_tlist = lnext(left_tlist);
foreach(tl, selectQuery->targetList)
{
TargetEntry *tle = (TargetEntry *) lfirst(tl);
- Resdom *resnode = tle->resdom;
- if (resnode->resjunk)
+ if (tle->resjunk)
continue;
- result = lappend_oid(result, resnode->restype);
+ result = lappend_oid(result, exprType((Node *) tle->expr));
}
return result;
}
TargetEntry *d = (TargetEntry *) lfirst(dst_item);
ColumnDef *s = (ColumnDef *) lfirst(src_item);
- Assert(d->resdom && !d->resdom->resjunk);
- d->resdom->resname = pstrdup(s->colname);
+ Assert(!d->resjunk);
+ d->resname = pstrdup(s->colname);
}
}
foreach(tl, qry->targetList)
{
TargetEntry *tle = (TargetEntry *) lfirst(tl);
- Resdom *resnode = tle->resdom;
ResTarget *origTarget;
- if (resnode->resjunk)
+ if (tle->resjunk)
{
/*
* Resjunk nodes need no additional processing, but be sure
* rewriter or planner might get confused. They don't need a
* resname either.
*/
- resnode->resno = (AttrNumber) pstate->p_next_resno++;
- resnode->resname = NULL;
+ tle->resno = (AttrNumber) pstate->p_next_resno++;
+ tle->resname = NULL;
continue;
}
if (origTargetList == NULL)
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/parser/parse_clause.c,v 1.138 2004/12/31 22:00:27 pgsql Exp $
+ * $PostgreSQL: pgsql/src/backend/parser/parse_clause.c,v 1.139 2005/04/06 16:34:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
foreach(tl, *tlist)
{
TargetEntry *tle = (TargetEntry *) lfirst(tl);
- Resdom *resnode = tle->resdom;
- if (!resnode->resjunk &&
- strcmp(resnode->resname, name) == 0)
+ if (!tle->resjunk &&
+ strcmp(tle->resname, name) == 0)
{
if (target_result != NULL)
{
foreach(tl, *tlist)
{
TargetEntry *tle = (TargetEntry *) lfirst(tl);
- Resdom *resnode = tle->resdom;
- if (!resnode->resjunk)
+ if (!tle->resjunk)
{
if (++targetlist_pos == target_pos)
return tle; /* return the unique match */
continue;
/* if tlist item is an UNKNOWN literal, change it to TEXT */
- restype = tle->resdom->restype;
+ restype = exprType((Node *) tle->expr);
if (restype == UNKNOWNOID)
{
restype, TEXTOID, -1,
COERCION_IMPLICIT,
COERCE_IMPLICIT_CAST);
- restype = tle->resdom->restype = TEXTOID;
- tle->resdom->restypmod = -1;
+ restype = TEXTOID;
}
/*
*/
if (sortItem &&
((SortClause *) lfirst(sortItem))->tleSortGroupRef ==
- tle->resdom->ressortgroupref)
+ tle->ressortgroupref)
{
ordering_op = ((SortClause *) lfirst(sortItem))->sortop;
sortItem = lnext(sortItem);
SortClause *scl = (SortClause *) lfirst(slitem);
TargetEntry *tle = get_sortgroupclause_tle(scl, *targetlist);
- if (tle->resdom->resjunk)
+ if (tle->resjunk)
ereport(ERROR,
(errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
errmsg("for SELECT DISTINCT, ORDER BY expressions must appear in select list")));
{
SortClause *scl = (SortClause *) lfirst(nextsortlist);
- if (tle->resdom->ressortgroupref != scl->tleSortGroupRef)
+ if (tle->ressortgroupref != scl->tleSortGroupRef)
ereport(ERROR,
(errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
errmsg("SELECT DISTINCT ON expressions must match initial ORDER BY expressions")));
{
SortClause *scl = (SortClause *) lfirst(slitem);
- if (tle->resdom->ressortgroupref == scl->tleSortGroupRef)
+ if (tle->ressortgroupref == scl->tleSortGroupRef)
{
result = lappend(result, copyObject(scl));
break;
{
TargetEntry *tle = (TargetEntry *) lfirst(l);
- if (!tle->resdom->resjunk)
+ if (!tle->resjunk)
sortlist = addTargetToSortList(pstate, tle,
sortlist, targetlist,
SORTBY_ASC, NIL,
if (!targetIsInSortList(tle, sortlist))
{
SortClause *sortcl = makeNode(SortClause);
- Oid restype = tle->resdom->restype;
+ Oid restype = exprType((Node *) tle->expr);
/* if tlist item is an UNKNOWN literal, change it to TEXT */
if (restype == UNKNOWNOID && resolveUnknown)
restype, TEXTOID, -1,
COERCION_IMPLICIT,
COERCE_IMPLICIT_CAST);
- restype = tle->resdom->restype = TEXTOID;
- tle->resdom->restypmod = -1;
+ restype = TEXTOID;
}
sortcl->tleSortGroupRef = assignSortGroupRef(tle, targetlist);
Index maxRef;
ListCell *l;
- if (tle->resdom->ressortgroupref) /* already has one? */
- return tle->resdom->ressortgroupref;
+ if (tle->ressortgroupref) /* already has one? */
+ return tle->ressortgroupref;
/* easiest way to pick an unused refnumber: max used + 1 */
maxRef = 0;
foreach(l, tlist)
{
- Index ref = ((TargetEntry *) lfirst(l))->resdom->ressortgroupref;
+ Index ref = ((TargetEntry *) lfirst(l))->ressortgroupref;
if (ref > maxRef)
maxRef = ref;
}
- tle->resdom->ressortgroupref = maxRef + 1;
- return tle->resdom->ressortgroupref;
+ tle->ressortgroupref = maxRef + 1;
+ return tle->ressortgroupref;
}
/*
bool
targetIsInSortList(TargetEntry *tle, List *sortList)
{
- Index ref = tle->resdom->ressortgroupref;
+ Index ref = tle->ressortgroupref;
ListCell *l;
/* no need to scan list if tle has no marker */
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.180 2005/01/19 23:45:24 neilc Exp $
+ * $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.181 2005/04/06 16:34:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* resjunk targets).
*/
if (tlist_item == NULL ||
- ((TargetEntry *) lfirst(tlist_item))->resdom->resjunk)
+ ((TargetEntry *) lfirst(tlist_item))->resjunk)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("subquery must return a column")));
while ((tlist_item = lnext(tlist_item)) != NULL)
{
- if (!((TargetEntry *) lfirst(tlist_item))->resdom->resjunk)
+ if (!((TargetEntry *) lfirst(tlist_item))->resjunk)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("subquery must return only one column")));
Operator optup;
Form_pg_operator opform;
- if (tent->resdom->resjunk)
+ if (tent->resjunk)
continue;
if (ll_item == NULL)
elog(ERROR, "cannot get type for untransformed sublink");
tent = (TargetEntry *) linitial(qtree->targetList);
Assert(IsA(tent, TargetEntry));
- Assert(!tent->resdom->resjunk);
- if (sublink->subLinkType == EXPR_SUBLINK)
- type = tent->resdom->restype;
- else
+ Assert(!tent->resjunk);
+ type = exprType((Node *) tent->expr);
+ if (sublink->subLinkType == ARRAY_SUBLINK)
{
- /* ARRAY_SUBLINK */
- type = get_array_type(tent->resdom->restype);
+ type = get_array_type(type);
if (!OidIsValid(type))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("could not find array type for data type %s",
- format_type_be(tent->resdom->restype))));
+ format_type_be(exprType((Node *) tent->expr)))));
}
}
else
tent = (TargetEntry *) linitial(subplan->plan->targetlist);
Assert(IsA(tent, TargetEntry));
- Assert(!tent->resdom->resjunk);
- if (subplan->subLinkType == EXPR_SUBLINK)
- type = tent->resdom->restype;
- else
+ Assert(!tent->resjunk);
+ type = exprType((Node *) tent->expr);
+ if (subplan->subLinkType == ARRAY_SUBLINK)
{
- /* ARRAY_SUBLINK */
- type = get_array_type(tent->resdom->restype);
+ type = get_array_type(type);
if (!OidIsValid(type))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("could not find array type for data type %s",
- format_type_be(tent->resdom->restype))));
+ format_type_be(exprType((Node *) tent->expr)))));
}
}
else
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/parser/parse_relation.c,v 1.103 2005/03/31 22:46:13 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/parser/parse_relation.c,v 1.104 2005/04/06 16:34:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
{
TargetEntry *te = (TargetEntry *) lfirst(tlistitem);
- if (te->resdom->resjunk)
+ if (te->resjunk)
continue;
varattno++;
- Assert(varattno == te->resdom->resno);
+ Assert(varattno == te->resno);
if (varattno > numaliases)
{
char *attrname;
- attrname = pstrdup(te->resdom->resname);
+ attrname = pstrdup(te->resname);
eref->colnames = lappend(eref->colnames, makeString(attrname));
}
}
{
TargetEntry *te = (TargetEntry *) lfirst(tlistitem);
- if (te->resdom->resjunk)
+ if (te->resjunk)
continue;
varattno++;
- Assert(varattno == te->resdom->resno);
+ Assert(varattno == te->resno);
if (colnames)
{
Var *varnode;
varnode = makeVar(rtindex, varattno,
- te->resdom->restype,
- te->resdom->restypmod,
+ exprType((Node *) te->expr),
+ exprTypmod((Node *) te->expr),
sublevels_up);
*colvars = lappend(*colvars, varnode);
{
char *label = strVal(lfirst(name));
Node *varnode = (Node *) lfirst(var);
- TargetEntry *te = makeNode(TargetEntry);
-
- te->resdom = makeResdom((AttrNumber) pstate->p_next_resno++,
- exprType(varnode),
- exprTypmod(varnode),
- label,
- false);
- te->expr = (Expr *) varnode;
+ TargetEntry *te;
+
+ te = makeTargetEntry((Expr *) varnode,
+ (AttrNumber) pstate->p_next_resno++,
+ label,
+ false);
te_list = lappend(te_list, te);
}
TargetEntry *te = get_tle_by_resno(rte->subquery->targetList,
attnum);
- if (te == NULL || te->resdom->resjunk)
+ if (te == NULL || te->resjunk)
elog(ERROR, "subquery %s does not have attribute %d",
rte->eref->aliasname, attnum);
- *vartype = te->resdom->restype;
- *vartypmod = te->resdom->restypmod;
+ *vartype = exprType((Node *) te->expr);
+ *vartypmod = exprTypmod((Node *) te->expr);
}
break;
case RTE_FUNCTION:
{
TargetEntry *tle = (TargetEntry *) lfirst(l);
- if (tle->resdom->resno == resno)
+ if (tle->resno == resno)
return tle;
}
return NULL;
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/parser/parse_target.c,v 1.130 2005/03/26 06:28:59 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/parser/parse_target.c,v 1.131 2005/04/06 16:34:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "utils/typcache.h"
-static void markTargetListOrigin(ParseState *pstate, Resdom *res,
+static void markTargetListOrigin(ParseState *pstate, TargetEntry *tle,
Var *var, int levelsup);
static Node *transformAssignmentIndirection(ParseState *pstate,
Node *basenode,
char *colname,
bool resjunk)
{
- Oid type_id;
- int32 type_mod;
- Resdom *resnode;
-
/* Transform the node if caller didn't do it already */
if (expr == NULL)
expr = transformExpr(pstate, node);
- type_id = exprType(expr);
- type_mod = exprTypmod(expr);
-
if (colname == NULL && !resjunk)
{
/*
colname = FigureColname(node);
}
- resnode = makeResdom((AttrNumber) pstate->p_next_resno++,
- type_id,
- type_mod,
- colname,
- resjunk);
-
- return makeTargetEntry(resnode, (Expr *) expr);
+ return makeTargetEntry((Expr *) expr,
+ (AttrNumber) pstate->p_next_resno++,
+ colname,
+ resjunk);
}
{
TargetEntry *tle = (TargetEntry *) lfirst(l);
- markTargetListOrigin(pstate, tle->resdom, (Var *) tle->expr, 0);
+ markTargetListOrigin(pstate, tle, (Var *) tle->expr, 0);
}
}
/*
* markTargetListOrigin()
- * If 'var' is a Var of a plain relation, mark 'res' with its origin
+ * If 'var' is a Var of a plain relation, mark 'tle' with its origin
*
* levelsup is an extra offset to interpret the Var's varlevelsup correctly.
*
* do not drill down into views, but report the view as the column owner.
*/
static void
-markTargetListOrigin(ParseState *pstate, Resdom *res, Var *var, int levelsup)
+markTargetListOrigin(ParseState *pstate, TargetEntry *tle,
+ Var *var, int levelsup)
{
int netlevelsup;
RangeTblEntry *rte;
{
case RTE_RELATION:
/* It's a table or view, report it */
- res->resorigtbl = rte->relid;
- res->resorigcol = attnum;
+ tle->resorigtbl = rte->relid;
+ tle->resorigcol = attnum;
break;
case RTE_SUBQUERY:
{
/* Subselect-in-FROM: copy up from the subselect */
- TargetEntry *te = get_tle_by_resno(rte->subquery->targetList,
- attnum);
+ TargetEntry *ste = get_tle_by_resno(rte->subquery->targetList,
+ attnum);
- if (te == NULL || te->resdom->resjunk)
+ if (ste == NULL || ste->resjunk)
elog(ERROR, "subquery %s does not have attribute %d",
rte->eref->aliasname, attnum);
- res->resorigtbl = te->resdom->resorigtbl;
- res->resorigcol = te->resdom->resorigcol;
+ tle->resorigtbl = ste->resorigtbl;
+ tle->resorigcol = ste->resorigcol;
}
break;
case RTE_JOIN:
Assert(attnum > 0 && attnum <= list_length(rte->joinaliasvars));
aliasvar = (Var *) list_nth(rte->joinaliasvars, attnum - 1);
- markTargetListOrigin(pstate, res, aliasvar, netlevelsup);
+ markTargetListOrigin(pstate, tle, aliasvar, netlevelsup);
}
break;
case RTE_SPECIAL:
Oid type_id; /* type of value provided */
Oid attrtype; /* type of target column */
int32 attrtypmod;
- Resdom *resnode = tle->resdom;
Relation rd = pstate->p_target_relation;
Assert(rd != NULL);
errhint("You will need to rewrite or cast the expression.")));
}
- /*
- * The result of the target expression should now match the
- * destination column's type.
- */
- resnode->restype = attrtype;
- resnode->restypmod = attrtypmod;
-
/*
* Set the resno to identify the target column --- the rewriter and
* planner depend on this. We also set the resname to identify the
* not be relied on. (In particular, it might be out of date in a
* stored rule.)
*/
- resnode->resno = (AttrNumber) attrno;
- resnode->resname = colname;
+ tle->resno = (AttrNumber) attrno;
+ tle->resname = colname;
}
/*
fieldnode = (Node *) fselect;
}
- te = makeNode(TargetEntry);
- te->resdom = makeResdom((AttrNumber) pstate->p_next_resno++,
- att->atttypid,
- att->atttypmod,
- pstrdup(NameStr(att->attname)),
- false);
- te->expr = (Expr *) fieldnode;
+ te = makeTargetEntry((Expr *) fieldnode,
+ (AttrNumber) pstate->p_next_resno++,
+ pstrdup(NameStr(att->attname)),
+ false);
te_list = lappend(te_list, te);
}
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/rewrite/rewriteDefine.c,v 1.101 2005/01/27 23:24:05 neilc Exp $
+ * $PostgreSQL: pgsql/src/backend/rewrite/rewriteDefine.c,v 1.102 2005/04/06 16:34:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "commands/view.h"
#include "miscadmin.h"
#include "optimizer/clauses.h"
+#include "parser/parse_expr.h"
#include "parser/parse_relation.h"
#include "rewrite/rewriteDefine.h"
#include "rewrite/rewriteManip.h"
foreach(tllist, query->targetList)
{
TargetEntry *tle = (TargetEntry *) lfirst(tllist);
- Resdom *resdom = tle->resdom;
+ int32 tletypmod;
Form_pg_attribute attr;
char *attname;
- if (resdom->resjunk)
+ if (tle->resjunk)
continue;
i++;
if (i > event_relation->rd_att->natts)
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot convert relation containing dropped columns to view")));
- if (strcmp(resdom->resname, attname) != 0)
+ if (strcmp(tle->resname, attname) != 0)
ereport(ERROR,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
errmsg("SELECT rule's target entry %d has different column name from \"%s\"", i, attname)));
- if (attr->atttypid != resdom->restype)
+ if (attr->atttypid != exprType((Node *) tle->expr))
ereport(ERROR,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
errmsg("SELECT rule's target entry %d has different type from column \"%s\"", i, attname)));
* length but the select rule's expression will probably have
* typmod = -1.
*/
- if (attr->atttypmod != resdom->restypmod &&
- attr->atttypmod != -1 && resdom->restypmod != -1)
+ tletypmod = exprTypmod((Node *) tle->expr);
+ if (attr->atttypmod != tletypmod &&
+ attr->atttypmod != -1 && tletypmod != -1)
ereport(ERROR,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
errmsg("SELECT rule's target entry %d has different size from column \"%s\"", i, attname)));
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/rewrite/rewriteHandler.c,v 1.149 2005/03/26 05:53:01 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/rewrite/rewriteHandler.c,v 1.150 2005/04/06 16:34:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
foreach(temp, parsetree->targetList)
{
TargetEntry *old_tle = (TargetEntry *) lfirst(temp);
- Resdom *resdom = old_tle->resdom;
- if (!resdom->resjunk)
+ if (!old_tle->resjunk)
{
/* Normal attr: stash it into new_tles[] */
- attrno = resdom->resno;
+ attrno = old_tle->resno;
if (attrno < 1 || attrno > numattrs)
elog(ERROR, "bogus resno %d in targetlist", attrno);
att_tup = target_relation->rd_att->attrs[attrno - 1];
*/
/* Get the resno right, but don't copy unnecessarily */
- if (resdom->resno != next_junk_attrno)
+ if (old_tle->resno != next_junk_attrno)
{
- resdom = (Resdom *) copyObject((Node *) resdom);
- resdom->resno = next_junk_attrno;
- old_tle = makeTargetEntry(resdom, old_tle->expr);
+ old_tle = flatCopyTargetEntry(old_tle);
+ old_tle->resno = next_junk_attrno;
}
junk_tlist = lappend(junk_tlist, old_tle);
next_junk_attrno++;
}
if (new_expr)
- new_tle = makeTargetEntry(makeResdom(attrno,
- att_tup->atttypid,
- att_tup->atttypmod,
- pstrdup(NameStr(att_tup->attname)),
- false),
- (Expr *) new_expr);
+ new_tle = makeTargetEntry((Expr *) new_expr,
+ attrno,
+ pstrdup(NameStr(att_tup->attname)),
+ false);
}
if (new_tle)
TargetEntry *prior_tle,
const char *attrName)
{
- Resdom *resdom = src_tle->resdom;
+ TargetEntry *result;
Node *src_expr;
Node *prior_expr;
Node *src_input;
newexpr = NULL;
}
- return makeTargetEntry(resdom, (Expr *) newexpr);
+ result = flatCopyTargetEntry(src_tle);
+ result->expr = (Expr *) newexpr;
+ return result;
}
/*
* back to source text
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.189 2005/03/29 00:17:08 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.190 2005/04/06 16:34:06 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
foreach(tl, tlist)
{
TargetEntry *tle = lfirst(tl);
- Resdom *resdom = tle->resdom;
nattrs++;
- Assert(resdom->resno == nattrs);
- if (resdom->resname)
+ Assert(tle->resno == nattrs);
+ if (tle->resname)
{
- attrs = lappend(attrs, makeString(resdom->resname));
+ attrs = lappend(attrs, makeString(tle->resname));
continue;
}
if (tle->expr && IsA(tle->expr, Var))
}
}
/* Fallback if can't get name */
- snprintf(buf, sizeof(buf), "?column%d?", resdom->resno);
+ snprintf(buf, sizeof(buf), "?column%d?", tle->resno);
attrs = lappend(attrs, makeString(pstrdup(buf)));
}
TargetEntry *tle = (TargetEntry *) lfirst(l);
char *colname;
- if (tle->resdom->resjunk)
+ if (tle->resjunk)
continue; /* ignore junk entries */
appendStringInfo(buf, sep);
if (resultDesc && colno <= resultDesc->natts)
colname = NameStr(resultDesc->attrs[colno - 1]->attname);
else
- colname = tle->resdom->resname;
+ colname = tle->resname;
if (colname) /* resname could be NULL */
{
*/
if (force_colno || (expr && IsA(expr, Const)))
{
- Assert(!tle->resdom->resjunk);
- appendStringInfo(buf, "%d", tle->resdom->resno);
+ Assert(!tle->resjunk);
+ appendStringInfo(buf, "%d", tle->resno);
}
else
get_rule_expr(expr, context, true);
{
TargetEntry *tle = (TargetEntry *) lfirst(l);
- if (tle->resdom->resjunk)
+ if (tle->resjunk)
continue; /* ignore junk entries */
appendStringInfo(buf, sep);
*/
appendStringInfoString(buf,
quote_identifier(get_relid_attribute_name(rte->relid,
- tle->resdom->resno)));
+ tle->resno)));
/*
* Print any indirection needed (subfields or subscripts), and
TargetEntry *tle = (TargetEntry *) lfirst(l);
Node *expr;
- if (tle->resdom->resjunk)
+ if (tle->resjunk)
continue; /* ignore junk entries */
appendStringInfo(buf, sep);
*/
appendStringInfoString(buf,
quote_identifier(get_relid_attribute_name(rte->relid,
- tle->resdom->resno)));
+ tle->resno)));
/*
* Print any indirection needed (subfields or subscripts), and
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.262 2005/03/29 19:44:23 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.263 2005/04/06 16:34:07 tgl Exp $
*
*-------------------------------------------------------------------------
*/
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 200503291
+#define CATALOG_VERSION_NO 200504061
#endif
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/nodes/makefuncs.h,v 1.51 2004/12/31 22:03:34 pgsql Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/makefuncs.h,v 1.52 2005/04/06 16:34:07 tgl Exp $
*
*-------------------------------------------------------------------------
*/
int32 vartypmod,
Index varlevelsup);
-extern TargetEntry *makeTargetEntry(Resdom *resdom, Expr *expr);
+extern TargetEntry *makeTargetEntry(Expr *expr,
+ AttrNumber resno,
+ char *resname,
+ bool resjunk);
-extern Resdom *makeResdom(AttrNumber resno,
- Oid restype,
- int32 restypmod,
- char *resname,
- bool resjunk);
+extern TargetEntry *flatCopyTargetEntry(TargetEntry *src_tle);
extern Const *makeConst(Oid consttype,
int constlen,
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.164 2005/03/14 00:19:37 neilc Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.165 2005/04/06 16:34:07 tgl Exp $
*
*-------------------------------------------------------------------------
*/
/*
* TAGS FOR PRIMITIVE NODES (primnodes.h)
*/
- T_Resdom = 300,
- T_Alias,
+ T_Alias = 300,
T_RangeVar,
T_Expr,
T_Var,
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.275 2005/03/29 17:58:51 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.276 2005/04/06 16:34:07 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* SortClause -
* representation of ORDER BY clauses
*
- * tleSortGroupRef must match ressortgroupref of exactly one Resdom of the
+ * tleSortGroupRef must match ressortgroupref of exactly one entry of the
* associated targetlist; that is the expression to be sorted (or grouped) by.
* sortop is the OID of the ordering operator.
*
- * SortClauses are also used to identify Resdoms that we will do a "Unique"
+ * SortClauses are also used to identify targets that we will do a "Unique"
* filter step on (for SELECT DISTINCT and SELECT DISTINCT ON). The
* distinctClause list is simply a copy of the relevant members of the
* sortClause list. Note that distinctClause can be a subset of sortClause,
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/nodes/primnodes.h,v 1.106 2004/12/31 22:03:34 pgsql Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/primnodes.h,v 1.107 2005/04/06 16:34:07 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* ----------------------------------------------------------------
*/
-/*--------------------
- * Resdom (Result Domain)
- *
- * Notes:
- *
- * In a SELECT's targetlist, resno should always be equal to the item's
- * ordinal position (counting from 1). However, in an INSERT or UPDATE
- * targetlist, resno represents the attribute number of the destination
- * column for the item; so there may be missing or out-of-order resnos.
- * It is even legal to have duplicated resnos; consider
- * UPDATE table SET arraycol[1] = ..., arraycol[2] = ..., ...
- * The two meanings come together in the executor, because the planner
- * transforms INSERT/UPDATE tlists into a normalized form with exactly
- * one entry for each column of the destination table. Before that's
- * happened, however, it is risky to assume that resno == position.
- * Generally get_tle_by_resno() should be used rather than list_nth()
- * to fetch tlist entries by resno, and only in SELECT should you assume
- * that resno is a unique identifier.
- *
- * resname is required to represent the correct column name in non-resjunk
- * entries of top-level SELECT targetlists, since it will be used as the
- * column title sent to the frontend. In most other contexts it is only
- * a debugging aid, and may be wrong or even NULL. (In particular, it may
- * be wrong in a tlist from a stored rule, if the referenced column has been
- * renamed by ALTER TABLE since the rule was made. Also, the planner tends
- * to store NULL rather than look up a valid name for tlist entries in
- * non-toplevel plan nodes.) In resjunk entries, resname should be either
- * a specific system-generated name (such as "ctid") or NULL; anything else
- * risks confusing ExecGetJunkAttribute!
- *
- * ressortgroupref is used in the representation of ORDER BY and
- * GROUP BY items. Targetlist entries with ressortgroupref=0 are not
- * sort/group items. If ressortgroupref>0, then this item is an ORDER BY or
- * GROUP BY value. No two entries in a targetlist may have the same nonzero
- * ressortgroupref --- but there is no particular meaning to the nonzero
- * values, except as tags. (For example, one must not assume that lower
- * ressortgroupref means a more significant sort key.) The order of the
- * associated SortClause or GroupClause lists determine the semantics.
- *
- * resorigtbl/resorigcol identify the source of the column, if it is a
- * simple reference to a column of a base table (or view). If it is not
- * a simple reference, these fields are zeroes.
- *
- * If resjunk is true then the column is a working column (such as a sort key)
- * that should be removed from the final output of the query. Resjunk columns
- * must have resnos that cannot duplicate any regular column's resno. Also
- * note that there are places that assume resjunk columns come after non-junk
- * columns.
- *--------------------
- */
-typedef struct Resdom
-{
- NodeTag type;
- AttrNumber resno; /* attribute number (see notes above) */
- Oid restype; /* type of the value */
- int32 restypmod; /* type-specific modifier of the value */
- char *resname; /* name of the column (could be NULL) */
- Index ressortgroupref;/* nonzero if referenced by a sort/group
- * clause */
- Oid resorigtbl; /* OID of column's source table */
- AttrNumber resorigcol; /* column's number in source table */
- bool resjunk; /* set to true to eliminate the attribute
- * from final target list */
-} Resdom;
-
-
/*
* Alias -
* specifies an alias for a range variable; the alias might also
int32 typeMod; /* typemod for substituted value */
} SetToDefault;
-/*
+/*--------------------
* TargetEntry -
* a target entry (used in query target lists)
*
* very many places it's convenient to process a whole query targetlist as a
* single expression tree.
*
- * The separation between TargetEntry and Resdom is historical. One of these
- * days, Resdom should probably get folded into TargetEntry.
+ * In a SELECT's targetlist, resno should always be equal to the item's
+ * ordinal position (counting from 1). However, in an INSERT or UPDATE
+ * targetlist, resno represents the attribute number of the destination
+ * column for the item; so there may be missing or out-of-order resnos.
+ * It is even legal to have duplicated resnos; consider
+ * UPDATE table SET arraycol[1] = ..., arraycol[2] = ..., ...
+ * The two meanings come together in the executor, because the planner
+ * transforms INSERT/UPDATE tlists into a normalized form with exactly
+ * one entry for each column of the destination table. Before that's
+ * happened, however, it is risky to assume that resno == position.
+ * Generally get_tle_by_resno() should be used rather than list_nth()
+ * to fetch tlist entries by resno, and only in SELECT should you assume
+ * that resno is a unique identifier.
+ *
+ * resname is required to represent the correct column name in non-resjunk
+ * entries of top-level SELECT targetlists, since it will be used as the
+ * column title sent to the frontend. In most other contexts it is only
+ * a debugging aid, and may be wrong or even NULL. (In particular, it may
+ * be wrong in a tlist from a stored rule, if the referenced column has been
+ * renamed by ALTER TABLE since the rule was made. Also, the planner tends
+ * to store NULL rather than look up a valid name for tlist entries in
+ * non-toplevel plan nodes.) In resjunk entries, resname should be either
+ * a specific system-generated name (such as "ctid") or NULL; anything else
+ * risks confusing ExecGetJunkAttribute!
+ *
+ * ressortgroupref is used in the representation of ORDER BY and
+ * GROUP BY items. Targetlist entries with ressortgroupref=0 are not
+ * sort/group items. If ressortgroupref>0, then this item is an ORDER BY or
+ * GROUP BY value. No two entries in a targetlist may have the same nonzero
+ * ressortgroupref --- but there is no particular meaning to the nonzero
+ * values, except as tags. (For example, one must not assume that lower
+ * ressortgroupref means a more significant sort key.) The order of the
+ * associated SortClause or GroupClause lists determine the semantics.
+ *
+ * resorigtbl/resorigcol identify the source of the column, if it is a
+ * simple reference to a column of a base table (or view). If it is not
+ * a simple reference, these fields are zeroes.
+ *
+ * If resjunk is true then the column is a working column (such as a sort key)
+ * that should be removed from the final output of the query. Resjunk columns
+ * must have resnos that cannot duplicate any regular column's resno. Also
+ * note that there are places that assume resjunk columns come after non-junk
+ * columns.
+ *--------------------
*/
typedef struct TargetEntry
{
Expr xpr;
- Resdom *resdom; /* descriptor for targetlist item */
Expr *expr; /* expression to evaluate */
+ AttrNumber resno; /* attribute number (see notes above) */
+ char *resname; /* name of the column (could be NULL) */
+ Index ressortgroupref;/* nonzero if referenced by a sort/group
+ * clause */
+ Oid resorigtbl; /* OID of column's source table */
+ AttrNumber resorigcol; /* column's number in source table */
+ bool resjunk; /* set to true to eliminate the attribute
+ * from final target list */
} TargetEntry;
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/optimizer/tlist.h,v 1.41 2004/12/31 22:03:36 pgsql Exp $
+ * $PostgreSQL: pgsql/src/include/optimizer/tlist.h,v 1.42 2005/04/06 16:34:07 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "nodes/relation.h"
-extern TargetEntry *tlistentry_member(Node *node, List *targetlist);
-extern Resdom *tlist_member(Node *node, List *targetlist);
-
-extern TargetEntry *create_tl_element(Var *var, int resdomno);
+extern TargetEntry *tlist_member(Node *node, List *targetlist);
extern List *flatten_tlist(List *tlist);
extern List *add_to_flat_tlist(List *tlist, List *vars);
Certain queries, like <I>SELECT,</I> return columns of data. Other
queries, like <I>INSERT</I> and <I>UPDATE,</I> specify the columns
modified by the query. These column references are converted to <A
-HREF="../../include/nodes/primnodes.h">Resdom</A> entries, which are
-placed in <A HREF="../../include/nodes/parsenodes.h">target list
-entries,</A> and linked together to make up the <I>target list</I> of
+HREF="../../include/nodes/primnodes.h">TargetEntry</A> entries, which are
+linked together to make up the <I>target list</I> of
the query. The target list is stored in Query.targetList, which is
generated by <A
HREF="../../backend/parser/parse_target.c">transformTargetList().</A></P><P>