Merge Resdom nodes into TargetEntry nodes to simplify code and save a
few palloc's. I also chose to eliminate the restype and restypmod fields entirely, since they are redundant with information stored in the node's contained expression; re-examining the expression at need seems simpler and more reliable than trying to keep restype/restypmod up to date. initdb forced due to change in contents of stored rules.
This commit is contained in:
parent
0f3748a28c
commit
ad161bcc8a
@ -9,7 +9,7 @@
|
||||
* 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 $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -190,14 +190,14 @@ SendRowDescriptionMessage(TupleDesc typeinfo, List *targetlist, int16 *formats)
|
||||
{
|
||||
/* 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
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* 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 $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -22,6 +22,7 @@
|
||||
#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"
|
||||
@ -106,18 +107,17 @@ DefineVirtualRelation(const RangeVar *relation, List *tlist, bool replace)
|
||||
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;
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* 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 $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -31,8 +31,8 @@
|
||||
* 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
|
||||
@ -101,11 +101,10 @@ ExecInitJunkFilter(List *targetList, bool hasoid, TupleTableSlot *slot)
|
||||
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++;
|
||||
}
|
||||
}
|
||||
@ -177,12 +176,11 @@ ExecInitJunkFilterConversion(List *targetList,
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -228,13 +226,12 @@ ExecGetJunkAttribute(JunkFilter *junkfilter,
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,7 @@
|
||||
*
|
||||
*
|
||||
* 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 $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -640,7 +640,7 @@ InitPlan(QueryDesc *queryDesc, bool explainOnly)
|
||||
{
|
||||
TargetEntry *tle = (TargetEntry *) lfirst(tlist);
|
||||
|
||||
if (tle->resdom->resjunk)
|
||||
if (tle->resjunk)
|
||||
{
|
||||
junk_filter_needed = true;
|
||||
break;
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* 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 $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -3467,7 +3467,7 @@ ExecCleanTargetListLength(List *targetlist)
|
||||
TargetEntry *curTle = (TargetEntry *) lfirst(tl);
|
||||
|
||||
Assert(IsA(curTle, TargetEntry));
|
||||
if (!curTle->resdom->resjunk)
|
||||
if (!curTle->resjunk)
|
||||
len++;
|
||||
}
|
||||
return len;
|
||||
@ -3516,7 +3516,7 @@ ExecTargetList(List *targetlist,
|
||||
{
|
||||
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,
|
||||
@ -3568,7 +3568,7 @@ ExecTargetList(List *targetlist,
|
||||
{
|
||||
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)
|
||||
{
|
||||
@ -3602,7 +3602,7 @@ ExecTargetList(List *targetlist,
|
||||
{
|
||||
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)
|
||||
{
|
||||
|
@ -15,7 +15,7 @@
|
||||
*
|
||||
*
|
||||
* 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 $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -784,15 +784,14 @@ ExecTypeFromTLInternal(List *targetList, bool hasoid, bool skipjunk)
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* 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 $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -561,7 +561,7 @@ ExecBuildProjectionInfo(List *targetList,
|
||||
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;
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* 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 $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -935,7 +935,7 @@ check_sql_fn_retval(Oid func_id, Oid rettype, List *queryTreeList,
|
||||
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),
|
||||
@ -961,7 +961,7 @@ check_sql_fn_retval(Oid func_id, Oid rettype, List *queryTreeList,
|
||||
*/
|
||||
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 */
|
||||
}
|
||||
@ -996,7 +996,7 @@ check_sql_fn_retval(Oid func_id, Oid rettype, List *queryTreeList,
|
||||
Oid tletype;
|
||||
Oid atttype;
|
||||
|
||||
if (tle->resdom->resjunk)
|
||||
if (tle->resjunk)
|
||||
continue;
|
||||
|
||||
do
|
||||
|
@ -7,7 +7,7 @@
|
||||
* 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 $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -828,12 +828,10 @@ ExecInitSubPlan(SubPlanState *node, EState *estate)
|
||||
/* 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;
|
||||
@ -844,12 +842,10 @@ ExecInitSubPlan(SubPlanState *node, EState *estate)
|
||||
/* 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;
|
||||
|
@ -15,7 +15,7 @@
|
||||
* 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 $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -539,26 +539,6 @@ _copyLimit(Limit *from)
|
||||
* ****************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
* _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
|
||||
*/
|
||||
@ -1077,8 +1057,13 @@ _copyTargetEntry(TargetEntry *from)
|
||||
{
|
||||
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;
|
||||
}
|
||||
@ -2670,9 +2655,6 @@ copyObject(void *from)
|
||||
/*
|
||||
* PRIMITIVE NODES
|
||||
*/
|
||||
case T_Resdom:
|
||||
retval = _copyResdom(from);
|
||||
break;
|
||||
case T_Alias:
|
||||
retval = _copyAlias(from);
|
||||
break;
|
||||
|
@ -18,7 +18,7 @@
|
||||
* 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 $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -82,21 +82,6 @@
|
||||
* 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)
|
||||
{
|
||||
@ -546,8 +531,13 @@ _equalSetToDefault(SetToDefault *a, SetToDefault *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;
|
||||
}
|
||||
@ -1814,9 +1804,6 @@ equal(void *a, void *b)
|
||||
/*
|
||||
* PRIMITIVE NODES
|
||||
*/
|
||||
case T_Resdom:
|
||||
retval = _equalResdom(a, b);
|
||||
break;
|
||||
case T_Alias:
|
||||
retval = _equalAlias(a, b);
|
||||
break;
|
||||
|
@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* 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 $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -87,48 +87,49 @@ makeVar(Index varno,
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
resdom->resjunk = resjunk;
|
||||
tle->resjunk = resjunk;
|
||||
|
||||
return resdom;
|
||||
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);
|
||||
|
||||
Assert(IsA(src_tle, TargetEntry));
|
||||
memcpy(tle, src_tle, sizeof(TargetEntry));
|
||||
return tle;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* 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*
|
||||
@ -520,21 +520,6 @@ _outHash(StringInfo str, Hash *node)
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
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)
|
||||
{
|
||||
@ -900,8 +885,13 @@ _outTargetEntry(StringInfo str, TargetEntry *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
|
||||
@ -1684,9 +1674,6 @@ _outNode(StringInfo str, void *obj)
|
||||
case T_Hash:
|
||||
_outHash(str, obj);
|
||||
break;
|
||||
case T_Resdom:
|
||||
_outResdom(str, obj);
|
||||
break;
|
||||
case T_Alias:
|
||||
_outAlias(str, obj);
|
||||
break;
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* 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
|
||||
@ -449,10 +449,10 @@ print_tl(List *tlist, List *rtable)
|
||||
{
|
||||
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);
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* 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
|
||||
@ -238,26 +238,6 @@ _readSetOperationStmt(void)
|
||||
* 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)
|
||||
{
|
||||
@ -787,8 +767,13 @@ _readTargetEntry(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();
|
||||
}
|
||||
@ -952,8 +937,6 @@ parseNodeString(void)
|
||||
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))
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* 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 $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -29,6 +29,7 @@
|
||||
#include "optimizer/var.h"
|
||||
#include "parser/parsetree.h"
|
||||
#include "parser/parse_clause.h"
|
||||
#include "parser/parse_expr.h"
|
||||
#include "rewrite/rewriteManip.h"
|
||||
|
||||
|
||||
@ -656,12 +657,12 @@ compare_tlist_datatypes(List *tlist, List *colTypes,
|
||||
{
|
||||
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)
|
||||
@ -740,7 +741,7 @@ qual_is_pushdown_safe(Query *subquery, Index rti, Node *qual,
|
||||
/* 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 &&
|
||||
|
@ -11,7 +11,7 @@
|
||||
* 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 $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -791,7 +791,7 @@ build_subquery_pathkeys(Query *root, RelOptInfo *rel, Query *subquery)
|
||||
{
|
||||
TargetEntry *tle = (TargetEntry *) lfirst(k);
|
||||
|
||||
if (!tle->resdom->resjunk &&
|
||||
if (!tle->resjunk &&
|
||||
equal(tle->expr, sub_key))
|
||||
{
|
||||
/* Found a representation for this sub_key */
|
||||
@ -800,9 +800,9 @@ build_subquery_pathkeys(Query *root, RelOptInfo *rel, Query *subquery)
|
||||
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,
|
||||
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
*
|
||||
* 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 $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -259,7 +259,7 @@ static List *
|
||||
build_relation_tlist(RelOptInfo *rel)
|
||||
{
|
||||
List *tlist = NIL;
|
||||
int resdomno = 1;
|
||||
int resno = 1;
|
||||
ListCell *v;
|
||||
|
||||
foreach(v, rel->reltargetlist)
|
||||
@ -267,8 +267,11 @@ build_relation_tlist(RelOptInfo *rel)
|
||||
/* 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;
|
||||
}
|
||||
@ -557,20 +560,18 @@ create_unique_plan(Query *root, UniquePath *best_path)
|
||||
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)
|
||||
@ -1844,7 +1845,7 @@ make_sort_from_pathkeys(Query *root, Plan *lefttree, List *pathkeys)
|
||||
{
|
||||
List *keysublist = (List *) lfirst(i);
|
||||
PathKeyItem *pathkey = NULL;
|
||||
Resdom *resdom = NULL;
|
||||
TargetEntry *tle = NULL;
|
||||
ListCell *j;
|
||||
|
||||
/*
|
||||
@ -1863,11 +1864,11 @@ make_sort_from_pathkeys(Query *root, Plan *lefttree, List *pathkeys)
|
||||
{
|
||||
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)
|
||||
@ -1901,14 +1902,11 @@ make_sort_from_pathkeys(Query *root, Plan *lefttree, List *pathkeys)
|
||||
/*
|
||||
* 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 */
|
||||
}
|
||||
|
||||
@ -1918,7 +1916,7 @@ make_sort_from_pathkeys(Query *root, Plan *lefttree, List *pathkeys)
|
||||
* 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);
|
||||
}
|
||||
|
||||
@ -1964,7 +1962,7 @@ make_sort_from_sortclauses(Query *root, List *sortcls, Plan *lefttree)
|
||||
* 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);
|
||||
}
|
||||
|
||||
@ -2020,7 +2018,7 @@ make_sort_from_groupcols(Query *root,
|
||||
* 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++;
|
||||
}
|
||||
@ -2253,7 +2251,7 @@ make_unique(Plan *lefttree, List *distinctList)
|
||||
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;
|
||||
@ -2311,7 +2309,7 @@ make_setop(SetOpCmd cmd, Plan *lefttree,
|
||||
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;
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* 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 $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -1349,7 +1349,7 @@ hash_safe_grouping(Query *parse)
|
||||
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;
|
||||
@ -1467,18 +1467,16 @@ make_subplanTargetList(Query *parse,
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1528,7 +1526,7 @@ locate_grouping_columns(Query *parse,
|
||||
if (!sl)
|
||||
elog(ERROR, "failed to locate grouping columns");
|
||||
|
||||
groupColIdx[keyno++] = te->resdom->resno;
|
||||
groupColIdx[keyno++] = te->resno;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1554,17 +1552,16 @@ postprocess_setop_tlist(List *new_tlist, List *orig_tlist)
|
||||
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");
|
||||
|
@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* 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 $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -20,6 +20,7 @@
|
||||
#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"
|
||||
|
||||
@ -462,9 +463,9 @@ set_uppernode_references(Plan *plan, Index subvarno)
|
||||
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;
|
||||
|
||||
@ -550,25 +551,25 @@ join_references_mutator(Node *node,
|
||||
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;
|
||||
}
|
||||
|
||||
@ -582,33 +583,33 @@ join_references_mutator(Node *node,
|
||||
/* 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;
|
||||
@ -668,32 +669,32 @@ replace_vars_with_subplan_refs_mutator(Node *node,
|
||||
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;
|
||||
|
@ -7,7 +7,7 @@
|
||||
* 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 $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -350,8 +350,9 @@ make_subplan(SubLink *slink, List *lefthand, bool isTopQual)
|
||||
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;
|
||||
@ -362,11 +363,11 @@ make_subplan(SubLink *slink, List *lefthand, bool isTopQual)
|
||||
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);
|
||||
@ -525,15 +526,15 @@ convert_sublink_opers(List *lefthand, List *operOids,
|
||||
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);
|
||||
|
||||
/*
|
||||
@ -547,8 +548,8 @@ convert_sublink_opers(List *lefthand, List *operOids,
|
||||
/* 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;
|
||||
@ -575,7 +576,7 @@ convert_sublink_opers(List *lefthand, List *operOids,
|
||||
leftop,
|
||||
rightop,
|
||||
exprType(leftop),
|
||||
te->resdom->restype));
|
||||
exprType((Node *) te->expr)));
|
||||
|
||||
ReleaseSysCache(tup);
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
||||
*
|
||||
*
|
||||
* 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 $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -458,7 +458,7 @@ has_nullable_targetlist(Query *subquery)
|
||||
TargetEntry *tle = (TargetEntry *) lfirst(l);
|
||||
|
||||
/* ignore resjunk columns */
|
||||
if (tle->resdom->resjunk)
|
||||
if (tle->resjunk)
|
||||
continue;
|
||||
|
||||
/* Must contain a Var of current level */
|
||||
|
@ -15,7 +15,7 @@
|
||||
* 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 $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -79,18 +79,17 @@ preprocess_targetlist(Query *parse, List *tlist)
|
||||
*/
|
||||
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
|
||||
@ -99,7 +98,7 @@ preprocess_targetlist(Query *parse, List *tlist)
|
||||
if (command_type == CMD_DELETE)
|
||||
tlist = list_copy(tlist);
|
||||
|
||||
tlist = lappend(tlist, makeTargetEntry(resdom, (Expr *) var));
|
||||
tlist = lappend(tlist, tle);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -132,18 +131,9 @@ preprocess_targetlist(Query *parse, List *tlist)
|
||||
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,
|
||||
@ -151,8 +141,15 @@ preprocess_targetlist(Query *parse, List *tlist)
|
||||
-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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -206,9 +203,8 @@ expand_targetlist(List *tlist, int command_type,
|
||||
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);
|
||||
@ -268,9 +264,6 @@ expand_targetlist(List *tlist, int command_type,
|
||||
(Datum) 0,
|
||||
true, /* isnull */
|
||||
true /* byval */ );
|
||||
/* label resdom with INT4, too */
|
||||
atttype = INT4OID;
|
||||
atttypmod = -1;
|
||||
}
|
||||
break;
|
||||
case CMD_UPDATE:
|
||||
@ -290,9 +283,6 @@ expand_targetlist(List *tlist, int command_type,
|
||||
(Datum) 0,
|
||||
true, /* isnull */
|
||||
true /* byval */ );
|
||||
/* label resdom with INT4, too */
|
||||
atttype = INT4OID;
|
||||
atttypmod = -1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -302,12 +292,10 @@ expand_targetlist(List *tlist, int command_type,
|
||||
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);
|
||||
@ -324,16 +312,14 @@ expand_targetlist(List *tlist, int command_type,
|
||||
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++;
|
||||
|
@ -14,7 +14,7 @@
|
||||
*
|
||||
*
|
||||
* 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 $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -32,6 +32,7 @@
|
||||
#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"
|
||||
|
||||
@ -429,7 +430,7 @@ generate_setop_tlist(List *colTypes, int flag,
|
||||
ListCell *i,
|
||||
*j,
|
||||
*k;
|
||||
Resdom *resdom;
|
||||
TargetEntry *tle;
|
||||
Node *expr;
|
||||
|
||||
j = list_head(input_tlist);
|
||||
@ -439,12 +440,11 @@ generate_setop_tlist(List *colTypes, int flag,
|
||||
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
|
||||
@ -463,29 +463,23 @@ generate_setop_tlist(List *colTypes, int flag,
|
||||
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);
|
||||
}
|
||||
@ -493,18 +487,17 @@ generate_setop_tlist(List *colTypes, int flag,
|
||||
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;
|
||||
@ -531,7 +524,7 @@ generate_append_tlist(List *colTypes, bool flag,
|
||||
ListCell *curColType;
|
||||
ListCell *ref_tl_item;
|
||||
int colindex;
|
||||
Resdom *resdom;
|
||||
TargetEntry *tle;
|
||||
Node *expr;
|
||||
ListCell *planl;
|
||||
int32 *colTypmods;
|
||||
@ -555,15 +548,17 @@ generate_append_tlist(List *colTypes, bool flag,
|
||||
{
|
||||
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
|
||||
@ -587,36 +582,34 @@ generate_append_tlist(List *colTypes, bool flag,
|
||||
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);
|
||||
@ -640,7 +633,7 @@ tlist_same_datatypes(List *tlist, List *colTypes, bool junkOK)
|
||||
{
|
||||
TargetEntry *tle = (TargetEntry *) lfirst(l);
|
||||
|
||||
if (tle->resdom->resjunk)
|
||||
if (tle->resjunk)
|
||||
{
|
||||
if (!junkOK)
|
||||
return false;
|
||||
@ -649,7 +642,7 @@ tlist_same_datatypes(List *tlist, List *colTypes, bool junkOK)
|
||||
{
|
||||
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);
|
||||
}
|
||||
@ -1105,8 +1098,7 @@ adjust_relid_set(Relids relids, Index oldrelid, Index newrelid)
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
@ -1124,18 +1116,15 @@ adjust_inherited_tlist(List *tlist,
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -1157,14 +1146,13 @@ adjust_inherited_tlist(List *tlist,
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -1172,17 +1160,11 @@ adjust_inherited_tlist(List *tlist,
|
||||
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++;
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* 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
|
||||
@ -966,22 +966,22 @@ has_distinct_on_clause(Query *query)
|
||||
{
|
||||
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 */
|
||||
@ -3314,10 +3314,6 @@ expression_tree_mutator(Node *node,
|
||||
break;
|
||||
case T_TargetEntry:
|
||||
{
|
||||
/*
|
||||
* We mutate the expression, but not the resdom, by
|
||||
* default.
|
||||
*/
|
||||
TargetEntry *targetentry = (TargetEntry *) node;
|
||||
TargetEntry *newnode;
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* 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 $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -789,7 +789,7 @@ is_distinct_query(Query *query)
|
||||
TargetEntry *tle = get_sortgroupclause_tle(grpcl,
|
||||
query->targetList);
|
||||
|
||||
if (tle->resdom->resjunk)
|
||||
if (tle->resjunk)
|
||||
break;
|
||||
}
|
||||
if (!gl) /* got to the end? */
|
||||
|
@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* 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 $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -378,6 +378,7 @@ build_physical_tlist(Query *root, RelOptInfo *rel)
|
||||
for (attrno = 1; attrno <= numattrs; attrno++)
|
||||
{
|
||||
Form_pg_attribute att_tup = relation->rd_att->attrs[attrno - 1];
|
||||
Var *var;
|
||||
|
||||
if (att_tup->attisdropped)
|
||||
{
|
||||
@ -386,13 +387,17 @@ build_physical_tlist(Query *root, RelOptInfo *rel)
|
||||
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);
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* 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 $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -25,12 +25,12 @@
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
@ -44,77 +44,6 @@ tlistentry_member(Node *node, List *targetlist)
|
||||
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.
|
||||
@ -153,24 +82,22 @@ flatten_tlist(List *tlist)
|
||||
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;
|
||||
TargetEntry *tle;
|
||||
|
||||
r = makeResdom(next_resdomno++,
|
||||
var->vartype,
|
||||
var->vartypmod,
|
||||
NULL,
|
||||
false);
|
||||
tlist = lappend(tlist,
|
||||
makeTargetEntry(r, copyObject(var)));
|
||||
tle = makeTargetEntry(copyObject(var), /* copy needed?? */
|
||||
next_resno++,
|
||||
NULL,
|
||||
false);
|
||||
tlist = lappend(tlist, tle);
|
||||
}
|
||||
}
|
||||
return tlist;
|
||||
@ -195,7 +122,7 @@ get_sortgroupclause_tle(SortClause *sortClause,
|
||||
{
|
||||
TargetEntry *tle = (TargetEntry *) lfirst(l);
|
||||
|
||||
if (tle->resdom->ressortgroupref == refnumber)
|
||||
if (tle->ressortgroupref == refnumber)
|
||||
return tle;
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
* 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 $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -438,15 +438,12 @@ transformViewStmt(ParseState *pstate, ViewStmt *stmt,
|
||||
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 */
|
||||
@ -507,7 +504,6 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
|
||||
{
|
||||
Query *qry = makeNode(Query);
|
||||
Query *selectQuery = NULL;
|
||||
bool copy_up_hack = false;
|
||||
List *sub_rtable;
|
||||
List *sub_namespace;
|
||||
List *icolumns;
|
||||
@ -615,7 +611,7 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
|
||||
* 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
|
||||
@ -627,28 +623,25 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
|
||||
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
|
||||
@ -690,7 +683,7 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
|
||||
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);
|
||||
|
||||
@ -708,28 +701,6 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
|
||||
(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);
|
||||
@ -2007,26 +1978,23 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
|
||||
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);
|
||||
@ -2284,11 +2252,10 @@ getSetColTypes(ParseState *pstate, Node *node)
|
||||
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;
|
||||
}
|
||||
@ -2324,8 +2291,8 @@ applyColumnNames(List *dst, List *src)
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2383,10 +2350,9 @@ transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt)
|
||||
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
|
||||
@ -2394,8 +2360,8 @@ transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt)
|
||||
* 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)
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* 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 $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -1161,10 +1161,9 @@ findTargetlistEntry(ParseState *pstate, Node *node, List **tlist, int clause)
|
||||
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)
|
||||
{
|
||||
@ -1204,9 +1203,8 @@ findTargetlistEntry(ParseState *pstate, Node *node, List **tlist, int clause)
|
||||
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 */
|
||||
@ -1282,7 +1280,7 @@ transformGroupClause(ParseState *pstate, List *grouplist,
|
||||
continue;
|
||||
|
||||
/* if tlist item is an UNKNOWN literal, change it to TEXT */
|
||||
restype = tle->resdom->restype;
|
||||
restype = exprType((Node *) tle->expr);
|
||||
|
||||
if (restype == UNKNOWNOID)
|
||||
{
|
||||
@ -1290,8 +1288,7 @@ transformGroupClause(ParseState *pstate, List *grouplist,
|
||||
restype, TEXTOID, -1,
|
||||
COERCION_IMPLICIT,
|
||||
COERCE_IMPLICIT_CAST);
|
||||
restype = tle->resdom->restype = TEXTOID;
|
||||
tle->resdom->restypmod = -1;
|
||||
restype = TEXTOID;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1304,7 +1301,7 @@ transformGroupClause(ParseState *pstate, List *grouplist,
|
||||
*/
|
||||
if (sortItem &&
|
||||
((SortClause *) lfirst(sortItem))->tleSortGroupRef ==
|
||||
tle->resdom->ressortgroupref)
|
||||
tle->ressortgroupref)
|
||||
{
|
||||
ordering_op = ((SortClause *) lfirst(sortItem))->sortop;
|
||||
sortItem = lnext(sortItem);
|
||||
@ -1405,7 +1402,7 @@ transformDistinctClause(ParseState *pstate, List *distinctlist,
|
||||
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")));
|
||||
@ -1445,7 +1442,7 @@ transformDistinctClause(ParseState *pstate, List *distinctlist,
|
||||
{
|
||||
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")));
|
||||
@ -1466,7 +1463,7 @@ transformDistinctClause(ParseState *pstate, List *distinctlist,
|
||||
{
|
||||
SortClause *scl = (SortClause *) lfirst(slitem);
|
||||
|
||||
if (tle->resdom->ressortgroupref == scl->tleSortGroupRef)
|
||||
if (tle->ressortgroupref == scl->tleSortGroupRef)
|
||||
{
|
||||
result = lappend(result, copyObject(scl));
|
||||
break;
|
||||
@ -1501,7 +1498,7 @@ addAllTargetsToSortList(ParseState *pstate, List *sortlist,
|
||||
{
|
||||
TargetEntry *tle = (TargetEntry *) lfirst(l);
|
||||
|
||||
if (!tle->resdom->resjunk)
|
||||
if (!tle->resjunk)
|
||||
sortlist = addTargetToSortList(pstate, tle,
|
||||
sortlist, targetlist,
|
||||
SORTBY_ASC, NIL,
|
||||
@ -1533,7 +1530,7 @@ addTargetToSortList(ParseState *pstate, TargetEntry *tle,
|
||||
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)
|
||||
@ -1542,8 +1539,7 @@ addTargetToSortList(ParseState *pstate, TargetEntry *tle,
|
||||
restype, TEXTOID, -1,
|
||||
COERCION_IMPLICIT,
|
||||
COERCE_IMPLICIT_CAST);
|
||||
restype = tle->resdom->restype = TEXTOID;
|
||||
tle->resdom->restypmod = -1;
|
||||
restype = TEXTOID;
|
||||
}
|
||||
|
||||
sortcl->tleSortGroupRef = assignSortGroupRef(tle, targetlist);
|
||||
@ -1586,20 +1582,20 @@ assignSortGroupRef(TargetEntry *tle, List *tlist)
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1613,7 +1609,7 @@ assignSortGroupRef(TargetEntry *tle, List *tlist)
|
||||
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 */
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* 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 $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -960,13 +960,13 @@ transformSubLink(ParseState *pstate, SubLink *sublink)
|
||||
* 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")));
|
||||
@ -1045,7 +1045,7 @@ transformSubLink(ParseState *pstate, SubLink *sublink)
|
||||
Operator optup;
|
||||
Form_pg_operator opform;
|
||||
|
||||
if (tent->resdom->resjunk)
|
||||
if (tent->resjunk)
|
||||
continue;
|
||||
|
||||
if (ll_item == NULL)
|
||||
@ -1417,18 +1417,16 @@ exprType(Node *expr)
|
||||
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
|
||||
@ -1456,18 +1454,16 @@ exprType(Node *expr)
|
||||
|
||||
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
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* 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 $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -910,15 +910,15 @@ addRangeTableEntryForSubquery(ParseState *pstate,
|
||||
{
|
||||
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));
|
||||
}
|
||||
}
|
||||
@ -1260,10 +1260,10 @@ expandRTE(List *rtable, int rtindex, int sublevels_up,
|
||||
{
|
||||
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)
|
||||
{
|
||||
@ -1279,8 +1279,8 @@ expandRTE(List *rtable, int rtindex, int sublevels_up,
|
||||
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);
|
||||
@ -1532,14 +1532,12 @@ expandRelAttrs(ParseState *pstate, List *rtable, int rtindex, int sublevels_up)
|
||||
{
|
||||
char *label = strVal(lfirst(name));
|
||||
Node *varnode = (Node *) lfirst(var);
|
||||
TargetEntry *te = makeNode(TargetEntry);
|
||||
TargetEntry *te;
|
||||
|
||||
te->resdom = makeResdom((AttrNumber) pstate->p_next_resno++,
|
||||
exprType(varnode),
|
||||
exprTypmod(varnode),
|
||||
label,
|
||||
false);
|
||||
te->expr = (Expr *) varnode;
|
||||
te = makeTargetEntry((Expr *) varnode,
|
||||
(AttrNumber) pstate->p_next_resno++,
|
||||
label,
|
||||
false);
|
||||
te_list = lappend(te_list, te);
|
||||
}
|
||||
|
||||
@ -1641,11 +1639,11 @@ get_rte_attribute_type(RangeTblEntry *rte, AttrNumber attnum,
|
||||
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:
|
||||
@ -1856,7 +1854,7 @@ get_tle_by_resno(List *tlist, AttrNumber resno)
|
||||
{
|
||||
TargetEntry *tle = (TargetEntry *) lfirst(l);
|
||||
|
||||
if (tle->resdom->resno == resno)
|
||||
if (tle->resno == resno)
|
||||
return tle;
|
||||
}
|
||||
return NULL;
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* 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 $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -30,7 +30,7 @@
|
||||
#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,
|
||||
@ -65,17 +65,10 @@ transformTargetEntry(ParseState *pstate,
|
||||
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)
|
||||
{
|
||||
/*
|
||||
@ -85,13 +78,10 @@ transformTargetEntry(ParseState *pstate,
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@ -176,13 +166,13 @@ markTargetListOrigins(ParseState *pstate, List *targetlist)
|
||||
{
|
||||
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.
|
||||
*
|
||||
@ -190,7 +180,8 @@ markTargetListOrigins(ParseState *pstate, List *targetlist)
|
||||
* 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;
|
||||
@ -206,20 +197,20 @@ markTargetListOrigin(ParseState *pstate, Resdom *res, Var *var, int levelsup)
|
||||
{
|
||||
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:
|
||||
@ -229,7 +220,7 @@ markTargetListOrigin(ParseState *pstate, Resdom *res, Var *var, int levelsup)
|
||||
|
||||
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:
|
||||
@ -264,7 +255,6 @@ updateTargetListEntry(ParseState *pstate,
|
||||
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);
|
||||
@ -368,13 +358,6 @@ updateTargetListEntry(ParseState *pstate,
|
||||
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
|
||||
@ -382,8 +365,8 @@ updateTargetListEntry(ParseState *pstate,
|
||||
* 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;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -881,13 +864,10 @@ ExpandIndirectionStar(ParseState *pstate, A_Indirection *ind)
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* 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 $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -22,6 +22,7 @@
|
||||
#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"
|
||||
@ -290,11 +291,11 @@ DefineQueryRewrite(RuleStmt *stmt)
|
||||
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)
|
||||
@ -318,12 +319,12 @@ DefineQueryRewrite(RuleStmt *stmt)
|
||||
(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)));
|
||||
@ -335,8 +336,9 @@ DefineQueryRewrite(RuleStmt *stmt)
|
||||
* 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)));
|
||||
|
@ -7,7 +7,7 @@
|
||||
* 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 $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -312,12 +312,11 @@ rewriteTargetList(Query *parsetree, Relation target_relation)
|
||||
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];
|
||||
@ -344,11 +343,10 @@ rewriteTargetList(Query *parsetree, Relation target_relation)
|
||||
*/
|
||||
|
||||
/* 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++;
|
||||
@ -407,12 +405,10 @@ rewriteTargetList(Query *parsetree, Relation target_relation)
|
||||
}
|
||||
|
||||
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)
|
||||
@ -436,7 +432,7 @@ process_matched_tle(TargetEntry *src_tle,
|
||||
TargetEntry *prior_tle,
|
||||
const char *attrName)
|
||||
{
|
||||
Resdom *resdom = src_tle->resdom;
|
||||
TargetEntry *result;
|
||||
Node *src_expr;
|
||||
Node *prior_expr;
|
||||
Node *src_input;
|
||||
@ -547,7 +543,9 @@ process_matched_tle(TargetEntry *src_tle,
|
||||
newexpr = NULL;
|
||||
}
|
||||
|
||||
return makeTargetEntry(resdom, (Expr *) newexpr);
|
||||
result = flatCopyTargetEntry(src_tle);
|
||||
result->expr = (Expr *) newexpr;
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -3,7 +3,7 @@
|
||||
* 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.
|
||||
*
|
||||
@ -1493,13 +1493,12 @@ deparse_context_for_subplan(const char *name, List *tlist,
|
||||
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))
|
||||
@ -1518,7 +1517,7 @@ deparse_context_for_subplan(const char *name, List *tlist,
|
||||
}
|
||||
}
|
||||
/* 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)));
|
||||
}
|
||||
|
||||
@ -1974,7 +1973,7 @@ get_basic_select_query(Query *query, deparse_context *context,
|
||||
TargetEntry *tle = (TargetEntry *) lfirst(l);
|
||||
char *colname;
|
||||
|
||||
if (tle->resdom->resjunk)
|
||||
if (tle->resjunk)
|
||||
continue; /* ignore junk entries */
|
||||
|
||||
appendStringInfo(buf, sep);
|
||||
@ -1992,7 +1991,7 @@ get_basic_select_query(Query *query, deparse_context *context,
|
||||
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 */
|
||||
{
|
||||
@ -2166,8 +2165,8 @@ get_rule_sortgroupclause(SortClause *srt, List *tlist, bool force_colno,
|
||||
*/
|
||||
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);
|
||||
@ -2227,7 +2226,7 @@ get_insert_query_def(Query *query, deparse_context *context)
|
||||
{
|
||||
TargetEntry *tle = (TargetEntry *) lfirst(l);
|
||||
|
||||
if (tle->resdom->resjunk)
|
||||
if (tle->resjunk)
|
||||
continue; /* ignore junk entries */
|
||||
|
||||
appendStringInfo(buf, sep);
|
||||
@ -2239,7 +2238,7 @@ get_insert_query_def(Query *query, deparse_context *context)
|
||||
*/
|
||||
appendStringInfoString(buf,
|
||||
quote_identifier(get_relid_attribute_name(rte->relid,
|
||||
tle->resdom->resno)));
|
||||
tle->resno)));
|
||||
|
||||
/*
|
||||
* Print any indirection needed (subfields or subscripts), and
|
||||
@ -2299,7 +2298,7 @@ get_update_query_def(Query *query, deparse_context *context)
|
||||
TargetEntry *tle = (TargetEntry *) lfirst(l);
|
||||
Node *expr;
|
||||
|
||||
if (tle->resdom->resjunk)
|
||||
if (tle->resjunk)
|
||||
continue; /* ignore junk entries */
|
||||
|
||||
appendStringInfo(buf, sep);
|
||||
@ -2311,7 +2310,7 @@ get_update_query_def(Query *query, deparse_context *context)
|
||||
*/
|
||||
appendStringInfoString(buf,
|
||||
quote_identifier(get_relid_attribute_name(rte->relid,
|
||||
tle->resdom->resno)));
|
||||
tle->resno)));
|
||||
|
||||
/*
|
||||
* Print any indirection needed (subfields or subscripts), and
|
||||
|
@ -37,7 +37,7 @@
|
||||
* 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 $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -53,6 +53,6 @@
|
||||
*/
|
||||
|
||||
/* yyyymmddN */
|
||||
#define CATALOG_VERSION_NO 200503291
|
||||
#define CATALOG_VERSION_NO 200504061
|
||||
|
||||
#endif
|
||||
|
@ -7,7 +7,7 @@
|
||||
* 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 $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -29,13 +29,12 @@ extern Var *makeVar(Index varno,
|
||||
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,
|
||||
|
@ -7,7 +7,7 @@
|
||||
* 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 $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -93,8 +93,7 @@ typedef enum NodeTag
|
||||
/*
|
||||
* TAGS FOR PRIMITIVE NODES (primnodes.h)
|
||||
*/
|
||||
T_Resdom = 300,
|
||||
T_Alias,
|
||||
T_Alias = 300,
|
||||
T_RangeVar,
|
||||
T_Expr,
|
||||
T_Var,
|
||||
|
@ -7,7 +7,7 @@
|
||||
* 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 $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -552,11 +552,11 @@ typedef struct RangeTblEntry
|
||||
* 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,
|
||||
|
@ -10,7 +10,7 @@
|
||||
* 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 $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -27,72 +27,6 @@
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*--------------------
|
||||
* 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
|
||||
@ -822,7 +756,7 @@ typedef struct SetToDefault
|
||||
int32 typeMod; /* typemod for substituted value */
|
||||
} SetToDefault;
|
||||
|
||||
/*
|
||||
/*--------------------
|
||||
* TargetEntry -
|
||||
* a target entry (used in query target lists)
|
||||
*
|
||||
@ -831,14 +765,63 @@ typedef struct SetToDefault
|
||||
* 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;
|
||||
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
* 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 $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -17,10 +17,7 @@
|
||||
#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);
|
||||
|
@ -71,9 +71,8 @@ transformFromClause().</A> Query.rtable holds the query's range table.</P><P>
|
||||
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>
|
||||
|
Loading…
x
Reference in New Issue
Block a user