From: Tom Lane Date: Tue, 10 Mar 2009 22:09:26 +0000 (+0000) Subject: Make SubPlan nodes carry the result's typmod as well as datatype OID. This is X-Git-Tag: REL8_4_BETA1~181 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=dcf3902f02db09a067f066bd46bc3ad354f323b9;p=postgresql 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. --- diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index ef3d5fc373..3c8bf6fb69 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -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); diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index 6b2d99b943..0950dd6131 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -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); diff --git a/src/backend/nodes/nodeFuncs.c b/src/backend/nodes/nodeFuncs.c index 8a04d71eb8..d0a3434783 100644 --- a/src/backend/nodes/nodeFuncs.c +++ b/src/backend/nodes/nodeFuncs.c @@ -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: diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index c68dea8a2c..d64f0ad042 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -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); diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c index 88dcbc2304..2cf177ab01 100644 --- a/src/backend/optimizer/plan/subselect.c +++ b/src/backend/optimizer/plan/subselect.c @@ -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); diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h index 3315329923..9cb4e8e50e 100644 --- a/src/include/nodes/primnodes.h +++ b/src/include/nodes/primnodes.h @@ -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") */