@ -7,7 +7,7 @@
* Portions Copyright ( c ) 1994 , Regents of the University of California
* Portions Copyright ( c ) 1994 , Regents of the University of California
*
*
* IDENTIFICATION
* IDENTIFICATION
* $ PostgreSQL : pgsql / src / backend / optimizer / plan / subselect . c , v 1.129 2008 / 01 / 17 20 : 35 : 27 tgl Exp $
* $ PostgreSQL : pgsql / src / backend / optimizer / plan / subselect . c , v 1.130 2008 / 04 / 21 20 : 54 : 15 tgl Exp $
*
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
*/
@ -725,10 +725,13 @@ convert_IN_to_join(PlannerInfo *root, SubLink *sublink)
Query * parse = root - > parse ;
Query * parse = root - > parse ;
Query * subselect = ( Query * ) sublink - > subselect ;
Query * subselect = ( Query * ) sublink - > subselect ;
List * in_operators ;
List * in_operators ;
List * left_exprs ;
List * right_exprs ;
Relids left_varnos ;
Relids left_varnos ;
int rtindex ;
int rtindex ;
RangeTblEntry * rte ;
RangeTblEntry * rte ;
RangeTblRef * rtr ;
RangeTblRef * rtr ;
List * subquery_vars ;
InClauseInfo * ininfo ;
InClauseInfo * ininfo ;
Node * result ;
Node * result ;
@ -744,28 +747,37 @@ convert_IN_to_join(PlannerInfo *root, SubLink *sublink)
return NULL ;
return NULL ;
if ( sublink - > testexpr & & IsA ( sublink - > testexpr , OpExpr ) )
if ( sublink - > testexpr & & IsA ( sublink - > testexpr , OpExpr ) )
{
{
Oid opno = ( ( OpExpr * ) sublink - > testexpr ) - > opno ;
OpExpr * op = ( OpExpr * ) sublink - > testexpr ;
Oid opno = op - > opno ;
List * opfamilies ;
List * opfamilies ;
List * opstrats ;
List * opstrats ;
if ( list_length ( op - > args ) ! = 2 )
return NULL ; /* not binary operator? */
get_op_btree_interpretation ( opno , & opfamilies , & opstrats ) ;
get_op_btree_interpretation ( opno , & opfamilies , & opstrats ) ;
if ( ! list_member_int ( opstrats , ROWCOMPARE_EQ ) )
if ( ! list_member_int ( opstrats , ROWCOMPARE_EQ ) )
return NULL ;
return NULL ;
in_operators = list_make1_oid ( opno ) ;
in_operators = list_make1_oid ( opno ) ;
left_exprs = list_make1 ( linitial ( op - > args ) ) ;
right_exprs = list_make1 ( lsecond ( op - > args ) ) ;
}
}
else if ( and_clause ( sublink - > testexpr ) )
else if ( and_clause ( sublink - > testexpr ) )
{
{
ListCell * lc ;
ListCell * lc ;
/* OK, but we need to extract the per-column operator OIDs */
/* OK, but we need to extract the per-column inf o */
in_operators = NIL ;
in_operators = left_exprs = right_exprs = NIL ;
foreach ( lc , ( ( BoolExpr * ) sublink - > testexpr ) - > args )
foreach ( lc , ( ( BoolExpr * ) sublink - > testexpr ) - > args )
{
{
OpExpr * op = ( OpExpr * ) lfirst ( lc ) ;
OpExpr * op = ( OpExpr * ) lfirst ( lc ) ;
if ( ! IsA ( op , OpExpr ) ) /* probably shouldn't happen */
if ( ! IsA ( op , OpExpr ) ) /* probably shouldn't happen */
return NULL ;
return NULL ;
if ( list_length ( op - > args ) ! = 2 )
return NULL ; /* not binary operator? */
in_operators = lappend_oid ( in_operators , op - > opno ) ;
in_operators = lappend_oid ( in_operators , op - > opno ) ;
left_exprs = lappend ( left_exprs , linitial ( op - > args ) ) ;
right_exprs = lappend ( right_exprs , lsecond ( op - > args ) ) ;
}
}
}
}
else
else
@ -782,10 +794,13 @@ convert_IN_to_join(PlannerInfo *root, SubLink *sublink)
* The left - hand expressions must contain some Vars of the current query ,
* The left - hand expressions must contain some Vars of the current query ,
* else it ' s not gonna be a join .
* else it ' s not gonna be a join .
*/
*/
left_varnos = pull_varnos ( sublink - > testexpr ) ;
left_varnos = pull_varnos ( ( Node * ) left_exprs ) ;
if ( bms_is_empty ( left_varnos ) )
if ( bms_is_empty ( left_varnos ) )
return NULL ;
return NULL ;
/* ... and the right-hand expressions better not contain Vars at all */
Assert ( ! contain_var_clause ( ( Node * ) right_exprs ) ) ;
/*
/*
* The combining operators and left - hand expressions mustn ' t be volatile .
* The combining operators and left - hand expressions mustn ' t be volatile .
*/
*/
@ -810,6 +825,20 @@ convert_IN_to_join(PlannerInfo *root, SubLink *sublink)
rtr - > rtindex = rtindex ;
rtr - > rtindex = rtindex ;
parse - > jointree - > fromlist = lappend ( parse - > jointree - > fromlist , rtr ) ;
parse - > jointree - > fromlist = lappend ( parse - > jointree - > fromlist , rtr ) ;
/*
* Build a list of Vars representing the subselect outputs .
*/
subquery_vars = generate_subquery_vars ( root ,
subselect - > targetList ,
rtindex ) ;
/*
* Build the result qual expression , replacing Params with these Vars .
*/
result = convert_testexpr ( root ,
sublink - > testexpr ,
subquery_vars ) ;
/*
/*
* Now build the InClauseInfo node .
* Now build the InClauseInfo node .
*/
*/
@ -819,24 +848,20 @@ convert_IN_to_join(PlannerInfo *root, SubLink *sublink)
ininfo - > in_operators = in_operators ;
ininfo - > in_operators = in_operators ;
/*
/*
* ininfo - > sub_targetlist is filled with a list of Vars representing the
* ininfo - > sub_targetlist must be filled with a list of expressions that
* subselect outputs .
* would need to be unique - ified if we try to implement the IN using a
* regular join to unique - ified subquery output . This is most easily done
* by applying convert_testexpr to just the RHS inputs of the testexpr
* operators . That handles cases like type coercions of the subquery
* outputs , clauses dropped due to const - simplification , etc .
*/
*/
ininfo - > sub_targetlist = generate_subquery_vars ( root ,
ininfo - > sub_targetlist = ( List * ) convert_testexpr ( root ,
subselect - > targetList ,
( Node * ) right_exprs ,
rtindex ) ;
subquery_vars ) ;
Assert ( list_length ( in_operators ) = = list_length ( ininfo - > sub_targetlist ) ) ;
/* Add the completed node to the query's list */
/* Add the completed node to the query's list */
root - > in_info_list = lappend ( root - > in_info_list , ininfo ) ;
root - > in_info_list = lappend ( root - > in_info_list , ininfo ) ;
/*
* Build the result qual expression .
*/
result = convert_testexpr ( root ,
sublink - > testexpr ,
ininfo - > sub_targetlist ) ;
return result ;
return result ;
}
}