@ -11,7 +11,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 / path / pathkeys . c , v 1.77 2006 / 07 / 14 14 : 52 : 20 momjian Exp $
* $ PostgreSQL : pgsql / src / backend / optimizer / path / pathkeys . c , v 1.78 2006 / 08 / 17 17 : 02 : 49 tgl Exp $
*
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
*/
@ -1059,39 +1059,73 @@ convert_subquery_pathkeys(PlannerInfo *root, RelOptInfo *rel,
{
{
PathKeyItem * sub_item = ( PathKeyItem * ) lfirst ( j ) ;
PathKeyItem * sub_item = ( PathKeyItem * ) lfirst ( j ) ;
Node * sub_key = sub_item - > key ;
Node * sub_key = sub_item - > key ;
Expr * rtarg ;
ListCell * k ;
ListCell * k ;
/*
* We handle two cases : the sub_pathkey key can be either an exact
* match for a targetlist entry , or a RelabelType of a targetlist
* entry . ( The latter case is worth extra code because it arises
* frequently in connection with varchar fields . )
*/
if ( IsA ( sub_key , RelabelType ) )
rtarg = ( ( RelabelType * ) sub_key ) - > arg ;
else
rtarg = NULL ;
foreach ( k , sub_tlist )
foreach ( k , sub_tlist )
{
{
TargetEntry * tle = ( TargetEntry * ) lfirst ( k ) ;
TargetEntry * tle = ( TargetEntry * ) lfirst ( k ) ;
Node * outer_expr ;
PathKeyItem * outer_item ;
int score ;
if ( ! tle - > resjunk & &
/* resjunk items aren't visible to outer query */
equal ( tle - > expr , sub_key ) )
if ( tle - > resjunk )
continue ;
if ( equal ( tle - > expr , sub_key ) )
{
{
/* Found a representation for this sub_key */
/* Exact match */
Var * outer_var ;
outer_expr = ( Node * )
PathKeyItem * outer_item ;
makeVar ( rel - > relid ,
int score ;
tle - > resno ,
exprType ( ( Node * ) tle - > expr ) ,
outer_var = makeVar ( rel - > relid ,
exprTypmod ( ( Node * ) tle - > expr ) ,
tle - > resno ,
0 ) ;
exprType ( ( Node * ) tle - > expr ) ,
}
exprTypmod ( ( Node * ) tle - > expr ) ,
else if ( rtarg & & equal ( tle - > expr , rtarg ) )
0 ) ;
{
outer_item = makePathKeyItem ( ( Node * ) outer_var ,
/* Match after discarding RelabelType */
sub_item - > sortop ,
outer_expr = ( Node * )
true ) ;
makeVar ( rel - > relid ,
/* score = # of mergejoin peers */
tle - > resno ,
score = count_canonical_peers ( root , outer_item ) ;
exprType ( ( Node * ) tle - > expr ) ,
/* +1 if it matches the proper query_pathkeys item */
exprTypmod ( ( Node * ) tle - > expr ) ,
if ( retvallen < outer_query_keys & &
0 ) ;
list_member ( list_nth ( root - > query_pathkeys , retvallen ) , outer_item ) )
outer_expr = ( Node * )
score + + ;
makeRelabelType ( ( Expr * ) outer_expr ,
if ( score > best_score )
( ( RelabelType * ) sub_key ) - > resulttype ,
{
( ( RelabelType * ) sub_key ) - > resulttypmod ,
best_item = outer_item ;
( ( RelabelType * ) sub_key ) - > relabelformat ) ;
best_score = score ;
}
}
else
continue ;
/* Found a representation for this sub_key */
outer_item = makePathKeyItem ( outer_expr ,
sub_item - > sortop ,
true ) ;
/* score = # of mergejoin peers */
score = count_canonical_peers ( root , outer_item ) ;
/* +1 if it matches the proper query_pathkeys item */
if ( retvallen < outer_query_keys & &
list_member ( list_nth ( root - > query_pathkeys , retvallen ) , outer_item ) )
score + + ;
if ( score > best_score )
{
best_item = outer_item ;
best_score = score ;
}
}
}
}
}
}