|
7 | 7 | *
|
8 | 8 | *
|
9 | 9 | * 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 $ |
11 | 11 | *
|
12 | 12 | *-------------------------------------------------------------------------
|
13 | 13 | */
|
@@ -55,16 +55,11 @@ static RewriteInfo *gatherRewriteMeta(Query *parsetree,
|
55 | 55 | static bool rangeTableEntry_used(Node *node, int rt_index, int sublevels_up);
|
56 | 56 | static bool attribute_used(Node *node, int rt_index, int attno,
|
57 | 57 | int sublevels_up);
|
58 |
| -static bool modifyAggrefUplevel(Node *node, void *context); |
59 | 58 | static bool modifyAggrefChangeVarnodes(Node *node, int rt_index, int new_index,
|
60 | 59 | int sublevels_up, int new_sublevels_up);
|
61 | 60 | static Node *modifyAggrefDropQual(Node *node, Node *targetNode);
|
62 | 61 | static SubLink *modifyAggrefMakeSublink(Aggref *aggref, Query *parsetree);
|
63 | 62 | 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); |
68 | 63 | static Query *fireRIRrules(Query *parsetree);
|
69 | 64 | static Query *Except_Intersect_Rewrite(Query *parsetree);
|
70 | 65 | 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)
|
290 | 285 | }
|
291 | 286 |
|
292 | 287 |
|
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 |
| - |
347 | 288 | /*
|
348 | 289 | * modifyAggrefChangeVarnodes -
|
349 | 290 | * Change the var nodes in a sublink created for an aggregate column
|
350 | 291 | * used in the qualification to point to the correct local RTE.
|
351 | 292 | *
|
| 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 | + * |
352 | 297 | * NOTE: although this has the form of a walker, we cheat and modify the
|
353 | 298 | * Var nodes in-place. The given expression tree should have been copied
|
354 | 299 | * earlier to ensure that no unwanted side-effects occur!
|
@@ -547,18 +492,18 @@ modifyAggrefMakeSublink(Aggref *aggref, Query *parsetree)
|
547 | 492 | * Recursing would be a bad idea --- we'd likely produce an
|
548 | 493 | * infinite recursion. This whole technique is a crock, really...
|
549 | 494 | */
|
550 |
| - if (checkQueryHasAggs(subquery->qual)) |
| 495 | + if (checkExprHasAggs(subquery->qual)) |
551 | 496 | elog(ERROR, "Cannot handle multiple aggregate functions in WHERE clause");
|
552 | 497 | subquery->groupClause = NIL;
|
553 | 498 | subquery->havingQual = NULL;
|
554 | 499 | subquery->hasAggs = TRUE;
|
555 |
| - subquery->hasSubLinks = checkQueryHasSubLink(subquery->qual); |
| 500 | + subquery->hasSubLinks = checkExprHasSubLink(subquery->qual); |
556 | 501 | subquery->unionClause = NULL;
|
557 | 502 |
|
558 | 503 | /* Increment all varlevelsup fields in the new subquery */
|
559 |
| - modifyAggrefUplevel((Node *) subquery, NULL); |
| 504 | + IncrementVarSublevelsUp((Node *) subquery, 1, 0); |
560 | 505 |
|
561 |
| - /* Replace references to the target table with correct varno. |
| 506 | + /* Replace references to the target table with correct local varno. |
562 | 507 | * Note +1 here to account for effects of previous line!
|
563 | 508 | */
|
564 | 509 | modifyAggrefChangeVarnodes((Node *) subquery, target->varno,
|
@@ -600,49 +545,6 @@ modifyAggrefQual(Node *node, Query *parsetree)
|
600 | 545 | }
|
601 | 546 |
|
602 | 547 |
|
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 |
| - |
646 | 548 | static Node *
|
647 | 549 | FindMatchingTLEntry(List *tlist, char *e_attname)
|
648 | 550 | {
|
@@ -675,38 +577,6 @@ make_null(Oid type)
|
675 | 577 | }
|
676 | 578 |
|
677 | 579 |
|
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 |
| - |
710 | 580 | /*
|
711 | 581 | * apply_RIR_view
|
712 | 582 | * Replace Vars matching a given RT index with copies of TL expressions.
|
@@ -749,9 +619,12 @@ apply_RIR_view_mutator(Node *node,
|
749 | 619 | return make_null(var->vartype);
|
750 | 620 | }
|
751 | 621 |
|
| 622 | + /* Make a copy of the tlist item to return */ |
752 | 623 | expr = copyObject(expr);
|
| 624 | + /* Adjust varlevelsup if tlist item is from higher query level */ |
753 | 625 | if (var->varlevelsup > 0)
|
754 |
| - apply_RIR_adjust_sublevel(expr, var->varlevelsup); |
| 626 | + IncrementVarSublevelsUp(expr, var->varlevelsup, 0); |
| 627 | + |
755 | 628 | *(context->modified) = true;
|
756 | 629 | return (Node *) expr;
|
757 | 630 | }
|
@@ -1279,8 +1152,11 @@ fireRules(Query *parsetree,
|
1279 | 1152 | else
|
1280 | 1153 | qual_product = (Query *) nth(0, *qual_products);
|
1281 | 1154 |
|
| 1155 | + MemSet(&qual_info, 0, sizeof(qual_info)); |
1282 | 1156 | qual_info.event = qual_product->commandType;
|
| 1157 | + qual_info.current_varno = rt_index; |
1283 | 1158 | qual_info.new_varno = length(qual_product->rtable) + 2;
|
| 1159 | + |
1284 | 1160 | qual_product = CopyAndAddQual(qual_product,
|
1285 | 1161 | actions,
|
1286 | 1162 | event_qual,
|
@@ -1575,16 +1451,16 @@ BasicQueryRewrite(Query *parsetree)
|
1575 | 1451 | if (query->hasAggs)
|
1576 | 1452 | {
|
1577 | 1453 | 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))) |
1581 | 1457 | elog(ERROR, "BasicQueryRewrite: failed to remove aggs from qual");
|
1582 | 1458 | }
|
1583 | 1459 | if (query->hasSubLinks)
|
1584 | 1460 | 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)); |
1588 | 1464 | results = lappend(results, query);
|
1589 | 1465 | }
|
1590 | 1466 |
|
|
0 commit comments