77 * Portions Copyright (c) 1994, Regents of the University of California
88 *
99 * IDENTIFICATION
10- * $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.112 2006/10/04 00:29:54 momjian Exp $
10+ * $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.113 2006/12/06 19:40:01 tgl Exp $
1111 *
1212 *-------------------------------------------------------------------------
1313 */
@@ -75,6 +75,7 @@ typedef struct convert_testexpr_context
7575{
7676int rtindex ;/* RT index for Vars, or 0 for Params */
7777List * righthandIds ;/* accumulated list of Vars or Param IDs */
78+ List * sub_tlist ;/* subselect targetlist (if given) */
7879}convert_testexpr_context ;
7980
8081typedef struct finalize_primnode_context
@@ -86,7 +87,8 @@ typedef struct finalize_primnode_context
8687
8788static Node * convert_testexpr (Node * testexpr ,
8889int rtindex ,
89- List * * righthandIds );
90+ List * * righthandIds ,
91+ List * sub_tlist );
9092static Node * convert_testexpr_mutator (Node * node ,
9193convert_testexpr_context * context );
9294static bool subplan_is_hashable (SubLink * slink ,SubPlan * node );
@@ -379,7 +381,8 @@ make_subplan(SubLink *slink, Node *testexpr, bool isTopQual)
379381/* Adjust the Params */
380382result = convert_testexpr (testexpr ,
3813830 ,
382- & node -> paramIds );
384+ & node -> paramIds ,
385+ NIL );
383386node -> setParam = list_copy (node -> paramIds );
384387PlannerInitPlan = lappend (PlannerInitPlan ,node );
385388
@@ -396,7 +399,8 @@ make_subplan(SubLink *slink, Node *testexpr, bool isTopQual)
396399/* Adjust the Params */
397400node -> testexpr = convert_testexpr (testexpr ,
3984010 ,
399- & node -> paramIds );
402+ & node -> paramIds ,
403+ NIL );
400404
401405/*
402406 * We can't convert subplans of ALL_SUBLINK or ANY_SUBLINK types to
@@ -470,6 +474,10 @@ make_subplan(SubLink *slink, Node *testexpr, bool isTopQual)
470474 * of the Var nodes are returned in *righthandIds (this is a bit of a type
471475 * cheat, but we can get away with it).
472476 *
477+ * The subquery targetlist need be supplied only if rtindex is not 0.
478+ * We consult it to extract the correct typmods for the created Vars.
479+ * (XXX this is a kluge that could go away if Params carried typmod.)
480+ *
473481 * The given testexpr has already been recursively processed by
474482 * process_sublinks_mutator. Hence it can no longer contain any
475483 * PARAM_SUBLINK Params for lower SubLink nodes; we can safely assume that
@@ -478,13 +486,15 @@ make_subplan(SubLink *slink, Node *testexpr, bool isTopQual)
478486static Node *
479487convert_testexpr (Node * testexpr ,
480488int rtindex ,
481- List * * righthandIds )
489+ List * * righthandIds ,
490+ List * sub_tlist )
482491{
483492Node * result ;
484493convert_testexpr_context context ;
485494
486495context .rtindex = rtindex ;
487496context .righthandIds = NIL ;
497+ context .sub_tlist = sub_tlist ;
488498result = convert_testexpr_mutator (testexpr ,& context );
489499* righthandIds = context .righthandIds ;
490500return result ;
@@ -516,10 +526,23 @@ convert_testexpr_mutator(Node *node,
516526/* Make the Var node representing the subplan's result */
517527Var * newvar ;
518528
529+ /*
530+ * XXX kluge: since Params don't carry typmod, we have to
531+ * look into the subquery targetlist to find out the right
532+ * typmod to assign to the Var.
533+ */
534+ TargetEntry * ste = get_tle_by_resno (context -> sub_tlist ,
535+ param -> paramid );
536+
537+ if (ste == NULL || ste -> resjunk )
538+ elog (ERROR ,"subquery output %d not found" ,
539+ param -> paramid );
540+ Assert (param -> paramtype == exprType ((Node * )ste -> expr ));
541+
519542newvar = makeVar (context -> rtindex ,
520543param -> paramid ,
521544param -> paramtype ,
522- -1 ,
545+ exprTypmod (( Node * ) ste -> expr ) ,
5235460 );
524547
525548/*
@@ -752,7 +775,8 @@ convert_IN_to_join(PlannerInfo *root, SubLink *sublink)
752775 */
753776return convert_testexpr (sublink -> testexpr ,
754777rtindex ,
755- & ininfo -> sub_targetlist );
778+ & ininfo -> sub_targetlist ,
779+ subselect -> targetList );
756780}
757781
758782/*