Re: BUG #15577: Query returns different results when executed multiple times - Mailing list pgsql-bugs
| From | Tom Lane |
|---|---|
| Subject | Re: BUG #15577: Query returns different results when executed multiple times |
| Date | |
| Msg-id | 2887.1547141893@sss.pgh.pa.us Whole thread Raw |
| In response to | Re: BUG #15577: Query returns different results when executed multiple times (Tom Lane <tgl@sss.pgh.pa.us>) |
| Responses |
Re: BUG #15577: Query returns different results when executedmultiple times
|
| List | pgsql-bugs |
I wrote:
> Well, if we posit that the problems are limited to false Param-sharing,
> my inclination is to fix it by simplifying rather than adding complexity.
> To wit, let's just assign a new PARAM_EXEC slot for every NestLoopParam
> and never try to share them. The argument that sharing them would work
> for NLPs representing the same Var hinged on the assumption that nested
> NestLoops would necessarily execute "in sync", which we now see is false
> at least when Gathers are in between.
Here's a POC patch for that. It's seriously ugly, but it passes
check-world and I can no longer reproduce the problem using
mockup_bug15577_v2.sql.
At this point assign_nestloop_param_var and
assign_nestloop_param_placeholdervar are dead code, and there's a bunch
of incorrect comments in subselect.c, and I really need to refactor
the division of labor between createplan.c and subselect.c (for one
thing, this is an abuse of the documented purpose of
SS_make_initplan_output_param). But functionally I think it does the
right thing. Please test and verify that you no longer see the race
condition.
regards, tom lane
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index 066685c..6ce5938 100644
*** a/src/backend/optimizer/plan/createplan.c
--- b/src/backend/optimizer/plan/createplan.c
*************** replace_nestloop_params_mutator(Node *no
*** 4360,4379 ****
/* If not to be replaced, we can just return the Var unmodified */
if (!bms_is_member(var->varno, root->curOuterRels))
return node;
! /* Create a Param representing the Var */
! param = assign_nestloop_param_var(root, var);
! /* Is this param already listed in root->curOuterParams? */
foreach(lc, root->curOuterParams)
{
nlp = (NestLoopParam *) lfirst(lc);
! if (nlp->paramno == param->paramid)
{
! Assert(equal(var, nlp->paramval));
! /* Present, so we can just return the Param */
return (Node *) param;
}
}
! /* No, so add it */
nlp = makeNode(NestLoopParam);
nlp->paramno = param->paramid;
nlp->paramval = var;
--- 4360,4389 ----
/* If not to be replaced, we can just return the Var unmodified */
if (!bms_is_member(var->varno, root->curOuterRels))
return node;
! /* Is this Var already listed in root->curOuterParams? */
foreach(lc, root->curOuterParams)
{
nlp = (NestLoopParam *) lfirst(lc);
! if (equal(var, nlp->paramval))
{
! /* Yes, so just make a Param referencing this NLP's slot */
! param = makeNode(Param);
! param->paramkind = PARAM_EXEC;
! param->paramid = nlp->paramno;
! param->paramtype = var->vartype;
! param->paramtypmod = var->vartypmod;
! param->paramcollid = var->varcollid;
! param->location = var->location;
return (Node *) param;
}
}
! /* No, so assign a PARAM_EXEC slot for a new NLP */
! param = SS_make_initplan_output_param(root,
! var->vartype,
! var->vartypmod,
! var->varcollid);
! param->location = var->location;
! /* Add it to the list of NLPs */
nlp = makeNode(NestLoopParam);
nlp->paramno = param->paramid;
nlp->paramval = var;
*************** replace_nestloop_params_mutator(Node *no
*** 4423,4442 ****
root);
return (Node *) newphv;
}
! /* Create a Param representing the PlaceHolderVar */
! param = assign_nestloop_param_placeholdervar(root, phv);
! /* Is this param already listed in root->curOuterParams? */
foreach(lc, root->curOuterParams)
{
nlp = (NestLoopParam *) lfirst(lc);
! if (nlp->paramno == param->paramid)
{
! Assert(equal(phv, nlp->paramval));
! /* Present, so we can just return the Param */
return (Node *) param;
}
}
! /* No, so add it */
nlp = makeNode(NestLoopParam);
nlp->paramno = param->paramid;
nlp->paramval = (Var *) phv;
--- 4433,4461 ----
root);
return (Node *) newphv;
}
! /* Is this PHV already listed in root->curOuterParams? */
foreach(lc, root->curOuterParams)
{
nlp = (NestLoopParam *) lfirst(lc);
! if (equal(phv, nlp->paramval))
{
! /* Yes, so just make a Param referencing this NLP's slot */
! param = makeNode(Param);
! param->paramkind = PARAM_EXEC;
! param->paramid = nlp->paramno;
! param->paramtype = exprType((Node *) phv->phexpr);
! param->paramtypmod = exprTypmod((Node *) phv->phexpr);
! param->paramcollid = exprCollation((Node *) phv->phexpr);
! param->location = -1;
return (Node *) param;
}
}
! /* No, so assign a PARAM_EXEC slot for a new NLP */
! param = SS_make_initplan_output_param(root,
! exprType((Node *) phv->phexpr),
! exprTypmod((Node *) phv->phexpr),
! exprCollation((Node *) phv->phexpr));
! /* Add it to the list of NLPs */
nlp = makeNode(NestLoopParam);
nlp->paramno = param->paramid;
nlp->paramval = (Var *) phv;
pgsql-bugs by date: