@ -79,7 +79,8 @@ static void ExecInitCoerceToDomain(ExprEvalStep *scratch, CoerceToDomain *ctest,
static void ExecBuildAggTransCall ( ExprState * state , AggState * aggstate ,
ExprEvalStep * scratch ,
FunctionCallInfo fcinfo , AggStatePerTrans pertrans ,
int transno , int setno , int setoff , bool ishash ) ;
int transno , int setno , int setoff , bool ishash ,
bool nullcheck ) ;
/*
@ -2924,10 +2925,13 @@ ExecInitCoerceToDomain(ExprEvalStep *scratch, CoerceToDomain *ctest,
* check for filters , evaluate aggregate input , check that that input is not
* NULL for a strict transition function , and then finally invoke the
* transition for each of the concurrently computed grouping sets .
*
* If nullcheck is true , the generated code will check for a NULL pointer to
* the array of AggStatePerGroup , and skip evaluation if so .
*/
ExprState *
ExecBuildAggTrans ( AggState * aggstate , AggStatePerPhase phase ,
bool doSort , bool doHash )
bool doSort , bool doHash , bool nullcheck )
{
ExprState * state = makeNode ( ExprState ) ;
PlanState * parent = & aggstate - > ss . ps ;
@ -3158,7 +3162,8 @@ ExecBuildAggTrans(AggState *aggstate, AggStatePerPhase phase,
for ( int setno = 0 ; setno < processGroupingSets ; setno + + )
{
ExecBuildAggTransCall ( state , aggstate , & scratch , trans_fcinfo ,
pertrans , transno , setno , setoff , false ) ;
pertrans , transno , setno , setoff , false ,
nullcheck ) ;
setoff + + ;
}
}
@ -3177,7 +3182,8 @@ ExecBuildAggTrans(AggState *aggstate, AggStatePerPhase phase,
for ( int setno = 0 ; setno < numHashes ; setno + + )
{
ExecBuildAggTransCall ( state , aggstate , & scratch , trans_fcinfo ,
pertrans , transno , setno , setoff , true ) ;
pertrans , transno , setno , setoff , true ,
nullcheck ) ;
setoff + + ;
}
}
@ -3227,15 +3233,28 @@ static void
ExecBuildAggTransCall ( ExprState * state , AggState * aggstate ,
ExprEvalStep * scratch ,
FunctionCallInfo fcinfo , AggStatePerTrans pertrans ,
int transno , int setno , int setoff , bool ishash )
int transno , int setno , int setoff , bool ishash ,
bool nullcheck )
{
ExprContext * aggcontext ;
int adjust_jumpnull = - 1 ;
if ( ishash )
aggcontext = aggstate - > hashcontext ;
else
aggcontext = aggstate - > aggcontexts [ setno ] ;
/* add check for NULL pointer? */
if ( nullcheck )
{
scratch - > opcode = EEOP_AGG_PLAIN_PERGROUP_NULLCHECK ;
scratch - > d . agg_plain_pergroup_nullcheck . setoff = setoff ;
/* adjust later */
scratch - > d . agg_plain_pergroup_nullcheck . jumpnull = - 1 ;
ExprEvalPushStep ( state , scratch ) ;
adjust_jumpnull = state - > steps_len - 1 ;
}
/*
* Determine appropriate transition implementation .
*
@ -3303,6 +3322,16 @@ ExecBuildAggTransCall(ExprState *state, AggState *aggstate,
scratch - > d . agg_trans . transno = transno ;
scratch - > d . agg_trans . aggcontext = aggcontext ;
ExprEvalPushStep ( state , scratch ) ;
/* fix up jumpnull */
if ( adjust_jumpnull ! = - 1 )
{
ExprEvalStep * as = & state - > steps [ adjust_jumpnull ] ;
Assert ( as - > opcode = = EEOP_AGG_PLAIN_PERGROUP_NULLCHECK ) ;
Assert ( as - > d . agg_plain_pergroup_nullcheck . jumpnull = = - 1 ) ;
as - > d . agg_plain_pergroup_nullcheck . jumpnull = state - > steps_len ;
}
}
/*