rewriteManip.c
上传用户:blenddy
上传日期:2007-01-07
资源大小:6495k
文件大小:24k
源码类别:

数据库系统

开发平台:

Unix_Linux

  1. /*-------------------------------------------------------------------------
  2.  *
  3.  * rewriteManip.c
  4.  *
  5.  * Copyright (c) 1994, Regents of the University of California
  6.  *
  7.  *
  8.  * IDENTIFICATION
  9.  *   $Header: /usr/local/cvsroot/pgsql/src/backend/rewrite/rewriteManip.c,v 1.32 1999/05/26 12:55:48 momjian Exp $
  10.  *
  11.  *-------------------------------------------------------------------------
  12.  */
  13. #include <string.h>
  14. #include "postgres.h"
  15. #include "nodes/pg_list.h"
  16. #include "utils/elog.h"
  17. #include "nodes/nodes.h"
  18. #include "nodes/relation.h"
  19. #include "nodes/primnodes.h"
  20. #include "parser/parsetree.h" /* for getrelid() */
  21. #include "utils/lsyscache.h"
  22. #include "utils/builtins.h"
  23. #include "rewrite/rewriteHandler.h"
  24. #include "rewrite/rewriteManip.h"
  25. #include "rewrite/rewriteSupport.h"
  26. #include "rewrite/locks.h"
  27. #include "nodes/plannodes.h"
  28. #include "optimizer/clauses.h"
  29. static void ResolveNew(RewriteInfo *info, List *targetlist,
  30.    Node **node, int sublevels_up);
  31. /*
  32.  * OffsetVarnodes -
  33.  */
  34. void
  35. OffsetVarNodes(Node *node, int offset, int sublevels_up)
  36. {
  37. if (node == NULL)
  38. return;
  39. switch (nodeTag(node))
  40. {
  41. case T_TargetEntry:
  42. {
  43. TargetEntry *tle = (TargetEntry *) node;
  44. OffsetVarNodes(
  45.    (Node *) (tle->expr),
  46.    offset,
  47.    sublevels_up);
  48. }
  49. break;
  50. case T_Aggref:
  51. {
  52. Aggref    *aggref = (Aggref *) node;
  53. OffsetVarNodes(
  54.    (Node *) (aggref->target),
  55.    offset,
  56.    sublevels_up);
  57. }
  58. break;
  59. case T_GroupClause:
  60. break;
  61. case T_Expr:
  62. {
  63. Expr    *exp = (Expr *) node;
  64. OffsetVarNodes(
  65.    (Node *) (exp->args),
  66.    offset,
  67.    sublevels_up);
  68. }
  69. break;
  70. case T_Iter:
  71. {
  72. Iter    *iter = (Iter *) node;
  73. OffsetVarNodes(
  74.    (Node *) (iter->iterexpr),
  75.    offset,
  76.    sublevels_up);
  77. }
  78. break;
  79. case T_ArrayRef:
  80. {
  81. ArrayRef   *ref = (ArrayRef *) node;
  82. OffsetVarNodes(
  83.    (Node *) (ref->refupperindexpr),
  84.    offset,
  85.    sublevels_up);
  86. OffsetVarNodes(
  87.    (Node *) (ref->reflowerindexpr),
  88.    offset,
  89.    sublevels_up);
  90. OffsetVarNodes(
  91.    (Node *) (ref->refexpr),
  92.    offset,
  93.    sublevels_up);
  94. OffsetVarNodes(
  95.    (Node *) (ref->refassgnexpr),
  96.    offset,
  97.    sublevels_up);
  98. }
  99. break;
  100. case T_Var:
  101. {
  102. Var    *var = (Var *) node;
  103. if (var->varlevelsup == sublevels_up)
  104. {
  105. var->varno += offset;
  106. var->varnoold += offset;
  107. }
  108. }
  109. break;
  110. case T_Param:
  111. break;
  112. case T_Const:
  113. break;
  114. case T_List:
  115. {
  116. List    *l;
  117. foreach(l, (List *) node)
  118. OffsetVarNodes(
  119.    (Node *) lfirst(l),
  120.    offset,
  121.    sublevels_up);
  122. }
  123. break;
  124. case T_SubLink:
  125. {
  126. SubLink    *sub = (SubLink *) node;
  127. List    *tmp_oper,
  128.    *tmp_lefthand;
  129. /*
  130.  * We also have to adapt the variables used in
  131.  * sub->lefthand and sub->oper
  132.  */
  133. OffsetVarNodes(
  134.    (Node *) (sub->lefthand),
  135.    offset,
  136.    sublevels_up);
  137. OffsetVarNodes(
  138.    (Node *) (sub->subselect),
  139.    offset,
  140.    sublevels_up + 1);
  141. /***S*I***/
  142. /*
  143.  * Make sure the first argument of sub->oper points to the
  144.  * same var as sub->lefthand does otherwise we will run
  145.  * into troubles using aggregates (aggno will not be set
  146.  * correctly)
  147.  */
  148. tmp_lefthand = sub->lefthand;
  149. foreach(tmp_oper, sub->oper)
  150. {
  151. lfirst(((Expr *) lfirst(tmp_oper))->args) =
  152. lfirst(tmp_lefthand);
  153. tmp_lefthand = lnext(tmp_lefthand);
  154. }
  155. }
  156. break;
  157. case T_Query:
  158. {
  159. Query    *qry = (Query *) node;
  160. OffsetVarNodes(
  161.    (Node *) (qry->targetList),
  162.    offset,
  163.    sublevels_up);
  164. OffsetVarNodes(
  165.    (Node *) (qry->qual),
  166.    offset,
  167.    sublevels_up);
  168. OffsetVarNodes(
  169.    (Node *) (qry->havingQual),
  170.    offset,
  171.    sublevels_up);
  172. }
  173. break;
  174. case T_CaseExpr:
  175. {
  176. CaseExpr   *exp = (CaseExpr *) node;
  177. OffsetVarNodes(
  178.    (Node *) (exp->args),
  179.    offset,
  180.    sublevels_up);
  181. OffsetVarNodes(
  182.    (Node *) (exp->defresult),
  183.    offset,
  184.    sublevels_up);
  185. }
  186. break;
  187. case T_CaseWhen:
  188. {
  189. CaseWhen   *exp = (CaseWhen *) node;
  190. OffsetVarNodes(
  191.    (Node *) (exp->expr),
  192.    offset,
  193.    sublevels_up);
  194. OffsetVarNodes(
  195.    (Node *) (exp->result),
  196.    offset,
  197.    sublevels_up);
  198. }
  199. break;
  200. default:
  201. elog(NOTICE, "unknown node tag %d in OffsetVarNodes()", nodeTag(node));
  202. elog(NOTICE, "Node is: %s", nodeToString(node));
  203. break;
  204. }
  205. }
  206. /*
  207.  * ChangeVarNodes -
  208.  */
  209. void
  210. ChangeVarNodes(Node *node, int rt_index, int new_index, int sublevels_up)
  211. {
  212. if (node == NULL)
  213. return;
  214. switch (nodeTag(node))
  215. {
  216. case T_TargetEntry:
  217. {
  218. TargetEntry *tle = (TargetEntry *) node;
  219. ChangeVarNodes(
  220.    (Node *) (tle->expr),
  221.    rt_index,
  222.    new_index,
  223.    sublevels_up);
  224. }
  225. break;
  226. case T_Aggref:
  227. {
  228. Aggref    *aggref = (Aggref *) node;
  229. ChangeVarNodes(
  230.    (Node *) (aggref->target),
  231.    rt_index,
  232.    new_index,
  233.    sublevels_up);
  234. }
  235. break;
  236. case T_GroupClause:
  237. break;
  238. case T_Expr:
  239. {
  240. Expr    *exp = (Expr *) node;
  241. ChangeVarNodes(
  242.    (Node *) (exp->args),
  243.    rt_index,
  244.    new_index,
  245.    sublevels_up);
  246. }
  247. break;
  248. case T_Iter:
  249. {
  250. Iter    *iter = (Iter *) node;
  251. ChangeVarNodes(
  252.    (Node *) (iter->iterexpr),
  253.    rt_index,
  254.    new_index,
  255.    sublevels_up);
  256. }
  257. break;
  258. case T_ArrayRef:
  259. {
  260. ArrayRef   *ref = (ArrayRef *) node;
  261. ChangeVarNodes(
  262.    (Node *) (ref->refupperindexpr),
  263.    rt_index,
  264.    new_index,
  265.    sublevels_up);
  266. ChangeVarNodes(
  267.    (Node *) (ref->reflowerindexpr),
  268.    rt_index,
  269.    new_index,
  270.    sublevels_up);
  271. ChangeVarNodes(
  272.    (Node *) (ref->refexpr),
  273.    rt_index,
  274.    new_index,
  275.    sublevels_up);
  276. ChangeVarNodes(
  277.    (Node *) (ref->refassgnexpr),
  278.    rt_index,
  279.    new_index,
  280.    sublevels_up);
  281. }
  282. break;
  283. case T_Var:
  284. {
  285. Var    *var = (Var *) node;
  286. if (var->varlevelsup == sublevels_up &&
  287. var->varno == rt_index)
  288. {
  289. var->varno = new_index;
  290. var->varnoold = new_index;
  291. }
  292. }
  293. break;
  294. case T_Param:
  295. break;
  296. case T_Const:
  297. break;
  298. case T_List:
  299. {
  300. List    *l;
  301. foreach(l, (List *) node)
  302. ChangeVarNodes(
  303.    (Node *) lfirst(l),
  304.    rt_index,
  305.    new_index,
  306.    sublevels_up);
  307. }
  308. break;
  309. case T_SubLink:
  310. {
  311. SubLink    *sub = (SubLink *) node;
  312. List    *tmp_oper,
  313.    *tmp_lefthand;
  314. ChangeVarNodes(
  315.    (Node *) (sub->lefthand),
  316.    rt_index,
  317.    new_index,
  318.    sublevels_up);
  319. ChangeVarNodes(
  320.    (Node *) (sub->subselect),
  321.    rt_index,
  322.    new_index,
  323.    sublevels_up + 1);
  324. /***S*I***/
  325. /*
  326.  * Make sure the first argument of sub->oper points to the
  327.  * same var as sub->lefthand does otherwise we will run
  328.  * into troubles using aggregates (aggno will not be set
  329.  * correctly)
  330.  */
  331. tmp_lefthand = sub->lefthand;
  332. foreach(tmp_oper, sub->oper)
  333. {
  334. lfirst(((Expr *) lfirst(tmp_oper))->args) =
  335. lfirst(tmp_lefthand);
  336. tmp_lefthand = lnext(tmp_lefthand);
  337. }
  338. }
  339. break;
  340. case T_Query:
  341. {
  342. Query    *qry = (Query *) node;
  343. ChangeVarNodes(
  344.    (Node *) (qry->targetList),
  345.    rt_index,
  346.    new_index,
  347.    sublevels_up);
  348. ChangeVarNodes(
  349.    (Node *) (qry->qual),
  350.    rt_index,
  351.    new_index,
  352.    sublevels_up);
  353. ChangeVarNodes(
  354.    (Node *) (qry->havingQual),
  355.    rt_index,
  356.    new_index,
  357.    sublevels_up);
  358. }
  359. break;
  360. case T_CaseExpr:
  361. {
  362. CaseExpr   *exp = (CaseExpr *) node;
  363. ChangeVarNodes(
  364.    (Node *) (exp->args),
  365.    rt_index,
  366.    new_index,
  367.    sublevels_up);
  368. ChangeVarNodes(
  369.    (Node *) (exp->defresult),
  370.    rt_index,
  371.    new_index,
  372.    sublevels_up);
  373. }
  374. break;
  375. case T_CaseWhen:
  376. {
  377. CaseWhen   *exp = (CaseWhen *) node;
  378. ChangeVarNodes(
  379.    (Node *) (exp->expr),
  380.    rt_index,
  381.    new_index,
  382.    sublevels_up);
  383. ChangeVarNodes(
  384.    (Node *) (exp->result),
  385.    rt_index,
  386.    new_index,
  387.    sublevels_up);
  388. }
  389. break;
  390. default:
  391. elog(NOTICE, "unknown node tag %d in ChangeVarNodes()", nodeTag(node));
  392. elog(NOTICE, "Node is: %s", nodeToString(node));
  393. break;
  394. }
  395. }
  396. void
  397. AddQual(Query *parsetree, Node *qual)
  398. {
  399. Node    *copy,
  400.    *old;
  401. if (qual == NULL)
  402. return;
  403. /***S*I***/
  404. /* INTERSECT want's the original, but we need to copy - Jan */
  405. /* copy = qual; */
  406. copy = copyObject(qual);
  407. old = parsetree->qual;
  408. if (old == NULL)
  409. parsetree->qual = copy;
  410. else
  411. parsetree->qual = (Node *) make_andclause(makeList(parsetree->qual, copy, -1));
  412. }
  413. /* Adds the given havingQual to the one already contained in the parsetree just as
  414.  * AddQual does for the normal 'where' qual */
  415. void
  416. AddHavingQual(Query *parsetree, Node *havingQual)
  417. {
  418. Node    *copy,
  419.    *old;
  420. if (havingQual == NULL)
  421. return;
  422. /***S*I***/
  423. /* INTERSECT want's the original, but we need to copy - Jan */
  424. /* copy = havingQual; */
  425. copy = copyObject(havingQual);
  426. old = parsetree->havingQual;
  427. if (old == NULL)
  428. parsetree->havingQual = copy;
  429. else
  430. parsetree->havingQual = (Node *) make_andclause(makeList(parsetree->havingQual, copy, -1));
  431. }
  432. #ifdef NOT_USED
  433. void
  434. AddNotHavingQual(Query *parsetree, Node *havingQual)
  435. {
  436. Node    *copy;
  437. if (havingQual == NULL)
  438. return;
  439. /***S*I***/
  440. /* INTERSECT want's the original, but we need to copy - Jan */
  441. /* copy = (Node *) make_notclause((Expr *)havingQual); */
  442. copy = (Node *) make_notclause((Expr *) copyObject(havingQual));
  443. AddHavingQual(parsetree, copy);
  444. }
  445. #endif
  446. void
  447. AddNotQual(Query *parsetree, Node *qual)
  448. {
  449. Node    *copy;
  450. if (qual == NULL)
  451. return;
  452. /***S*I***/
  453. /* INTERSECT want's the original, but we need to copy - Jan */
  454. /* copy = (Node *) make_notclause((Expr *)qual); */
  455. copy = (Node *) make_notclause((Expr *) copyObject(qual));
  456. AddQual(parsetree, copy);
  457. }
  458. void
  459. AddGroupClause(Query *parsetree, List *group_by, List *tlist)
  460. {
  461. List    *l;
  462. List    *tl;
  463. GroupClause *groupclause;
  464. TargetEntry *tle;
  465. int new_resno;
  466. new_resno = length(parsetree->targetList);
  467. foreach(l, group_by)
  468. {
  469. groupclause = (GroupClause *) copyObject(lfirst(l));
  470. tle = NULL;
  471. foreach(tl, tlist)
  472. {
  473. if (((TargetEntry *) lfirst(tl))->resdom->resgroupref ==
  474. groupclause->tleGroupref)
  475. {
  476. tle = (TargetEntry *) copyObject(lfirst(tl));
  477. break;
  478. }
  479. }
  480. if (tle == NULL)
  481. elog(ERROR, "AddGroupClause(): GROUP BY entry not found in rules targetlist");
  482. tle->resdom->resno = ++new_resno;
  483. tle->resdom->resjunk = true;
  484. tle->resdom->resgroupref = length(parsetree->groupClause) + 1;
  485. groupclause->tleGroupref = tle->resdom->resgroupref;
  486. parsetree->targetList = lappend(parsetree->targetList, tle);
  487. parsetree->groupClause = lappend(parsetree->groupClause, groupclause);
  488. }
  489. }
  490. static Node *
  491. make_null(Oid type)
  492. {
  493. Const    *c = makeNode(Const);
  494. c->consttype = type;
  495. c->constlen = get_typlen(type);
  496. c->constvalue = PointerGetDatum(NULL);
  497. c->constisnull = true;
  498. c->constbyval = get_typbyval(type);
  499. return (Node *) c;
  500. }
  501. #ifdef NOT_USED
  502. void
  503. FixResdomTypes(List *tlist)
  504. {
  505. List    *i;
  506. foreach(i, tlist)
  507. {
  508. TargetEntry *tle = lfirst(i);
  509. if (nodeTag(tle->expr) == T_Var)
  510. {
  511. Var    *var = (Var *) tle->expr;
  512. tle->resdom->restype = var->vartype;
  513. tle->resdom->restypmod = var->vartypmod;
  514. }
  515. }
  516. }
  517. #endif
  518. static Node *
  519. FindMatchingNew(List *tlist, int attno)
  520. {
  521. List    *i;
  522. foreach(i, tlist)
  523. {
  524. TargetEntry *tle = lfirst(i);
  525. if (tle->resdom->resno == attno)
  526. return tle->expr;
  527. }
  528. return NULL;
  529. }
  530. static Node *
  531. FindMatchingTLEntry(List *tlist, char *e_attname)
  532. {
  533. List    *i;
  534. foreach(i, tlist)
  535. {
  536. TargetEntry *tle = lfirst(i);
  537. char    *resname;
  538. resname = tle->resdom->resname;
  539. if (!strcmp(e_attname, resname))
  540. return tle->expr;
  541. }
  542. return NULL;
  543. }
  544. static void
  545. ResolveNew(RewriteInfo *info, List *targetlist, Node **nodePtr,
  546.    int sublevels_up)
  547. {
  548. Node    *node = *nodePtr;
  549. if (node == NULL)
  550. return;
  551. switch (nodeTag(node))
  552. {
  553. case T_TargetEntry:
  554. ResolveNew(info, targetlist, &((TargetEntry *) node)->expr,
  555.    sublevels_up);
  556. break;
  557. case T_Aggref:
  558. ResolveNew(info, targetlist, &((Aggref *) node)->target,
  559.    sublevels_up);
  560. break;
  561. case T_Expr:
  562. ResolveNew(info, targetlist, (Node **) (&(((Expr *) node)->args)),
  563.    sublevels_up);
  564. break;
  565. case T_Iter:
  566. ResolveNew(info, targetlist, (Node **) (&(((Iter *) node)->iterexpr)),
  567.    sublevels_up);
  568. break;
  569. case T_ArrayRef:
  570. ResolveNew(info, targetlist, (Node **) (&(((ArrayRef *) node)->refupperindexpr)),
  571.    sublevels_up);
  572. ResolveNew(info, targetlist, (Node **) (&(((ArrayRef *) node)->reflowerindexpr)),
  573.    sublevels_up);
  574. ResolveNew(info, targetlist, (Node **) (&(((ArrayRef *) node)->refexpr)),
  575.    sublevels_up);
  576. ResolveNew(info, targetlist, (Node **) (&(((ArrayRef *) node)->refassgnexpr)),
  577.    sublevels_up);
  578. break;
  579. case T_Var:
  580. {
  581. int this_varno = (int) ((Var *) node)->varno;
  582. int this_varlevelsup = (int) ((Var *) node)->varlevelsup;
  583. Node    *n;
  584. if (this_varno == info->new_varno &&
  585. this_varlevelsup == sublevels_up)
  586. {
  587. n = FindMatchingNew(targetlist,
  588. ((Var *) node)->varattno);
  589. if (n == NULL)
  590. {
  591. if (info->event == CMD_UPDATE)
  592. {
  593. *nodePtr = n = copyObject(node);
  594. ((Var *) n)->varno = info->current_varno;
  595. ((Var *) n)->varnoold = info->current_varno;
  596. }
  597. else
  598. *nodePtr = make_null(((Var *) node)->vartype);
  599. }
  600. else
  601. {
  602. *nodePtr = copyObject(n);
  603. ((Var *) *nodePtr)->varlevelsup = this_varlevelsup;
  604. }
  605. }
  606. break;
  607. }
  608. case T_List:
  609. {
  610. List    *l;
  611. foreach(l, (List *) node)
  612. ResolveNew(info, targetlist, (Node **) &(lfirst(l)),
  613.    sublevels_up);
  614. break;
  615. }
  616. case T_SubLink:
  617. {
  618. SubLink    *sublink = (SubLink *) node;
  619. Query    *query = (Query *) sublink->subselect;
  620. ResolveNew(info, targetlist, (Node **) &(query->qual), sublevels_up + 1);
  621. }
  622. break;
  623. case T_GroupClause:
  624. break;
  625. default:
  626. /* ignore the others */
  627. break;
  628. }
  629. }
  630. void
  631. FixNew(RewriteInfo *info, Query *parsetree)
  632. {
  633. ResolveNew(info, parsetree->targetList,
  634.    (Node **) &(info->rule_action->targetList), 0);
  635. ResolveNew(info, parsetree->targetList,
  636.    (Node **) &info->rule_action->qual, 0);
  637. ResolveNew(info, parsetree->targetList,
  638.    (Node **) &(info->rule_action->groupClause), 0);
  639. }
  640. static void
  641. nodeHandleRIRAttributeRule(Node **nodePtr,
  642.    List *rtable,
  643.    List *targetlist,
  644.    int rt_index,
  645.    int attr_num,
  646.    int *modified,
  647.    int *badsql,
  648.    int sublevels_up)
  649. {
  650. Node    *node = *nodePtr;
  651. if (node == NULL)
  652. return;
  653. switch (nodeTag(node))
  654. {
  655. case T_TargetEntry:
  656. {
  657. TargetEntry *tle = (TargetEntry *) node;
  658. nodeHandleRIRAttributeRule(&tle->expr, rtable, targetlist,
  659. rt_index, attr_num, modified, badsql,
  660.    sublevels_up);
  661. }
  662. break;
  663. case T_Aggref:
  664. {
  665. Aggref    *aggref = (Aggref *) node;
  666. nodeHandleRIRAttributeRule(&aggref->target, rtable, targetlist,
  667. rt_index, attr_num, modified, badsql,
  668.    sublevels_up);
  669. }
  670. break;
  671. case T_Expr:
  672. {
  673. Expr    *expr = (Expr *) node;
  674. nodeHandleRIRAttributeRule((Node **) (&(expr->args)), rtable,
  675.    targetlist, rt_index, attr_num,
  676.    modified, badsql,
  677.    sublevels_up);
  678. }
  679. break;
  680. case T_Iter:
  681. {
  682. Iter    *iter = (Iter *) node;
  683. nodeHandleRIRAttributeRule((Node **) (&(iter->iterexpr)), rtable,
  684.    targetlist, rt_index, attr_num,
  685.    modified, badsql,
  686.    sublevels_up);
  687. }
  688. break;
  689. case T_ArrayRef:
  690. {
  691. ArrayRef   *ref = (ArrayRef *) node;
  692. nodeHandleRIRAttributeRule((Node **) (&(ref->refupperindexpr)), rtable,
  693.    targetlist, rt_index, attr_num,
  694.    modified, badsql,
  695.    sublevels_up);
  696. nodeHandleRIRAttributeRule((Node **) (&(ref->reflowerindexpr)), rtable,
  697.    targetlist, rt_index, attr_num,
  698.    modified, badsql,
  699.    sublevels_up);
  700. nodeHandleRIRAttributeRule((Node **) (&(ref->refexpr)), rtable,
  701.    targetlist, rt_index, attr_num,
  702.    modified, badsql,
  703.    sublevels_up);
  704. nodeHandleRIRAttributeRule((Node **) (&(ref->refassgnexpr)), rtable,
  705.    targetlist, rt_index, attr_num,
  706.    modified, badsql,
  707.    sublevels_up);
  708. }
  709. break;
  710. case T_Var:
  711. {
  712. int this_varno = ((Var *) node)->varno;
  713. int this_varattno = ((Var *) node)->varattno;
  714. int this_varlevelsup = ((Var *) node)->varlevelsup;
  715. if (this_varno == rt_index &&
  716. this_varattno == attr_num &&
  717. this_varlevelsup == sublevels_up)
  718. {
  719. if (((Var *) node)->vartype == 32)
  720. { /* HACK */
  721. *nodePtr = make_null(((Var *) node)->vartype);
  722. *modified = TRUE;
  723. *badsql = TRUE;
  724. break;
  725. }
  726. else
  727. {
  728. NameData name_to_look_for;
  729. name_to_look_for.data[0] = '';
  730. namestrcpy(&name_to_look_for,
  731. (char *) get_attname(getrelid(this_varno,
  732.   rtable),
  733.  attr_num));
  734. if (name_to_look_for.data[0])
  735. {
  736. Node    *n;
  737. n = FindMatchingTLEntry(targetlist, (char *) &name_to_look_for);
  738. if (n == NULL)
  739. *nodePtr = make_null(((Var *) node)->vartype);
  740. else
  741. *nodePtr = n;
  742. *modified = TRUE;
  743. }
  744. }
  745. }
  746. }
  747. break;
  748. case T_List:
  749. {
  750. List    *i;
  751. foreach(i, (List *) node)
  752. {
  753. nodeHandleRIRAttributeRule((Node **) (&(lfirst(i))), rtable,
  754.   targetlist, rt_index, attr_num,
  755.  modified, badsql, sublevels_up);
  756. }
  757. }
  758. break;
  759. case T_SubLink:
  760. {
  761. SubLink    *sublink = (SubLink *) node;
  762. Query    *query = (Query *) sublink->subselect;
  763. nodeHandleRIRAttributeRule((Node **) &(query->qual), rtable, targetlist,
  764. rt_index, attr_num, modified, badsql,
  765.    sublevels_up + 1);
  766. }
  767. break;
  768. default:
  769. /* ignore the others */
  770. break;
  771. }
  772. }
  773. /*
  774.  * Handles 'on retrieve to relation.attribute
  775.  * do instead retrieve (attribute = expression) w/qual'
  776.  */
  777. void
  778. HandleRIRAttributeRule(Query *parsetree,
  779.    List *rtable,
  780.    List *targetlist,
  781.    int rt_index,
  782.    int attr_num,
  783.    int *modified,
  784.    int *badsql)
  785. {
  786. nodeHandleRIRAttributeRule((Node **) (&(parsetree->targetList)), rtable,
  787.    targetlist, rt_index, attr_num,
  788.    modified, badsql, 0);
  789. nodeHandleRIRAttributeRule(&parsetree->qual, rtable, targetlist,
  790.    rt_index, attr_num, modified, badsql, 0);
  791. }
  792. #ifdef NOT_USED
  793. static void
  794. nodeHandleViewRule(Node **nodePtr,
  795.    List *rtable,
  796.    List *targetlist,
  797.    int rt_index,
  798.    int *modified,
  799.    int sublevels_up)
  800. {
  801. Node    *node = *nodePtr;
  802. if (node == NULL)
  803. return;
  804. switch (nodeTag(node))
  805. {
  806. case T_TargetEntry:
  807. {
  808. TargetEntry *tle = (TargetEntry *) node;
  809. nodeHandleViewRule(&(tle->expr), rtable, targetlist,
  810.    rt_index, modified, sublevels_up);
  811. }
  812. break;
  813. case T_Aggref:
  814. {
  815. Aggref    *aggref = (Aggref *) node;
  816. nodeHandleViewRule(&(aggref->target), rtable, targetlist,
  817.    rt_index, modified, sublevels_up);
  818. }
  819. break;
  820. /*
  821.  * This has to be done to make queries using groupclauses work
  822.  * on views
  823.  */
  824. case T_GroupClause:
  825. {
  826. GroupClause *group = (GroupClause *) node;
  827. nodeHandleViewRule((Node **) (&(group->entry)), rtable, targetlist,
  828.    rt_index, modified, sublevels_up);
  829. }
  830. break;
  831. case T_Expr:
  832. {
  833. Expr    *expr = (Expr *) node;
  834. nodeHandleViewRule((Node **) (&(expr->args)),
  835.    rtable, targetlist,
  836.    rt_index, modified, sublevels_up);
  837. }
  838. break;
  839. case T_Iter:
  840. {
  841. Iter    *iter = (Iter *) node;
  842. nodeHandleViewRule((Node **) (&(iter->iterexpr)),
  843.    rtable, targetlist,
  844.    rt_index, modified, sublevels_up);
  845. }
  846. break;
  847. case T_ArrayRef:
  848. {
  849. ArrayRef   *ref = (ArrayRef *) node;
  850. nodeHandleViewRule((Node **) (&(ref->refupperindexpr)),
  851.    rtable, targetlist,
  852.    rt_index, modified, sublevels_up);
  853. nodeHandleViewRule((Node **) (&(ref->reflowerindexpr)),
  854.    rtable, targetlist,
  855.    rt_index, modified, sublevels_up);
  856. nodeHandleViewRule((Node **) (&(ref->refexpr)),
  857.    rtable, targetlist,
  858.    rt_index, modified, sublevels_up);
  859. nodeHandleViewRule((Node **) (&(ref->refassgnexpr)),
  860.    rtable, targetlist,
  861.    rt_index, modified, sublevels_up);
  862. }
  863. break;
  864. case T_Var:
  865. {
  866. Var    *var = (Var *) node;
  867. int this_varno = var->varno;
  868. int this_varlevelsup = var->varlevelsup;
  869. Node    *n;
  870. if (this_varno == rt_index &&
  871. this_varlevelsup == sublevels_up)
  872. {
  873. n = FindMatchingTLEntry(targetlist,
  874.  get_attname(getrelid(this_varno,
  875.   rtable),
  876.  var->varattno));
  877. if (n == NULL)
  878. *nodePtr = make_null(((Var *) node)->vartype);
  879. else
  880. {
  881. /*
  882.  * This is a hack: The varlevelsup of the orignal
  883.  * variable and the new one should be the same.
  884.  * Normally we adapt the node by changing a
  885.  * pointer to point to a var contained in
  886.  * 'targetlist'. In the targetlist all
  887.  * varlevelsups are 0 so if we want to change it
  888.  * to the original value we have to copy the node
  889.  * before! (Maybe this will cause troubles with
  890.  * some sophisticated queries on views?)
  891.  */
  892. if (this_varlevelsup > 0)
  893. *nodePtr = copyObject(n);
  894. else
  895. *nodePtr = n;
  896. if (nodeTag(nodePtr) == T_Var)
  897. ((Var *) *nodePtr)->varlevelsup = this_varlevelsup;
  898. else
  899. nodeHandleViewRule(&n, rtable, targetlist,
  900.    rt_index, modified, sublevels_up);
  901. }
  902. *modified = TRUE;
  903. }
  904. break;
  905. }
  906. case T_List:
  907. {
  908. List    *l;
  909. foreach(l, (List *) node)
  910. {
  911. nodeHandleViewRule((Node **) (&(lfirst(l))),
  912.    rtable, targetlist,
  913.    rt_index, modified, sublevels_up);
  914. }
  915. }
  916. break;
  917. case T_SubLink:
  918. {
  919. SubLink    *sublink = (SubLink *) node;
  920. Query    *query = (Query *) sublink->subselect;
  921. List    *tmp_lefthand,
  922.    *tmp_oper;
  923. nodeHandleViewRule((Node **) &(query->qual), rtable, targetlist,
  924.    rt_index, modified, sublevels_up + 1);
  925. /***S*H*D***/
  926. nodeHandleViewRule((Node **) &(query->havingQual), rtable, targetlist,
  927.    rt_index, modified, sublevels_up + 1);
  928. nodeHandleViewRule((Node **) &(query->targetList), rtable, targetlist,
  929.    rt_index, modified, sublevels_up + 1);
  930. /*
  931.  * We also have to adapt the variables used in
  932.  * sublink->lefthand and sublink->oper
  933.  */
  934. nodeHandleViewRule((Node **) &(sublink->lefthand), rtable,
  935.    targetlist, rt_index, modified, sublevels_up);
  936. /*
  937.  * Make sure the first argument of sublink->oper points to
  938.  * the same var as sublink->lefthand does otherwise we
  939.  * will run into troubles using aggregates (aggno will not
  940.  * be set correctly
  941.  */
  942. pfree(lfirst(((Expr *) lfirst(sublink->oper))->args));
  943. lfirst(((Expr *) lfirst(sublink->oper))->args) =
  944. lfirst(sublink->lefthand);
  945. /***S*I***/
  946. /* INTERSECT want's this - Jan */
  947. /*
  948.  * tmp_lefthand = sublink->lefthand; foreach(tmp_oper,
  949.  * sublink->oper) { lfirst(((Expr *)
  950.  * lfirst(tmp_oper))->args) = lfirst(tmp_lefthand);
  951.  * tmp_lefthand = lnext(tmp_lefthand); }
  952.  */
  953. }
  954. break;
  955. default:
  956. /* ignore the others */
  957. break;
  958. }
  959. }
  960. void
  961. HandleViewRule(Query *parsetree,
  962.    List *rtable,
  963.    List *targetlist,
  964.    int rt_index,
  965.    int *modified)
  966. {
  967. nodeHandleViewRule(&parsetree->qual, rtable, targetlist, rt_index,
  968.    modified, 0);
  969. nodeHandleViewRule((Node **) (&(parsetree->targetList)), rtable, targetlist,
  970.    rt_index, modified, 0);
  971. /*
  972.  * The variables in the havingQual and groupClause also have to be
  973.  * adapted
  974.  */
  975. nodeHandleViewRule(&parsetree->havingQual, rtable, targetlist, rt_index,
  976.    modified, 0);
  977. nodeHandleViewRule((Node **) (&(parsetree->groupClause)), rtable, targetlist, rt_index,
  978.    modified, 0);
  979. }
  980. #endif