Commit dcf3902f authored by Tom Lane's avatar Tom Lane

Make SubPlan nodes carry the result's typmod as well as datatype OID. This is

for consistency with the (relatively) recent addition of typmod to SubLink.
An example of why it's a good idea is to be seen in the recent "failed to
locate grouping columns" bug, which wouldn't have happened if a SubPlan
exposed the same typmod info as the SubLink it was derived from.

This could be back-patched, since it doesn't affect any on-disk data format,
but for the moment it doesn't seem necessary to do so.
parent 4886dc92
......@@ -15,7 +15,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.425 2009/02/25 03:30:37 tgl Exp $
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.426 2009/03/10 22:09:25 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -1113,6 +1113,7 @@ _copySubPlan(SubPlan *from)
COPY_NODE_FIELD(paramIds);
COPY_SCALAR_FIELD(plan_id);
COPY_SCALAR_FIELD(firstColType);
COPY_SCALAR_FIELD(firstColTypmod);
COPY_SCALAR_FIELD(useHashTable);
COPY_SCALAR_FIELD(unknownEqFalse);
COPY_NODE_FIELD(setParam);
......
......@@ -22,7 +22,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.349 2009/02/25 03:30:37 tgl Exp $
* $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.350 2009/03/10 22:09:25 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -342,6 +342,7 @@ _equalSubPlan(SubPlan *a, SubPlan *b)
COMPARE_NODE_FIELD(paramIds);
COMPARE_SCALAR_FIELD(plan_id);
COMPARE_SCALAR_FIELD(firstColType);
COMPARE_SCALAR_FIELD(firstColTypmod);
COMPARE_SCALAR_FIELD(useHashTable);
COMPARE_SCALAR_FIELD(unknownEqFalse);
COMPARE_NODE_FIELD(setParam);
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/nodeFuncs.c,v 1.38 2009/02/25 03:30:37 tgl Exp $
* $PostgreSQL: pgsql/src/backend/nodes/nodeFuncs.c,v 1.39 2009/03/10 22:09:25 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -28,7 +28,7 @@ static int leftmostLoc(int loc1, int loc2);
/*
* exprType -
* returns the Oid of the type of the expression. (Used for typechecking.)
* returns the Oid of the type of the expression's result.
*/
Oid
exprType(Node *expr)
......@@ -117,11 +117,6 @@ exprType(Node *expr)
break;
case T_SubPlan:
{
/*
* Although the parser does not ever deal with already-planned
* expression trees, we support SubPlan nodes in this routine
* for the convenience of ruleutils.c.
*/
SubPlan *subplan = (SubPlan *) expr;
if (subplan->subLinkType == EXPR_SUBLINK ||
......@@ -148,7 +143,6 @@ exprType(Node *expr)
break;
case T_AlternativeSubPlan:
{
/* As above, supported for the convenience of ruleutils.c */
AlternativeSubPlan *asplan = (AlternativeSubPlan *) expr;
/* subplans should all return the same thing */
......@@ -236,8 +230,8 @@ exprType(Node *expr)
/*
* exprTypmod -
* returns the type-specific attrmod of the expression, if it can be
* determined. In most cases, it can't and we return -1.
* returns the type-specific modifier of the expression's result type,
* if it can be determined. In many cases, it can't and we return -1.
*/
int32
exprTypmod(Node *expr)
......@@ -286,6 +280,32 @@ exprTypmod(Node *expr)
}
}
break;
case T_SubPlan:
{
SubPlan *subplan = (SubPlan *) expr;
if (subplan->subLinkType == EXPR_SUBLINK ||
subplan->subLinkType == ARRAY_SUBLINK)
{
/* get the typmod of the subselect's first target column */
/* note we don't need to care if it's an array */
return subplan->firstColTypmod;
}
else
{
/* for all other subplan types, result is boolean */
return -1;
}
}
break;
case T_AlternativeSubPlan:
{
AlternativeSubPlan *asplan = (AlternativeSubPlan *) expr;
/* subplans should all return the same thing */
return exprTypmod((Node *) linitial(asplan->subplans));
}
break;
case T_FieldSelect:
return ((FieldSelect *) expr)->resulttypmod;
case T_RelabelType:
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.353 2009/02/25 03:30:37 tgl Exp $
* $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.354 2009/03/10 22:09:25 tgl Exp $
*
* NOTES
* Every node type that can appear in stored rules' parsetrees *must*
......@@ -957,6 +957,7 @@ _outSubPlan(StringInfo str, SubPlan *node)
WRITE_NODE_FIELD(paramIds);
WRITE_INT_FIELD(plan_id);
WRITE_OID_FIELD(firstColType);
WRITE_INT_FIELD(firstColTypmod);
WRITE_BOOL_FIELD(useHashTable);
WRITE_BOOL_FIELD(unknownEqFalse);
WRITE_NODE_FIELD(setParam);
......
......@@ -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.146 2009/02/25 03:30:37 tgl Exp $
* $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.147 2009/03/10 22:09:26 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -229,13 +229,13 @@ SS_assign_worktable_param(PlannerInfo *root)
/*
* Get the datatype of the first column of the plan's output.
*
* This is stored for ARRAY_SUBLINK and for exprType(), which doesn't have any
* way to get at the plan associated with a SubPlan node. We really only need
* the value for EXPR_SUBLINK and ARRAY_SUBLINK subplans, but for consistency
* we set it always.
* This is stored for ARRAY_SUBLINK execution and for exprType()/exprTypmod(),
* which have no way to get at the plan associated with a SubPlan node.
* We really only need the info for EXPR_SUBLINK and ARRAY_SUBLINK subplans,
* but for consistency we save it always.
*/
static Oid
get_first_col_type(Plan *plan)
static void
get_first_col_type(Plan *plan, Oid *coltype, int32 *coltypmod)
{
/* In cases such as EXISTS, tlist might be empty; arbitrarily use VOID */
if (plan->targetlist)
......@@ -244,9 +244,14 @@ get_first_col_type(Plan *plan)
Assert(IsA(tent, TargetEntry));
if (!tent->resjunk)
return exprType((Node *) tent->expr);
{
*coltype = exprType((Node *) tent->expr);
*coltypmod = exprTypmod((Node *) tent->expr);
return;
}
}
return VOIDOID;
*coltype = VOIDOID;
*coltypmod = -1;
}
/*
......@@ -414,7 +419,7 @@ build_subplan(PlannerInfo *root, Plan *plan, List *rtable,
splan->subLinkType = subLinkType;
splan->testexpr = NULL;
splan->paramIds = NIL;
splan->firstColType = get_first_col_type(plan);
get_first_col_type(plan, &splan->firstColType, &splan->firstColTypmod);
splan->useHashTable = false;
splan->unknownEqFalse = unknownEqFalse;
splan->setParam = NIL;
......@@ -876,7 +881,7 @@ SS_process_ctes(PlannerInfo *root)
splan->subLinkType = CTE_SUBLINK;
splan->testexpr = NULL;
splan->paramIds = NIL;
splan->firstColType = get_first_col_type(plan);
get_first_col_type(plan, &splan->firstColType, &splan->firstColTypmod);
splan->useHashTable = false;
splan->unknownEqFalse = false;
splan->setParam = NIL;
......@@ -2111,7 +2116,7 @@ SS_make_initplan_from_plan(PlannerInfo *root, Plan *plan,
*/
node = makeNode(SubPlan);
node->subLinkType = EXPR_SUBLINK;
node->firstColType = get_first_col_type(plan);
get_first_col_type(plan, &node->firstColType, &node->firstColTypmod);
node->plan_id = list_length(root->glob->subplans);
root->init_plans = lappend(root->init_plans, node);
......
......@@ -10,7 +10,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/nodes/primnodes.h,v 1.146 2009/02/25 03:30:37 tgl Exp $
* $PostgreSQL: pgsql/src/include/nodes/primnodes.h,v 1.147 2009/03/10 22:09:26 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -504,6 +504,7 @@ typedef struct SubPlan
int plan_id; /* Index (from 1) in PlannedStmt.subplans */
/* Extra data useful for determining subplan's output type: */
Oid firstColType; /* Type of first column of subplan result */
int32 firstColTypmod; /* Typmod of first column of subplan result */
/* Information about execution strategy: */
bool useHashTable; /* TRUE to store subselect output in a hash
* table (implies we are doing "IN") */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment