Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit e64a331

Browse files
committed
Fix some (more) problems with subselects in rules. Rewriter failed to
mark query as having subselects if a subselect was added from a rule WHERE condition (as opposed to a rule action). Also, fix adjustment of varlevelsup so that it actually has some prospect of working when inserting an expression containing a subselect into a subquery.
1 parent 4a3a1e2 commit e64a331

File tree

3 files changed

+188
-166
lines changed

3 files changed

+188
-166
lines changed

src/backend/rewrite/rewriteHandler.c

+22-146
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.68 2000/03/12 18:57:05 tgl Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.69 2000/03/16 03:23:18 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -55,16 +55,11 @@ static RewriteInfo *gatherRewriteMeta(Query *parsetree,
5555
static bool rangeTableEntry_used(Node *node, int rt_index, int sublevels_up);
5656
static bool attribute_used(Node *node, int rt_index, int attno,
5757
int sublevels_up);
58-
static bool modifyAggrefUplevel(Node *node, void *context);
5958
static bool modifyAggrefChangeVarnodes(Node *node, int rt_index, int new_index,
6059
int sublevels_up, int new_sublevels_up);
6160
static Node *modifyAggrefDropQual(Node *node, Node *targetNode);
6261
static SubLink *modifyAggrefMakeSublink(Aggref *aggref, Query *parsetree);
6362
static Node *modifyAggrefQual(Node *node, Query *parsetree);
64-
static bool checkQueryHasAggs(Node *node);
65-
static bool checkQueryHasAggs_walker(Node *node, void *context);
66-
static bool checkQueryHasSubLink(Node *node);
67-
static bool checkQueryHasSubLink_walker(Node *node, void *context);
6863
static Query *fireRIRrules(Query *parsetree);
6964
static Query *Except_Intersect_Rewrite(Query *parsetree);
7065
static void check_targetlists_are_compatible(List *prev_target,
@@ -290,65 +285,15 @@ attribute_used(Node *node, int rt_index, int attno, int sublevels_up)
290285
}
291286

292287

293-
/*
294-
* modifyAggrefUplevel -
295-
* In the newly created sublink for an aggregate column used in
296-
* the qualification, we must increment the varlevelsup in all the
297-
* var nodes.
298-
*
299-
* NOTE: although this has the form of a walker, we cheat and modify the
300-
* Var nodes in-place. The given expression tree should have been copied
301-
* earlier to ensure that no unwanted side-effects occur!
302-
*/
303-
static bool
304-
modifyAggrefUplevel(Node *node, void *context)
305-
{
306-
if (node == NULL)
307-
return false;
308-
if (IsA(node, Var))
309-
{
310-
Var *var = (Var *) node;
311-
312-
var->varlevelsup++;
313-
return false;
314-
}
315-
if (IsA(node, SubLink))
316-
{
317-
/*
318-
* Standard expression_tree_walker will not recurse into subselect,
319-
* but here we must do so.
320-
*/
321-
SubLink *sub = (SubLink *) node;
322-
323-
if (modifyAggrefUplevel((Node *) (sub->lefthand), context))
324-
return true;
325-
if (modifyAggrefUplevel((Node *) (sub->subselect), context))
326-
return true;
327-
return false;
328-
}
329-
if (IsA(node, Query))
330-
{
331-
/* Reach here after recursing down into subselect above... */
332-
Query *qry = (Query *) node;
333-
334-
if (modifyAggrefUplevel((Node *) (qry->targetList), context))
335-
return true;
336-
if (modifyAggrefUplevel((Node *) (qry->qual), context))
337-
return true;
338-
if (modifyAggrefUplevel((Node *) (qry->havingQual), context))
339-
return true;
340-
return false;
341-
}
342-
return expression_tree_walker(node, modifyAggrefUplevel,
343-
(void *) context);
344-
}
345-
346-
347288
/*
348289
* modifyAggrefChangeVarnodes -
349290
* Change the var nodes in a sublink created for an aggregate column
350291
* used in the qualification to point to the correct local RTE.
351292
*
293+
* XXX if we still need this after redoing querytree design, it should
294+
* be combined with ChangeVarNodes, which is the same thing except for
295+
* not having the option to adjust the vars' varlevelsup.
296+
*
352297
* NOTE: although this has the form of a walker, we cheat and modify the
353298
* Var nodes in-place. The given expression tree should have been copied
354299
* earlier to ensure that no unwanted side-effects occur!
@@ -547,18 +492,18 @@ modifyAggrefMakeSublink(Aggref *aggref, Query *parsetree)
547492
* Recursing would be a bad idea --- we'd likely produce an
548493
* infinite recursion. This whole technique is a crock, really...
549494
*/
550-
if (checkQueryHasAggs(subquery->qual))
495+
if (checkExprHasAggs(subquery->qual))
551496
elog(ERROR, "Cannot handle multiple aggregate functions in WHERE clause");
552497
subquery->groupClause = NIL;
553498
subquery->havingQual = NULL;
554499
subquery->hasAggs = TRUE;
555-
subquery->hasSubLinks = checkQueryHasSubLink(subquery->qual);
500+
subquery->hasSubLinks = checkExprHasSubLink(subquery->qual);
556501
subquery->unionClause = NULL;
557502

558503
/* Increment all varlevelsup fields in the new subquery */
559-
modifyAggrefUplevel((Node *) subquery, NULL);
504+
IncrementVarSublevelsUp((Node *) subquery, 1, 0);
560505

561-
/* Replace references to the target table with correct varno.
506+
/* Replace references to the target table with correct local varno.
562507
* Note +1 here to account for effects of previous line!
563508
*/
564509
modifyAggrefChangeVarnodes((Node *) subquery, target->varno,
@@ -600,49 +545,6 @@ modifyAggrefQual(Node *node, Query *parsetree)
600545
}
601546

602547

603-
/*
604-
* checkQueryHasAggs -
605-
* Queries marked hasAggs might not have them any longer after
606-
* rewriting. Check it.
607-
*/
608-
static bool
609-
checkQueryHasAggs(Node *node)
610-
{
611-
return checkQueryHasAggs_walker(node, NULL);
612-
}
613-
614-
static bool
615-
checkQueryHasAggs_walker(Node *node, void *context)
616-
{
617-
if (node == NULL)
618-
return false;
619-
if (IsA(node, Aggref))
620-
return true; /* abort the tree traversal and return true */
621-
return expression_tree_walker(node, checkQueryHasAggs_walker, context);
622-
}
623-
624-
/*
625-
* checkQueryHasSubLink -
626-
* Queries marked hasSubLinks might not have them any longer after
627-
* rewriting. Check it.
628-
*/
629-
static bool
630-
checkQueryHasSubLink(Node *node)
631-
{
632-
return checkQueryHasSubLink_walker(node, NULL);
633-
}
634-
635-
static bool
636-
checkQueryHasSubLink_walker(Node *node, void *context)
637-
{
638-
if (node == NULL)
639-
return false;
640-
if (IsA(node, SubLink))
641-
return true; /* abort the tree traversal and return true */
642-
return expression_tree_walker(node, checkQueryHasSubLink_walker, context);
643-
}
644-
645-
646548
static Node *
647549
FindMatchingTLEntry(List *tlist, char *e_attname)
648550
{
@@ -675,38 +577,6 @@ make_null(Oid type)
675577
}
676578

677579

678-
/*
679-
* apply_RIR_adjust_sublevel -
680-
* Set the varlevelsup field of all Var nodes in the given expression tree
681-
* to sublevels_up. We do NOT recurse into subselects.
682-
*
683-
* NOTE: although this has the form of a walker, we cheat and modify the
684-
* Var nodes in-place. The given expression tree should have been copied
685-
* earlier to ensure that no unwanted side-effects occur!
686-
*/
687-
static bool
688-
apply_RIR_adjust_sublevel_walker(Node *node, int *sublevels_up)
689-
{
690-
if (node == NULL)
691-
return false;
692-
if (IsA(node, Var))
693-
{
694-
Var *var = (Var *) node;
695-
696-
var->varlevelsup = *sublevels_up;
697-
return false;
698-
}
699-
return expression_tree_walker(node, apply_RIR_adjust_sublevel_walker,
700-
(void *) sublevels_up);
701-
}
702-
703-
static void
704-
apply_RIR_adjust_sublevel(Node *node, int sublevels_up)
705-
{
706-
apply_RIR_adjust_sublevel_walker(node, &sublevels_up);
707-
}
708-
709-
710580
/*
711581
* apply_RIR_view
712582
* Replace Vars matching a given RT index with copies of TL expressions.
@@ -749,9 +619,12 @@ apply_RIR_view_mutator(Node *node,
749619
return make_null(var->vartype);
750620
}
751621

622+
/* Make a copy of the tlist item to return */
752623
expr = copyObject(expr);
624+
/* Adjust varlevelsup if tlist item is from higher query level */
753625
if (var->varlevelsup > 0)
754-
apply_RIR_adjust_sublevel(expr, var->varlevelsup);
626+
IncrementVarSublevelsUp(expr, var->varlevelsup, 0);
627+
755628
*(context->modified) = true;
756629
return (Node *) expr;
757630
}
@@ -1279,8 +1152,11 @@ fireRules(Query *parsetree,
12791152
else
12801153
qual_product = (Query *) nth(0, *qual_products);
12811154

1155+
MemSet(&qual_info, 0, sizeof(qual_info));
12821156
qual_info.event = qual_product->commandType;
1157+
qual_info.current_varno = rt_index;
12831158
qual_info.new_varno = length(qual_product->rtable) + 2;
1159+
12841160
qual_product = CopyAndAddQual(qual_product,
12851161
actions,
12861162
event_qual,
@@ -1575,16 +1451,16 @@ BasicQueryRewrite(Query *parsetree)
15751451
if (query->hasAggs)
15761452
{
15771453
query->hasAggs =
1578-
checkQueryHasAggs((Node *) (query->targetList)) ||
1579-
checkQueryHasAggs((Node *) (query->havingQual));
1580-
if (checkQueryHasAggs((Node *) (query->qual)))
1454+
checkExprHasAggs((Node *) (query->targetList)) ||
1455+
checkExprHasAggs((Node *) (query->havingQual));
1456+
if (checkExprHasAggs((Node *) (query->qual)))
15811457
elog(ERROR, "BasicQueryRewrite: failed to remove aggs from qual");
15821458
}
15831459
if (query->hasSubLinks)
15841460
query->hasSubLinks =
1585-
checkQueryHasSubLink((Node *) (query->targetList)) ||
1586-
checkQueryHasSubLink((Node *) (query->qual)) ||
1587-
checkQueryHasSubLink((Node *) (query->havingQual));
1461+
checkExprHasSubLink((Node *) (query->targetList)) ||
1462+
checkExprHasSubLink((Node *) (query->qual)) ||
1463+
checkExprHasSubLink((Node *) (query->havingQual));
15881464
results = lappend(results, query);
15891465
}
15901466

0 commit comments

Comments
 (0)