diff options
-rw-r--r-- | src/backend/executor/execExpr.c | 23 |
1 files changed, 14 insertions, 9 deletions
diff --git a/src/backend/executor/execExpr.c b/src/backend/executor/execExpr.c index 45954d979f6..8f7a5340059 100644 --- a/src/backend/executor/execExpr.c +++ b/src/backend/executor/execExpr.c @@ -4004,8 +4004,9 @@ ExecBuildHash32Expr(TupleDesc desc, const TupleTableSlotOps *ops, ListCell *lc2; intptr_t strict_opcode; intptr_t opcode; + int num_exprs = list_length(hash_exprs); - Assert(list_length(hash_exprs) == list_length(collations)); + Assert(num_exprs == list_length(collations)); state->parent = parent; @@ -4013,11 +4014,11 @@ ExecBuildHash32Expr(TupleDesc desc, const TupleTableSlotOps *ops, 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. + * Make a place to store intermediate hash values between subsequent + * hashing of individual expressions. We only need this if there is more + * than one expression to hash or an initial value plus one expression. */ - if (list_length(hash_exprs) > 1 || init_value != 0) + if ((int64) num_exprs + (init_value != 0) > 1) iresult = palloc(sizeof(NullableDatum)); if (init_value == 0) @@ -4032,11 +4033,15 @@ ExecBuildHash32Expr(TupleDesc desc, const TupleTableSlotOps *ops, } else { - /* Set up operation to set the initial value. */ + /* + * Set up operation to set the initial value. Normally we store this + * in the intermediate hash value location, but if there are no exprs + * to hash, store it in the ExprState's result field. + */ scratch.opcode = EEOP_HASHDATUM_SET_INITVAL; scratch.d.hashdatum_initvalue.init_value = UInt32GetDatum(init_value); - scratch.resvalue = &iresult->value; - scratch.resnull = &iresult->isnull; + scratch.resvalue = num_exprs > 0 ? &iresult->value : &state->resvalue; + scratch.resnull = num_exprs > 0 ? &iresult->isnull : &state->resnull; ExprEvalPushStep(state, &scratch); @@ -4074,7 +4079,7 @@ ExecBuildHash32Expr(TupleDesc desc, const TupleTableSlotOps *ops, &fcinfo->args[0].value, &fcinfo->args[0].isnull); - if (i == list_length(hash_exprs) - 1) + if (i == num_exprs - 1) { /* the result for hashing the final expr is stored in the state */ scratch.resvalue = &state->resvalue; |