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: