diff options
Diffstat (limited to 'src/backend/executor/execExpr.c')
-rw-r--r-- | src/backend/executor/execExpr.c | 35 |
1 files changed, 31 insertions, 4 deletions
diff --git a/src/backend/executor/execExpr.c b/src/backend/executor/execExpr.c index c8077aa57bd..a343d0bc6a2 100644 --- a/src/backend/executor/execExpr.c +++ b/src/backend/executor/execExpr.c @@ -3996,6 +3996,7 @@ ExecBuildHash32Expr(TupleDesc desc, const TupleTableSlotOps *ops, { ExprState *state = makeNode(ExprState); ExprEvalStep scratch = {0}; + NullableDatum *iresult = NULL; List *adjust_jumps = NIL; ListCell *lc; ListCell *lc2; @@ -4009,6 +4010,14 @@ ExecBuildHash32Expr(TupleDesc desc, const TupleTableSlotOps *ops, /* Insert setup steps as needed. */ ExecCreateExprSetupSteps(state, (Node *) hash_exprs); + /* + * When hashing more than 1 expression or if we have an init value, we + * need somewhere to store the intermediate hash value so that it's + * available to be combined with the result of subsequent hashing. + */ + if (list_length(hash_exprs) > 1 || init_value != 0) + iresult = palloc(sizeof(NullableDatum)); + if (init_value == 0) { /* @@ -4024,8 +4033,8 @@ ExecBuildHash32Expr(TupleDesc desc, const TupleTableSlotOps *ops, /* Set up operation to set the initial value. */ scratch.opcode = EEOP_HASHDATUM_SET_INITVAL; scratch.d.hashdatum_initvalue.init_value = UInt32GetDatum(init_value); - scratch.resvalue = &state->resvalue; - scratch.resnull = &state->resnull; + scratch.resvalue = &iresult->value; + scratch.resnull = &iresult->isnull; ExprEvalPushStep(state, &scratch); @@ -4063,8 +4072,26 @@ ExecBuildHash32Expr(TupleDesc desc, const TupleTableSlotOps *ops, &fcinfo->args[0].value, &fcinfo->args[0].isnull); - scratch.resvalue = &state->resvalue; - scratch.resnull = &state->resnull; + if (i == list_length(hash_exprs) - 1) + { + /* the result for hashing the final expr is stored in the state */ + scratch.resvalue = &state->resvalue; + scratch.resnull = &state->resnull; + } + else + { + Assert(iresult != NULL); + + /* intermediate values are stored in an intermediate result */ + scratch.resvalue = &iresult->value; + scratch.resnull = &iresult->isnull; + } + + /* + * NEXT32 opcodes need to look at the intermediate result. We might + * as well just set this for all ops. FIRSTs won't look at it. + */ + scratch.d.hashdatum.iresult = iresult; /* Initialize function call parameter structure too */ InitFunctionCallInfoData(*fcinfo, finfo, 1, inputcollid, NULL, NULL); |