@ -2343,7 +2343,7 @@ ExecBuildAuxRowMark(ExecRowMark *erm, List *targetlist)
* relation - table containing tuple
* relation - table containing tuple
* rti - rangetable index of table containing tuple
* rti - rangetable index of table containing tuple
* inputslot - tuple for processing - this can be the slot from
* inputslot - tuple for processing - this can be the slot from
* EvalPlanQualSlot ( ) , for the increased efficiency .
* EvalPlanQualSlot ( ) for this rel , for increased efficiency .
*
*
* This tests whether the tuple in inputslot still matches the relevant
* This tests whether the tuple in inputslot still matches the relevant
* quals . For that result to be useful , typically the input tuple has to be
* quals . For that result to be useful , typically the input tuple has to be
@ -2377,6 +2377,14 @@ EvalPlanQual(EPQState *epqstate, Relation relation,
if ( testslot ! = inputslot )
if ( testslot ! = inputslot )
ExecCopySlot ( testslot , inputslot ) ;
ExecCopySlot ( testslot , inputslot ) ;
/*
* Mark that an EPQ tuple is available for this relation . ( If there is
* more than one result relation , the others remain marked as having no
* tuple available . )
*/
epqstate - > relsubs_done [ rti - 1 ] = false ;
epqstate - > epqExtra - > relsubs_blocked [ rti - 1 ] = false ;
/*
/*
* Run the EPQ query . We assume it will return at most one tuple .
* Run the EPQ query . We assume it will return at most one tuple .
*/
*/
@ -2393,11 +2401,12 @@ EvalPlanQual(EPQState *epqstate, Relation relation,
ExecMaterializeSlot ( slot ) ;
ExecMaterializeSlot ( slot ) ;
/*
/*
* Clear out the test tuple . This is needed in case the EPQ query is
* Clear out the test tuple , and mark that no tuple is available here .
* re - used to test a tuple for a different relation . ( Not clear that can
* This is needed in case the EPQ state is re - used to test a tuple for a
* really happen , but let ' s be safe . )
* different target relation .
*/
*/
ExecClearTuple ( testslot ) ;
ExecClearTuple ( testslot ) ;
epqstate - > epqExtra - > relsubs_blocked [ rti - 1 ] = true ;
return slot ;
return slot ;
}
}
@ -2412,12 +2421,34 @@ EvalPlanQual(EPQState *epqstate, Relation relation,
void
void
EvalPlanQualInit ( EPQState * epqstate , EState * parentestate ,
EvalPlanQualInit ( EPQState * epqstate , EState * parentestate ,
Plan * subplan , List * auxrowmarks , int epqParam )
Plan * subplan , List * auxrowmarks , int epqParam )
{
EvalPlanQualInitExt ( epqstate , parentestate ,
subplan , auxrowmarks , epqParam , NIL ) ;
}
/*
* EvalPlanQualInitExt - - same , but allow specification of resultRelations
*
* If the caller intends to use EvalPlanQual ( ) , resultRelations should be
* a list of RT indexes of potential target relations for EvalPlanQual ( ) ,
* and we will arrange that the other listed relations don ' t return any
* tuple during an EvalPlanQual ( ) call . Otherwise resultRelations
* should be NIL .
*/
void
EvalPlanQualInitExt ( EPQState * epqstate , EState * parentestate ,
Plan * subplan , List * auxrowmarks ,
int epqParam , List * resultRelations )
{
{
Index rtsize = parentestate - > es_range_table_size ;
Index rtsize = parentestate - > es_range_table_size ;
/* create some extra space to avoid ABI break */
epqstate - > epqExtra = ( EPQStateExtra * ) palloc ( sizeof ( EPQStateExtra ) ) ;
/* initialize data not changing over EPQState's lifetime */
/* initialize data not changing over EPQState's lifetime */
epqstate - > parentestate = parentestate ;
epqstate - > parentestate = parentestate ;
epqstate - > epqParam = epqParam ;
epqstate - > epqParam = epqParam ;
epqstate - > epqExtra - > resultRelations = resultRelations ;
/*
/*
* Allocate space to reference a slot for each potential rti - do so now
* Allocate space to reference a slot for each potential rti - do so now
@ -2426,7 +2457,7 @@ EvalPlanQualInit(EPQState *epqstate, EState *parentestate,
* that * may * need EPQ later , without forcing the overhead of
* that * may * need EPQ later , without forcing the overhead of
* EvalPlanQualBegin ( ) .
* EvalPlanQualBegin ( ) .
*/
*/
epqstate - > tuple_table = NIL ;
epqstate - > epqExtra - > tuple_table = NIL ;
epqstate - > relsubs_slot = ( TupleTableSlot * * )
epqstate - > relsubs_slot = ( TupleTableSlot * * )
palloc0 ( rtsize * sizeof ( TupleTableSlot * ) ) ;
palloc0 ( rtsize * sizeof ( TupleTableSlot * ) ) ;
@ -2440,6 +2471,7 @@ EvalPlanQualInit(EPQState *epqstate, EState *parentestate,
epqstate - > recheckplanstate = NULL ;
epqstate - > recheckplanstate = NULL ;
epqstate - > relsubs_rowmark = NULL ;
epqstate - > relsubs_rowmark = NULL ;
epqstate - > relsubs_done = NULL ;
epqstate - > relsubs_done = NULL ;
epqstate - > epqExtra - > relsubs_blocked = NULL ;
}
}
/*
/*
@ -2480,7 +2512,7 @@ EvalPlanQualSlot(EPQState *epqstate,
MemoryContext oldcontext ;
MemoryContext oldcontext ;
oldcontext = MemoryContextSwitchTo ( epqstate - > parentestate - > es_query_cxt ) ;
oldcontext = MemoryContextSwitchTo ( epqstate - > parentestate - > es_query_cxt ) ;
* slot = table_slot_create ( relation , & epqstate - > tuple_table ) ;
* slot = table_slot_create ( relation , & epqstate - > epqExtra - > tuple_table ) ;
MemoryContextSwitchTo ( oldcontext ) ;
MemoryContextSwitchTo ( oldcontext ) ;
}
}
@ -2637,7 +2669,13 @@ EvalPlanQualBegin(EPQState *epqstate)
Index rtsize = parentestate - > es_range_table_size ;
Index rtsize = parentestate - > es_range_table_size ;
PlanState * rcplanstate = epqstate - > recheckplanstate ;
PlanState * rcplanstate = epqstate - > recheckplanstate ;
MemSet ( epqstate - > relsubs_done , 0 , rtsize * sizeof ( bool ) ) ;
/*
* Reset the relsubs_done [ ] flags to equal relsubs_blocked [ ] , so that
* the EPQ run will never attempt to fetch tuples from blocked target
* relations .
*/
memcpy ( epqstate - > relsubs_done , epqstate - > epqExtra - > relsubs_blocked ,
rtsize * sizeof ( bool ) ) ;
/* Recopy current values of parent parameters */
/* Recopy current values of parent parameters */
if ( parentestate - > es_plannedstmt - > paramExecTypes ! = NIL )
if ( parentestate - > es_plannedstmt - > paramExecTypes ! = NIL )
@ -2804,10 +2842,22 @@ EvalPlanQualStart(EPQState *epqstate, Plan *planTree)
}
}
/*
/*
* Initialize per - relation EPQ tuple states to not - fetched .
* Initialize per - relation EPQ tuple states . Result relations , if any ,
* get marked as blocked ; others as not - fetched .
*/
*/
epqstate - > relsubs_done = ( bool * )
epqstate - > relsubs_done = palloc_array ( bool , rtsize ) ;
palloc0 ( rtsize * sizeof ( bool ) ) ;
epqstate - > epqExtra - > relsubs_blocked = palloc0_array ( bool , rtsize ) ;
foreach ( l , epqstate - > epqExtra - > resultRelations )
{
int rtindex = lfirst_int ( l ) ;
Assert ( rtindex > 0 & & rtindex < = rtsize ) ;
epqstate - > epqExtra - > relsubs_blocked [ rtindex - 1 ] = true ;
}
memcpy ( epqstate - > relsubs_done , epqstate - > epqExtra - > relsubs_blocked ,
rtsize * sizeof ( bool ) ) ;
/*
/*
* Initialize the private state information for all the nodes in the part
* Initialize the private state information for all the nodes in the part
@ -2844,12 +2894,12 @@ EvalPlanQualEnd(EPQState *epqstate)
* We may have a tuple table , even if EPQ wasn ' t started , because we allow
* We may have a tuple table , even if EPQ wasn ' t started , because we allow
* use of EvalPlanQualSlot ( ) without calling EvalPlanQualBegin ( ) .
* use of EvalPlanQualSlot ( ) without calling EvalPlanQualBegin ( ) .
*/
*/
if ( epqstate - > tuple_table ! = NIL )
if ( epqstate - > epqExtra - > tuple_table ! = NIL )
{
{
memset ( epqstate - > relsubs_slot , 0 ,
memset ( epqstate - > relsubs_slot , 0 ,
rtsize * sizeof ( TupleTableSlot * ) ) ;
rtsize * sizeof ( TupleTableSlot * ) ) ;
ExecResetTupleTable ( epqstate - > tuple_table , true ) ;
ExecResetTupleTable ( epqstate - > epqExtra - > tuple_table , true ) ;
epqstate - > tuple_table = NIL ;
epqstate - > epqExtra - > tuple_table = NIL ;
}
}
/* EPQ wasn't started, nothing further to do */
/* EPQ wasn't started, nothing further to do */
@ -2883,4 +2933,5 @@ EvalPlanQualEnd(EPQState *epqstate)
epqstate - > recheckplanstate = NULL ;
epqstate - > recheckplanstate = NULL ;
epqstate - > relsubs_rowmark = NULL ;
epqstate - > relsubs_rowmark = NULL ;
epqstate - > relsubs_done = NULL ;
epqstate - > relsubs_done = NULL ;
epqstate - > epqExtra - > relsubs_blocked = NULL ;
}
}