mirror of
https://github.com/postgres/postgres.git
synced 2025-04-24 10:47:04 +03:00
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.
This commit is contained in:
parent
4cb0950cfe
commit
07c741e61c
@ -9,7 +9,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.68 2000/10/26 21:36:09 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.69 2001/01/09 03:48:51 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
#include "postgres.h"
|
#include "postgres.h"
|
||||||
|
|
||||||
|
#include "nodes/makefuncs.h"
|
||||||
#include "nodes/nodeFuncs.h"
|
#include "nodes/nodeFuncs.h"
|
||||||
#include "optimizer/clauses.h"
|
#include "optimizer/clauses.h"
|
||||||
#include "optimizer/planmain.h"
|
#include "optimizer/planmain.h"
|
||||||
@ -270,22 +271,75 @@ set_join_references(Join *join)
|
|||||||
* to refer to the tuples returned by its lefttree subplan.
|
* to refer to the tuples returned by its lefttree subplan.
|
||||||
*
|
*
|
||||||
* This is used for single-input plan types like Agg, Group, Result.
|
* This is used for single-input plan types like Agg, Group, Result.
|
||||||
|
*
|
||||||
|
* In most cases, we have to match up individual Vars in the tlist and
|
||||||
|
* qual expressions with elements of the subplan's tlist (which was
|
||||||
|
* generated by flatten_tlist() from these selfsame expressions, so it
|
||||||
|
* should have all the required variables). There is an important exception,
|
||||||
|
* however: a GROUP BY expression that is also an output expression will
|
||||||
|
* have been pushed into the subplan tlist unflattened. We want to detect
|
||||||
|
* this case and reference the subplan output directly. Therefore, check
|
||||||
|
* for equality of the whole tlist expression to any subplan element before
|
||||||
|
* we resort to picking the expression apart for individual Vars.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
set_uppernode_references(Plan *plan, Index subvarno)
|
set_uppernode_references(Plan *plan, Index subvarno)
|
||||||
{
|
{
|
||||||
Plan *subplan = plan->lefttree;
|
Plan *subplan = plan->lefttree;
|
||||||
List *subplanTargetList;
|
List *subplanTargetList,
|
||||||
|
*outputTargetList,
|
||||||
|
*l;
|
||||||
|
|
||||||
if (subplan != NULL)
|
if (subplan != NULL)
|
||||||
subplanTargetList = subplan->targetlist;
|
subplanTargetList = subplan->targetlist;
|
||||||
else
|
else
|
||||||
subplanTargetList = NIL;
|
subplanTargetList = NIL;
|
||||||
|
|
||||||
plan->targetlist = (List *)
|
outputTargetList = NIL;
|
||||||
replace_vars_with_subplan_refs((Node *) plan->targetlist,
|
foreach (l, plan->targetlist)
|
||||||
subvarno,
|
{
|
||||||
subplanTargetList);
|
TargetEntry *tle = (TargetEntry *) lfirst(l);
|
||||||
|
TargetEntry *subplantle;
|
||||||
|
Node *newexpr;
|
||||||
|
|
||||||
|
subplantle = tlistentry_member(tle->expr, subplanTargetList);
|
||||||
|
if (subplantle)
|
||||||
|
{
|
||||||
|
/* Found a matching subplan output expression */
|
||||||
|
Resdom *resdom = subplantle->resdom;
|
||||||
|
Var *newvar;
|
||||||
|
|
||||||
|
newvar = makeVar(subvarno,
|
||||||
|
resdom->resno,
|
||||||
|
resdom->restype,
|
||||||
|
resdom->restypmod,
|
||||||
|
0);
|
||||||
|
/* If we're just copying a simple Var, copy up original info */
|
||||||
|
if (subplantle->expr && IsA(subplantle->expr, Var))
|
||||||
|
{
|
||||||
|
Var *subvar = (Var *) subplantle->expr;
|
||||||
|
|
||||||
|
newvar->varnoold = subvar->varnoold;
|
||||||
|
newvar->varoattno = subvar->varoattno;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
newvar->varnoold = 0;
|
||||||
|
newvar->varoattno = 0;
|
||||||
|
}
|
||||||
|
newexpr = (Node *) newvar;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* No matching expression, so replace individual Vars */
|
||||||
|
newexpr = replace_vars_with_subplan_refs(tle->expr,
|
||||||
|
subvarno,
|
||||||
|
subplanTargetList);
|
||||||
|
}
|
||||||
|
outputTargetList = lappend(outputTargetList,
|
||||||
|
makeTargetEntry(tle->resdom, newexpr));
|
||||||
|
}
|
||||||
|
plan->targetlist = outputTargetList;
|
||||||
|
|
||||||
plan->qual = (List *)
|
plan->qual = (List *)
|
||||||
replace_vars_with_subplan_refs((Node *) plan->qual,
|
replace_vars_with_subplan_refs((Node *) plan->qual,
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.46 2000/11/21 00:17:59 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.47 2001/01/09 03:48:51 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -125,6 +125,7 @@ make_subplan(SubLink *slink)
|
|||||||
{
|
{
|
||||||
SubPlan *node = makeNode(SubPlan);
|
SubPlan *node = makeNode(SubPlan);
|
||||||
Query *subquery = (Query *) (slink->subselect);
|
Query *subquery = (Query *) (slink->subselect);
|
||||||
|
Oid result_type = exprType((Node *) slink);
|
||||||
double tuple_fraction;
|
double tuple_fraction;
|
||||||
Plan *plan;
|
Plan *plan;
|
||||||
List *lst;
|
List *lst;
|
||||||
@ -368,7 +369,7 @@ make_subplan(SubLink *slink)
|
|||||||
/*
|
/*
|
||||||
* Make expression of SUBPLAN type
|
* Make expression of SUBPLAN type
|
||||||
*/
|
*/
|
||||||
expr->typeOid = BOOLOID;/* bogus, but we don't really care */
|
expr->typeOid = result_type;
|
||||||
expr->opType = SUBPLAN_EXPR;
|
expr->opType = SUBPLAN_EXPR;
|
||||||
expr->oper = (Node *) node;
|
expr->oper = (Node *) node;
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/tlist.c,v 1.47 2000/08/08 15:41:53 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/tlist.c,v 1.48 2001/01/09 03:48:50 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -18,7 +18,6 @@
|
|||||||
#include "optimizer/tlist.h"
|
#include "optimizer/tlist.h"
|
||||||
#include "optimizer/var.h"
|
#include "optimizer/var.h"
|
||||||
|
|
||||||
static TargetEntry *tlistentry_member(Node *node, List *targetlist);
|
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* ---------- RELATION node target list routines ----------
|
* ---------- RELATION node target list routines ----------
|
||||||
@ -29,7 +28,7 @@ static TargetEntry *tlistentry_member(Node *node, List *targetlist);
|
|||||||
* Finds the (first) member of the given tlist whose expression is
|
* Finds the (first) member of the given tlist whose expression is
|
||||||
* equal() to the given expression. Result is NULL if no such member.
|
* equal() to the given expression. Result is NULL if no such member.
|
||||||
*/
|
*/
|
||||||
static TargetEntry *
|
TargetEntry *
|
||||||
tlistentry_member(Node *node, List *targetlist)
|
tlistentry_member(Node *node, List *targetlist)
|
||||||
{
|
{
|
||||||
List *temp;
|
List *temp;
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: tlist.h,v 1.26 2000/06/08 22:37:51 momjian Exp $
|
* $Id: tlist.h,v 1.27 2001/01/09 03:48:50 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
#include "nodes/relation.h"
|
#include "nodes/relation.h"
|
||||||
|
|
||||||
|
extern TargetEntry *tlistentry_member(Node *node, List *targetlist);
|
||||||
extern Resdom *tlist_member(Node *node, List *targetlist);
|
extern Resdom *tlist_member(Node *node, List *targetlist);
|
||||||
|
|
||||||
extern void add_var_to_tlist(RelOptInfo *rel, Var *var);
|
extern void add_var_to_tlist(RelOptInfo *rel, Var *var);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user