8000 Fix oversight in planning of GROUP queries: when an expression is used · postgrespro/postgres_cluster@07c741e · GitHub
[go: up one dir, main page]

Skip to content

Commit 07c741e

Browse files
committed
Fix oversight in planning of GROUP queries: when an expression is used
as both a GROUP BY item and an output expression, the top-level Group node should just copy up the evaluated expression value from its input, rather than re-evaluating the expression. Aside from any performance benefit this might offer, this avoids a crash when there is a sub-SELECT in said expression.
1 parent 4cb0950 commit 07c741e

File tree

4 files changed

+67
-12
lines changed
  • src
    • backend/optimizer
      • plan
        • < 8000 div style="width:100%;display:flex">
  • util
  • include/optimizer
  • 4 files changed

    +67
    -12
    lines changed

    src/backend/optimizer/plan/setrefs.c

    Lines changed: 60 additions & 6 deletions
    Original file line numberDiff line numberDiff line change
    @@ -9,14 +9,15 @@
    99
    *
    1010
    *
    1111
    * IDENTIFICATION
    12-
    * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.68 2000/10/26 21:36:09 tgl Exp $
    12+
    * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.69 2001/01/09 03:48:51 tgl Exp $
    1313
    *
    1414
    *-------------------------------------------------------------------------
    1515
    */
    1616
    #include <sys/types.h>
    1717

    1818
    #include "postgres.h"
    1919

    20+
    #include "nodes/makefuncs.h"
    2021
    #include "nodes/nodeFuncs.h"
    2122
    #include "optimizer/clauses.h"
    2223
    #include "optimizer/planmain.h"
    @@ -270,22 +271,75 @@ set_join_references(Join *join)
    270271
    * to refer to the tuples returned by its lefttree subplan.
    271272
    *
    272273
    * This is used for single-input plan types like Agg, Group, Result.
    274+
    *
    275+
    * In most cases, we have to match up individual Vars in the tlist and
    276+
    * qual expressions with elements of the subplan's tlist (which was
    277+
    * generated by flatten_tlist() from these selfsame expressions, so it
    278+
    * should have all the required variables). There is an important exception,
    279+
    * however: a GROUP BY expression that is also an output expression will
    280+
    * have been pushed into the subplan tlist unflattened. We want to detect
    281+
    * this case and reference the subplan output directly. Therefore, check
    282+
    * for equality of the whole tlist expression to any subplan element before
    283+
    * we resort to picking the expression apart for individual Vars.
    273284
    */
    274285
    static void
    275286
    set_uppernode_references(Plan *plan, Index subvarno)
    276287
    {
    277288
    Plan *subplan = plan->lefttree;
    278-
    List *subplanTargetList;
    289+
    List *subplanTargetList,
    290+
    *outputTargetList,
    291+
    *l;
    279292

    280293
    if (subplan != NULL)
    281294
    subplanTargetList = subplan->targetlist;
    282295
    else
    283296
    subplanTargetList = NIL;
    284297

    285-
    plan->targetlist = (List *)
    286-
    replace_vars_with_subplan_refs((Node *) plan->targetlist,
    287-
    subvarno,
    288-
    subplanTargetList);
    298+
    outputTargetList = NIL;
    299+
    foreach (l, plan->targetlist)
    300+
    {
    301+
    TargetEntry *tle = (TargetEntry *) lfirst(l);
    302+
    TargetEntry *subplantle;
    303+
    Node *newexpr;
    304+
    305+
    subplantle = tlistentry_member(tle->expr, subplanTargetList);
    306+
    if (subplantle)
    307+
    {
    308+
    /* Found a matching subplan output expression */
    309+
    Resdom *resdom = subplantle->resdom;
    310+
    Var *newvar;
    311+
    312+
    newvar = makeVar(subvarno,
    313+
    resdom->resno,
    314+
    resdom->restype,
    315+
    resdom->restypmod,
    316+
    0);
    317+
    /* If we're just copying a simple Var, copy up original info */
    318+
    if (subplantle->expr && IsA(subplantle->expr, Var))
    319+
    {
    320+
    Var *subvar = (Var *) subplantle->expr;
    321+
    322+
    newvar->varnoold = subvar->varnoold;
    323+
    newvar->varoattno = subvar->varoattno;
    324+
    }
    325+
    else
    326+
    {
    327+
    newvar->varnoold = 0;
    328+
    newvar->varoattno = 0;
    329+
    }
    330+
    newexpr = (Node *) newvar;
    331+
    }
    332+
    else
    333+
    {
    334+
    /* No matching expression, so replace individual Vars */
    335+
    newexpr = replace_vars_with_subplan_refs(tle->expr,
    336+
    subvarno,
    337+
    subplanTargetList);
    338+
    }
    339+
    outputTargetList = lappend(outputTargetList,
    340+
    makeTargetEntry(tle->resdom, newexpr));
    341+
    }
    342+
    plan->targetlist = outputTargetList;
    289343

    290344
    plan->qual = (List *)
    291345
    replace_vars_with_subplan_refs((Node *) plan->qual,

    src/backend/optimizer/plan/subselect.c

    Lines changed: 3 additions & 2 deletions
    Original file line numberDiff line numberDiff line change
    @@ -7,7 +7,7 @@
    77
    * Portions Copyright (c) 1994, Regents of the University of California
    88
    *
    99
    * IDENTIFICATION
    10-
    * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.46 2000/11/21 00:17:59 tgl Exp $
    10+
    * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.47 2001/01/09 03:48:51 tgl Exp $
    1111
    *
    1212
    *-------------------------------------------------------------------------
    1313
    */
    @@ -125,6 +125,7 @@ make_subplan(SubLink *slink)
    125125
    {
    126126
    SubPlan *node = makeNode(SubPlan);
    127127
    Query *subquery = (Query *) (slink->subselect);
    128+
    Oid result_type = exprType((Node *) slink);
    128129
    double tuple_fraction;
    129130
    Plan *plan;
    130131
    List *lst;
    @@ -368,7 +369,7 @@ make_subplan(SubLink *slink)
    368369
    /*
    369370
    * Make expression of SUBPLAN type
    370371
    */
    371-
    expr->typeOid = BOOLOID;/* bogus, but we don't really care */
    372+
    expr->typeOid = result_type;
    372373
    expr->opType = SUBPLAN_EXPR;
    373374
    expr->oper = (Node *) node;
    374375

    src/backend/optimizer/util/tlist.c

    Lines changed: 2 additions & 3 deletions
    Original file line numberDiff line numberDiff line change
    @@ -8,7 +8,7 @@
    88
    *
    99
    *
    1010
    * IDENTIFICATION
    11-
    * $Header: /cvsroot/pgsql/src/backend/optimizer/util/tlist.c,v 1.47 2000/08/08 15:41:53 tgl Exp $
    11+
    * $Header: /cvsroot/pgsql/src/backend/optimizer/util/tlist.c,v 1.48 2001/01/09 03:48:50 tgl Exp $
    1212
    *
    1313
    *-------------------------------------------------------------------------
    1414
    */
    @@ -18,7 +18,6 @@
    1818
    #include "optimizer/tlist.h"
    1919
    #include "optimizer/var.h"
    2020

    21-
    static TargetEntry *tlistentry_member(Node *node, List *targetlist);
    2221

    2322
    /*****************************************************************************
    2423
    * ---------- RELATION node target list routines ----------
    @@ -29,7 +28,7 @@ static TargetEntry *tlistentry_member(Node *node, List *targetlist);
    2928
    * Finds the (first) member of the given tlist whose expression is
    3029
    * equal() to the given expression. Result is NULL if no such member.
    3130
    */
    32-
    static TargetEntry *
    31+
    TargetEntry *
    3332
    tlistentry_member(Node *node, List *targetlist)
    3433
    {
    3534
    List *temp;

    src/include/optimizer/tlist.h

    Lines changed: 2 additions & 1 deletion
    Original file line numberDiff line numberDiff line change
    @@ -7,7 +7,7 @@
    77
    * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
    88
    * Portions Copyright (c) 1994, Regents of the University of California
    99
    *
    10-
    * $Id: tlist.h,v 1.26 2000/06/08 22:37:51 momjian Exp $
    10+
    * $Id: tlist.h,v 1.27 2001/01/09 03:48:50 tgl Exp $
    1111
    *
    1212
    *-------------------------------------------------------------------------
    1313
    */
    @@ -16,6 +16,7 @@
    1616

    1717
    #include "nodes/relation.h"
    1818

    19+
    extern TargetEntry *tlistentry_member(Node *node, List *targetlist);
    1920
    extern Resdom *tlist_member(Node *node, List *targetlist);
    2021

    2122
    extern void add_var_to_tlist(RelOptInfo *rel, Var *var);

    0 commit comments

    Comments
     (0)
    0