diff --git a/src/backend/executor/nodeSubplan.c b/src/backend/executor/nodeSubplan.c index f6445e286a..1991b90a55 100644 --- a/src/backend/executor/nodeSubplan.c +++ b/src/backend/executor/nodeSubplan.c @@ -860,6 +860,7 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent) i; TupleDesc tupDescLeft; TupleDesc tupDescRight; + Oid *cross_eq_funcoids; TupleTableSlot *slot; List *oplist, *lefttlist, @@ -923,6 +924,9 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent) sstate->tab_collations = (Oid *) palloc(ncols * sizeof(Oid)); sstate->lhs_hash_funcs = (FmgrInfo *) palloc(ncols * sizeof(FmgrInfo)); sstate->cur_eq_funcs = (FmgrInfo *) palloc(ncols * sizeof(FmgrInfo)); + /* we'll need the cross-type equality fns below, but not in sstate */ + cross_eq_funcoids = (Oid *) palloc(ncols * sizeof(Oid)); + i = 1; foreach(l, oplist) { @@ -952,7 +956,7 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent) righttlist = lappend(righttlist, tle); /* Lookup the equality function (potentially cross-type) */ - sstate->tab_eq_funcoids[i - 1] = opexpr->opfuncid; + cross_eq_funcoids[i - 1] = opexpr->opfuncid; fmgr_info(opexpr->opfuncid, &sstate->cur_eq_funcs[i - 1]); fmgr_info_set_expr((Node *) opexpr, &sstate->cur_eq_funcs[i - 1]); @@ -961,7 +965,9 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent) NULL, &rhs_eq_oper)) elog(ERROR, "could not find compatible hash operator for operator %u", opexpr->opno); - fmgr_info(get_opcode(rhs_eq_oper), &sstate->tab_eq_funcs[i - 1]); + sstate->tab_eq_funcoids[i - 1] = get_opcode(rhs_eq_oper); + fmgr_info(sstate->tab_eq_funcoids[i - 1], + &sstate->tab_eq_funcs[i - 1]); /* Lookup the associated hash functions */ if (!get_op_hash_functions(opexpr->opno, @@ -1003,16 +1009,15 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent) /* * Create comparator for lookups of rows in the table (potentially - * across-type comparison). + * cross-type comparisons). */ sstate->cur_eq_comp = ExecBuildGroupingEqual(tupDescLeft, tupDescRight, &TTSOpsVirtual, &TTSOpsMinimalTuple, ncols, sstate->keyColIdx, - sstate->tab_eq_funcoids, + cross_eq_funcoids, sstate->tab_collations, parent); - } return sstate; diff --git a/src/test/regress/expected/subselect.out b/src/test/regress/expected/subselect.out index 2d1963d12a..ee9c5db0d5 100644 --- a/src/test/regress/expected/subselect.out +++ b/src/test/regress/expected/subselect.out @@ -764,6 +764,30 @@ select * from outer_text where (f1, f2) not in (select * from inner_text); b | (2 rows) +-- +-- Another test case for cross-type hashed subplans: comparison of +-- inner-side values must be done with appropriate operator +-- +explain (verbose, costs off) +select 'foo'::text in (select 'bar'::name union all select 'bar'::name); + QUERY PLAN +------------------------------------- + Result + Output: (hashed SubPlan 1) + SubPlan 1 + -> Append + -> Result + Output: 'bar'::name + -> Result + Output: 'bar'::name +(8 rows) + +select 'foo'::text in (select 'bar'::name union all select 'bar'::name); + ?column? +---------- + f +(1 row) + -- -- Test case for premature memory release during hashing of subplan output -- diff --git a/src/test/regress/sql/subselect.sql b/src/test/regress/sql/subselect.sql index 99ca69791e..20c4f99c9c 100644 --- a/src/test/regress/sql/subselect.sql +++ b/src/test/regress/sql/subselect.sql @@ -452,6 +452,16 @@ insert into inner_text values ('a', null); select * from outer_text where (f1, f2) not in (select * from inner_text); +-- +-- Another test case for cross-type hashed subplans: comparison of +-- inner-side values must be done with appropriate operator +-- + +explain (verbose, costs off) +select 'foo'::text in (select 'bar'::name union all select 'bar'::name); + +select 'foo'::text in (select 'bar'::name union all select 'bar'::name); + -- -- Test case for premature memory release during hashing of subplan output --