@ -3,7 +3,7 @@
* out of it ' s tuple
*
* IDENTIFICATION
* $ Header : / cvsroot / pgsql / src / backend / utils / adt / ruleutils . c , v 1.23 1999 / 08 / 25 23 : 21 : 3 5 tgl Exp $
* $ Header : / cvsroot / pgsql / src / backend / utils / adt / ruleutils . c , v 1.24 1999 / 08 / 28 03 : 59 : 0 5 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg .
*
@ -58,6 +58,11 @@ typedef struct QryHier
Query * query ;
} QryHier ;
typedef struct {
Index rt_index ;
int levelsup ;
} check_if_rte_used_context ;
/* ----------
* Global data
@ -95,6 +100,7 @@ static char *get_select_query_def(Query *query, QryHier *qh);
static char * get_insert_query_def ( Query * query , QryHier * qh ) ;
static char * get_update_query_def ( Query * query , QryHier * qh ) ;
static char * get_delete_query_def ( Query * query , QryHier * qh ) ;
static RangeTblEntry * get_rte_for_var ( Var * var , QryHier * qh ) ;
static char * get_rule_expr ( QryHier * qh , int rt_index , Node * node , bool varprefix ) ;
static char * get_func_expr ( QryHier * qh , int rt_index , Expr * expr , bool varprefix ) ;
static char * get_tle_expr ( QryHier * qh , int rt_index , TargetEntry * tle , bool varprefix ) ;
@ -102,7 +108,9 @@ static char *get_const_expr(Const *constval);
static char * get_sublink_expr ( QryHier * qh , int rt_index , Node * node , bool varprefix ) ;
static char * get_relation_name ( Oid relid ) ;
static char * get_attribute_name ( Oid relid , int2 attnum ) ;
static bool check_if_rte_used ( int rt_index , Node * node , int sup ) ;
static bool check_if_rte_used ( Node * node , Index rt_index , int levelsup ) ;
static bool check_if_rte_used_walker ( Node * node ,
check_if_rte_used_context * context ) ;
/* ----------
@ -853,7 +861,7 @@ get_select_query_def(Query *query, QryHier *qh)
List * l ;
/* ----------
* First we need need to know which and how many of the
* First we need to know which and how many of the
* range table entries in the query are used in the target list
* or queries qualification
* - - - - - - - - - -
@ -862,21 +870,15 @@ get_select_query_def(Query *query, QryHier *qh)
rt_used = palloc ( sizeof ( bool ) * rt_length ) ;
for ( i = 0 ; i < rt_length ; i + + )
{
if ( check_if_rte_used ( i + 1 , ( Node * ) ( query - > targetList ) , 0 ) )
if ( check_if_rte_used ( ( Node * ) ( query - > targetList ) , i + 1 , 0 ) | |
check_if_rte_used ( query - > qual , i + 1 , 0 ) | |
check_if_rte_used ( query - > havingQual , i + 1 , 0 ) )
{
rt_used [ i ] = TRUE ;
rt_numused + + ;
}
else
{
if ( check_if_rte_used ( i + 1 , ( Node * ) ( query - > qual ) , 0 ) )
{
rt_used [ i ] = TRUE ;
rt_numused + + ;
}
else
rt_used [ i ] = FALSE ;
}
rt_used [ i ] = FALSE ;
}
/* ----------
@ -920,14 +922,14 @@ get_select_query_def(Query *query, QryHier *qh)
strcat ( buf , get_tle_expr ( qh , 0 , tle , ( rt_numused > 1 ) ) ) ;
/* Check if we must say AS ... */
if ( nodeTag ( tle - > expr ) ! = T_Var )
if ( ! IsA ( tle - > expr , Var ) )
tell_as = strcmp ( tle - > resdom - > resname , " ?column? " ) ;
else
{
Var * var = ( Var * ) ( tle - > expr ) ;
char * attname ;
rte = ( RangeTblEntry * ) nth ( var - > varno - 1 , query - > rtable ) ;
rte = get_rte_for_var ( var , qh ) ;
attname = get_attribute_name ( rte - > relid , var - > varattno ) ;
if ( strcmp ( attname , tle - > resdom - > resname ) )
tell_as = TRUE ;
@ -990,9 +992,14 @@ get_select_query_def(Query *query, QryHier *qh)
sep = " " ;
foreach ( l , query - > groupClause )
{
GroupClause * grp = ( GroupClause * ) lfirst ( l ) ;
Node * groupexpr ;
groupexpr = get_sortgroupclause_expr ( grp ,
query - > targetList ) ;
strcat ( buf , sep ) ;
strcat ( buf , get_rule_expr ( qh , 0 , groupexpr , ( rt_numused > 1 ) ) ) ;
sep = " , " ;
strcat ( buf , get_rule_expr ( qh , 0 , lfirst ( l ) , ( rt_numused > 1 ) ) ) ;
}
}
@ -1032,21 +1039,15 @@ get_insert_query_def(Query *query, QryHier *qh)
rt_used = palloc ( sizeof ( bool ) * rt_length ) ;
for ( i = 0 ; i < rt_length ; i + + )
{
if ( check_if_rte_used ( i + 1 , ( Node * ) ( query - > targetList ) , 0 ) )
if ( check_if_rte_used ( ( Node * ) ( query - > targetList ) , i + 1 , 0 ) | |
check_if_rte_used ( query - > qual , i + 1 , 0 ) | |
check_if_rte_used ( query - > havingQual , i + 1 , 0 ) )
{
rt_used [ i ] = TRUE ;
rt_numused + + ;
}
else
{
if ( check_if_rte_used ( i + 1 , ( Node * ) ( query - > qual ) , 0 ) )
{
rt_used [ i ] = TRUE ;
rt_numused + + ;
}
else
rt_used [ i ] = FALSE ;
}
rt_used [ i ] = FALSE ;
}
i = 0 ;
@ -1200,6 +1201,20 @@ get_delete_query_def(Query *query, QryHier *qh)
return pstrdup ( buf ) ;
}
/*
* Find the RTE referenced by a ( possibly nonlocal ) Var .
*/
static RangeTblEntry *
get_rte_for_var ( Var * var , QryHier * qh )
{
int sup = var - > varlevelsup ;
while ( sup - - > 0 )
qh = qh - > parent ;
return ( RangeTblEntry * ) nth ( var - > varno - 1 , qh - > query - > rtable ) ;
}
/* ----------
* get_rule_expr - Parse back an expression
@ -1216,44 +1231,39 @@ get_rule_expr(QryHier *qh, int rt_index, Node *node, bool varprefix)
buf [ 0 ] = ' \0 ' ;
/* ----------
* Up to now I don ' t know if all the node types below
* can really occur in rules actions and qualifications .
* There might be some work left .
* Each level of get_rule_expr must return an indivisible term
* ( parenthesized if necessary ) to ensure result is reparsed into
* the same expression tree .
*
* There might be some work left here to support additional node types . . .
* - - - - - - - - - -
*/
switch ( nodeTag ( node ) )
{
case T_TargetEntry :
{
TargetEntry * tle = ( TargetEntry * ) node ;
return get_rule_expr ( qh , rt_index ,
( Node * ) ( tle - > expr ) , varprefix ) ;
}
case T_Const :
return get_const_expr ( ( Const * ) node ) ;
break ;
case T_Aggref :
case T_Var :
{
Aggref * aggref = ( Aggref * ) node ;
Var * var = ( Var * ) node ;
RangeTblEntry * rte = get_rte_for_var ( var , qh ) ;
if ( ! strcmp ( rte - > refname , " *NEW* " ) )
strcat ( buf , " new. " ) ;
else if ( ! strcmp ( rte - > refname , " *CURRENT* " ) )
strcat ( buf , " old. " ) ;
else
{
strcat ( buf , " \" " ) ;
strcat ( buf , rte - > refname ) ;
strcat ( buf , " \" . " ) ;
}
strcat ( buf , " \" " ) ;
strcat ( buf , get_attribute_name ( rte - > relid , var - > varattno ) ) ;
strcat ( buf , " \" " ) ;
strcat ( buf , aggref - > aggname ) ;
strcat ( buf , " \" ( " ) ;
strcat ( buf , get_rule_expr ( qh , rt_index ,
( Node * ) ( aggref - > target ) , varprefix ) ) ;
strcat ( buf , " ) " ) ;
return pstrdup ( buf ) ;
}
break ;
case T_GroupClause :
{
GroupClause * grp = ( GroupClause * ) node ;
Node * groupexpr ;
groupexpr = get_sortgroupclause_expr ( grp ,
qh - > query - > targetList ) ;
return get_rule_expr ( qh , rt_index , groupexpr , varprefix ) ;
return pstrdup ( buf ) ;
}
break ;
@ -1268,6 +1278,7 @@ get_rule_expr(QryHier *qh, int rt_index, Node *node, bool varprefix)
switch ( expr - > opType )
{
case OP_EXPR :
strcat ( buf , " ( " ) ;
strcat ( buf , get_rule_expr ( qh , rt_index ,
( Node * ) get_leftop ( expr ) ,
varprefix ) ) ;
@ -1277,6 +1288,7 @@ get_rule_expr(QryHier *qh, int rt_index, Node *node, bool varprefix)
strcat ( buf , get_rule_expr ( qh , rt_index ,
( Node * ) get_rightop ( expr ) ,
varprefix ) ) ;
strcat ( buf , " ) " ) ;
return pstrdup ( buf ) ;
break ;
@ -1285,7 +1297,7 @@ get_rule_expr(QryHier *qh, int rt_index, Node *node, bool varprefix)
strcat ( buf , get_rule_expr ( qh , rt_index ,
( Node * ) get_leftop ( expr ) ,
varprefix ) ) ;
strcat ( buf , " ) OR ( " ) ;
strcat ( buf , " OR " ) ;
strcat ( buf , get_rule_expr ( qh , rt_index ,
( Node * ) get_rightop ( expr ) ,
varprefix ) ) ;
@ -1298,7 +1310,7 @@ get_rule_expr(QryHier *qh, int rt_index, Node *node, bool varprefix)
strcat ( buf , get_rule_expr ( qh , rt_index ,
( Node * ) get_leftop ( expr ) ,
varprefix ) ) ;
strcat ( buf , " ) AND ( " ) ;
strcat ( buf , " AND " ) ;
strcat ( buf , get_rule_expr ( qh , rt_index ,
( Node * ) get_rightop ( expr ) ,
varprefix ) ) ;
@ -1307,7 +1319,7 @@ get_rule_expr(QryHier *qh, int rt_index, Node *node, bool varprefix)
break ;
case NOT_EXPR :
strcat ( buf , " NOT ( " ) ;
strcat ( buf , " ( NOT " ) ;
strcat ( buf , get_rule_expr ( qh , rt_index ,
( Node * ) get_leftop ( expr ) ,
varprefix ) ) ;
@ -1323,50 +1335,77 @@ get_rule_expr(QryHier *qh, int rt_index, Node *node, bool varprefix)
default :
printf ( " \n %s \n " , nodeToString ( node ) ) ;
elog ( ERROR , " Expr no t yet supported " ) ;
elog ( ERROR , " Expr typ e no t supported " ) ;
}
}
break ;
case T_Var :
case T_Aggref :
{
Var * var = ( Var * ) node ;
RangeTblEntry * rte ;
int sup = var - > varlevelsup ;
Aggref * aggref = ( Aggref * ) node ;
while ( sup - - > 0 )
qh = qh - > parent ;
strcat ( buf , " \" " ) ;
strcat ( buf , aggref - > aggname ) ;
strcat ( buf , " \" ( " ) ;
strcat ( buf , get_rule_expr ( qh , rt_index ,
( Node * ) ( aggref - > target ) , varprefix ) ) ;
strcat ( buf , " ) " ) ;
return pstrdup ( buf ) ;
}
break ;
rte = ( RangeTblEntry * ) nth ( var - > varno - 1 , qh - > query - > rtable ) ;
case T_ArrayRef :
{
ArrayRef * aref = ( ArrayRef * ) node ;
List * lowlist ;
List * uplist ;
if ( ! strcmp ( rte - > refname , " *NEW* " ) )
strcat ( buf , " new. " ) ;
else
strcat ( buf , get_rule_expr ( qh , rt_index ,
aref - > refexpr , varprefix ) ) ;
lowlist = aref - > reflowerindexpr ;
foreach ( uplist , aref - > refupperindexpr )
{
if ( ! strcmp ( rte - > refname , " *CURRENT* " ) )
strcat ( buf , " old. " ) ;
else
strcat ( buf , " [ " ) ;
if ( lowlist )
{
if ( strcmp ( rte - > relname , rte - > refname ) ! = 0 )
{
strcat ( buf , " \" " ) ;
strcat ( buf , rte - > refname ) ;
strcat ( buf , " \" . " ) ;
}
strcat ( buf , get_rule_expr ( qh , rt_index ,
( Node * ) lfirst ( lowlist ) ,
varprefix ) ) ;
strcat ( buf , " : " ) ;
lowlist = lnext ( lowlist ) ;
}
strcat ( buf , get_rule_expr ( qh , rt_index ,
( Node * ) lfirst ( uplist ) ,
varprefix ) ) ;
strcat ( buf , " ] " ) ;
}
strcat ( buf , " \" " ) ;
strcat ( buf , get_attribute_name ( rte - > relid , var - > varattno ) ) ;
strcat ( buf , " \" " ) ;
/* XXX need to do anything with refassgnexpr? */
return pstrdup ( buf ) ;
}
break ;
case T_List :
case T_CaseExpr :
{
printf ( " \n %s \n " , nodeToString ( node ) ) ;
elog ( ERROR , " List not yet supported " ) ;
CaseExpr * caseexpr = ( CaseExpr * ) node ;
List * temp ;
strcat ( buf , " CASE " ) ;
foreach ( temp , caseexpr - > args )
{
CaseWhen * when = ( CaseWhen * ) lfirst ( temp ) ;
strcat ( buf , " WHEN " ) ;
strcat ( buf , get_rule_expr ( qh , rt_index ,
when - > expr , varprefix ) ) ;
strcat ( buf , " THEN " ) ;
strcat ( buf , get_rule_expr ( qh , rt_index ,
when - > result , varprefix ) ) ;
}
strcat ( buf , " ELSE " ) ;
strcat ( buf , get_rule_expr ( qh , rt_index ,
caseexpr - > defresult , varprefix ) ) ;
strcat ( buf , " END " ) ;
return pstrdup ( buf ) ;
}
break ;
@ -1374,13 +1413,9 @@ get_rule_expr(QryHier *qh, int rt_index, Node *node, bool varprefix)
return get_sublink_expr ( qh , rt_index , node , varprefix ) ;
break ;
case T_Const :
return get_const_expr ( ( Const * ) node ) ;
break ;
default :
printf ( " \n %s \n " , nodeToString ( node ) ) ;
elog ( ERROR , " get_ruledef of %s: unknown node type %d get_rule_expr() " ,
elog ( ERROR , " get_ruledef of %s: unknown node type %d in get_rule_expr() " ,
rulename , nodeTag ( node ) ) ;
break ;
}
@ -1423,7 +1458,7 @@ get_func_expr(QryHier *qh, int rt_index, Expr *expr, bool varprefix)
strcpy ( buf , " ( " ) ;
strcat ( buf , get_rule_expr ( qh , rt_index , lfirst ( expr - > args ) ,
varprefix ) ) ;
strcat ( buf , " ) ISNULL" ) ;
strcat ( buf , " ISNULL) " ) ;
return pstrdup ( buf ) ;
}
if ( ! strcmp ( proname , " nonnullvalue " ) )
@ -1431,7 +1466,7 @@ get_func_expr(QryHier *qh, int rt_index, Expr *expr, bool varprefix)
strcpy ( buf , " ( " ) ;
strcat ( buf , get_rule_expr ( qh , rt_index , lfirst ( expr - > args ) ,
varprefix ) ) ;
strcat ( buf , " ) NOTNULL" ) ;
strcat ( buf , " NOTNULL) " ) ;
return pstrdup ( buf ) ;
}
}
@ -1475,10 +1510,11 @@ get_func_expr(QryHier *qh, int rt_index, Expr *expr, bool varprefix)
static char *
get_tle_expr ( QryHier * qh , int rt_index , TargetEntry * tle , bool varprefix )
{
HeapTuple proctup ;
Form_pg_proc procStruct ;
Expr * expr ;
Expr * expr = ( Expr * ) ( tle - > expr ) ;
Func * func ;
HeapTuple tup ;
Form_pg_proc procStruct ;
Form_pg_type typeStruct ;
Const * second_arg ;
/* ----------
@ -1486,12 +1522,9 @@ get_tle_expr(QryHier *qh, int rt_index, TargetEntry *tle, bool varprefix)
* expression in the targetlist entry is a function call
* - - - - - - - - - -
*/
if ( tle - > resdom - > restypmod < 0 )
return get_rule_expr ( qh , rt_index , tle - > expr , varprefix ) ;
if ( nodeTag ( tle - > expr ) ! = T_Expr )
return get_rule_expr ( qh , rt_index , tle - > expr , varprefix ) ;
expr = ( Expr * ) ( tle - > expr ) ;
if ( expr - > opType ! = FUNC_EXPR )
if ( tle - > resdom - > restypmod < 0 | |
! IsA ( expr , Expr ) | |
expr - > opType ! = FUNC_EXPR )
return get_rule_expr ( qh , rt_index , tle - > expr , varprefix ) ;
func = ( Func * ) ( expr - > oper ) ;
@ -1500,12 +1533,11 @@ get_tle_expr(QryHier *qh, int rt_index, TargetEntry *tle, bool varprefix)
* Get the functions pg_proc tuple
* - - - - - - - - - -
*/
proc tup = SearchSysCacheTuple ( PROOID ,
ObjectIdGetDatum ( func - > funcid ) , 0 , 0 , 0 ) ;
if ( ! HeapTupleIsValid ( proc tup) )
tup = SearchSysCacheTuple ( PROOID ,
ObjectIdGetDatum ( func - > funcid ) , 0 , 0 , 0 ) ;
if ( ! HeapTupleIsValid ( tup ) )
elog ( ERROR , " cache lookup for proc %u failed " , func - > funcid ) ;
procStruct = ( Form_pg_proc ) GETSTRUCT ( proctup ) ;
procStruct = ( Form_pg_proc ) GETSTRUCT ( tup ) ;
/* ----------
* It must be a function with two arguments where the first
@ -1513,22 +1545,34 @@ get_tle_expr(QryHier *qh, int rt_index, TargetEntry *tle, bool varprefix)
* an int4 .
* - - - - - - - - - -
*/
if ( procStruct - > pronargs ! = 2 )
return get_rule_expr ( qh , rt_index , tle - > expr , varprefix ) ;
if ( procStruct - > prorettype ! = procStruct - > proargtypes [ 0 ] )
return get_rule_expr ( qh , rt_index , tle - > expr , varprefix ) ;
if ( procStruct - > proargtypes [ 1 ] ! = INT4OID )
if ( procStruct - > pronargs ! = 2 | |
procStruct - > prorettype ! = procStruct - > proargtypes [ 0 ] | |
procStruct - > proargtypes [ 1 ] ! = INT4OID )
return get_rule_expr ( qh , rt_index , tle - > expr , varprefix ) ;
/*
* Furthermore , the name of the function must be the same
* as the argument / result type name .
*/
tup = SearchSysCacheTuple ( TYPOID ,
ObjectIdGetDatum ( procStruct - > prorettype ) ,
0 , 0 , 0 ) ;
if ( ! HeapTupleIsValid ( tup ) )
elog ( ERROR , " cache lookup for type %u failed " ,
procStruct - > prorettype ) ;
typeStruct = ( Form_pg_type ) GETSTRUCT ( tup ) ;
if ( strncmp ( procStruct - > proname . data , typeStruct - > typname . data ,
NAMEDATALEN ) ! = 0 )
return get_rule_expr ( qh , rt_index , tle - > expr , varprefix ) ;
/* ----------
* Finally ( to be totally safe ) the second argument must be a
* const and match the value in the results atttypmod .
* - - - - - - - - - -
*/
second_arg = ( Const * ) nth ( 1 , expr - > args ) ;
if ( nodeTag ( ( Node * ) second_arg ) ! = T_Const )
return get_rule_expr ( qh , rt_index , tle - > expr , varprefix ) ;
if ( ( int4 ) ( second_arg - > constvalue ) ! = tle - > resdom - > restypmod )
if ( ! IsA ( second_arg , Const ) | |
( ( int4 ) second_arg - > constvalue ) ! = tle - > resdom - > restypmod )
return get_rule_expr ( qh , rt_index , tle - > expr , varprefix ) ;
/* ----------
@ -1556,12 +1600,12 @@ get_const_expr(Const *constval)
char namebuf [ 64 ] ;
if ( constval - > constisnull )
return " NULL " ;
return pstrdup ( " NULL " ) ;
typetup = SearchSysCacheTuple ( TYPOID ,
ObjectIdGetDatum ( constval - > consttype ) , 0 , 0 , 0 ) ;
if ( ! HeapTupleIsValid ( typetup ) )
elog ( ERROR , " cache lookup of type %d failed " , constval - > consttype ) ;
elog ( ERROR , " cache lookup of type %u failed " , constval - > consttype ) ;
typeStruct = ( Form_pg_type ) GETSTRUCT ( typetup ) ;
@ -1593,6 +1637,8 @@ get_sublink_expr(QryHier *qh, int rt_index, Node *node, bool varprefix)
buf [ 0 ] = ' \0 ' ;
strcat ( buf , " ( " ) ;
if ( sublink - > lefthand ! = NULL )
{
if ( length ( sublink - > lefthand ) > 1 )
@ -1645,7 +1691,7 @@ get_sublink_expr(QryHier *qh, int rt_index, Node *node, bool varprefix)
strcat ( buf , " ( " ) ;
strcat ( buf , get_query_def ( query , qh ) ) ;
strcat ( buf , " ) " ) ;
strcat ( buf , " )) " ) ;
return pstrdup ( buf ) ;
}
@ -1694,96 +1740,49 @@ get_attribute_name(Oid relid, int2 attnum)
/* ----------
* check_if_rte_used - Check a targetlist or qual
* if a given rangetable entry
* is used in it
* check_if_rte_used
* Check a targetlist or qual to see if a given rangetable entry
* is used in it
* - - - - - - - - - -
*/
static bool
check_if_rte_used ( int rt_index , Node * node , int sup )
check_if_rte_used ( Node * node , Index rt_index , int level sup)
{
if ( node = = NULL )
return FALSE ;
switch ( nodeTag ( node ) )
{
case T_TargetEntry :
{
TargetEntry * tle = ( TargetEntry * ) node ;
return check_if_rte_used ( rt_index ,
( Node * ) ( tle - > expr ) , sup ) ;
}
break ;
case T_Aggref :
{
Aggref * aggref = ( Aggref * ) node ;
return check_if_rte_used ( rt_index ,
( Node * ) ( aggref - > target ) , sup ) ;
}
break ;
check_if_rte_used_context context ;
case T_GroupClause :
return FALSE ;
break ;
case T_Expr :
{
Expr * expr = ( Expr * ) node ;
return check_if_rte_used ( rt_index ,
( Node * ) ( expr - > args ) , sup ) ;
}
break ;
case T_Var :
{
Var * var = ( Var * ) node ;
return var - > varno = = rt_index & & var - > varlevelsup = = sup ;
}
break ;
case T_List :
{
List * l ;
foreach ( l , ( List * ) node )
{
if ( check_if_rte_used ( rt_index , lfirst ( l ) , sup ) )
return TRUE ;
}
return FALSE ;
}
break ;
case T_SubLink :
{
SubLink * sublink = ( SubLink * ) node ;
Query * query = ( Query * ) sublink - > subselect ;
if ( check_if_rte_used ( rt_index , ( Node * ) ( query - > qual ) , sup + 1 ) )
return TRUE ;
/* why aren't we looking at query->targetlist, havingQual? */
if ( check_if_rte_used ( rt_index , ( Node * ) ( sublink - > lefthand ) , sup ) )
return TRUE ;
return FALSE ;
}
break ;
context . rt_index = rt_index ;
context . levelsup = levelsup ;
return check_if_rte_used_walker ( node , & context ) ;
}
case T_Const :
return FALSE ;
break ;
static bool
check_if_rte_used_walker ( Node * node ,
check_if_rte_used_context * context )
{
if ( node = = NULL )
return false ;
if ( IsA ( node , Var ) )
{
Var * var = ( Var * ) node ;
default :
elog ( ERROR , " get_ruledef of %s: unknown node type %d in check_if_rte_used() " ,
rulename , nodeTag ( node ) ) ;
break ;
return var - > varno = = context - > rt_index & &
var - > varlevelsup = = context - > levelsup ;
}
return FALSE ;
if ( IsA ( node , SubLink ) )
{
SubLink * sublink = ( SubLink * ) node ;
Query * query = ( Query * ) sublink - > subselect ;
/* Recurse into subquery; expression_tree_walker will not */
if ( check_if_rte_used ( ( Node * ) ( query - > targetList ) ,
context - > rt_index , context - > levelsup + 1 ) | |
check_if_rte_used ( query - > qual ,
context - > rt_index , context - > levelsup + 1 ) | |
check_if_rte_used ( query - > havingQual ,
context - > rt_index , context - > levelsup + 1 ) )
return true ;
/* fall through to let expression_tree_walker examine lefthand args */
}
return expression_tree_walker ( node , check_if_rte_used_walker ,
( void * ) context ) ;
}