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

数据库系统

开发平台:

Unix_Linux

  1. /*-------------------------------------------------------------------------
  2.  *
  3.  * rewriteHandler.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/rewriteHandler.c,v 1.48 1999/07/11 17:54:30 tgl Exp $
  10.  *
  11.  *-------------------------------------------------------------------------
  12.  */
  13. #include <string.h>
  14. #include "postgres.h"
  15. #include "miscadmin.h"
  16. #include "utils/palloc.h"
  17. #include "utils/elog.h"
  18. #include "utils/rel.h"
  19. #include "nodes/pg_list.h"
  20. #include "nodes/primnodes.h"
  21. #include "nodes/relation.h"
  22. #include "parser/parsetree.h" /* for parsetree manipulation */
  23. #include "parser/parse_relation.h"
  24. #include "nodes/parsenodes.h"
  25. /***S*I***/
  26. #include "parser/parse_node.h"
  27. #include "parser/parse_target.h"
  28. #include "parser/analyze.h"
  29. #include "optimizer/clauses.h"
  30. #include "optimizer/prep.h"
  31. #include "rewrite/rewriteSupport.h"
  32. #include "rewrite/rewriteHandler.h"
  33. #include "rewrite/rewriteManip.h"
  34. #include "rewrite/locks.h"
  35. #include "commands/creatinh.h"
  36. #include "access/heapam.h"
  37. #include "utils/lsyscache.h"
  38. #include "utils/syscache.h"
  39. #include "utils/acl.h"
  40. #include "catalog/pg_shadow.h"
  41. #include "catalog/pg_type.h"
  42. static RewriteInfo *gatherRewriteMeta(Query *parsetree,
  43.   Query *rule_action,
  44.   Node *rule_qual,
  45.   int rt_index,
  46.   CmdType event,
  47.   bool *instead_flag);
  48. static bool rangeTableEntry_used(Node *node, int rt_index, int sublevels_up);
  49. static bool attribute_used(Node *node, int rt_index, int attno, int sublevels_up);
  50. static void modifyAggrefUplevel(Node *node);
  51. static void modifyAggrefChangeVarnodes(Node **nodePtr, int rt_index, int new_index, int sublevels_up);
  52. static void modifyAggrefDropQual(Node **nodePtr, Node *orignode, Expr *expr);
  53. static SubLink *modifyAggrefMakeSublink(Expr *origexp, Query *parsetree);
  54. static void modifyAggrefQual(Node **nodePtr, Query *parsetree);
  55. static bool checkQueryHasAggs(Node *node);
  56. static bool checkQueryHasAggs_walker(Node *node, void *context);
  57. static bool checkQueryHasSubLink(Node *node);
  58. static bool checkQueryHasSubLink_walker(Node *node, void *context);
  59. static Query *fireRIRrules(Query *parsetree);
  60. static Query *Except_Intersect_Rewrite(Query *parsetree);
  61. static void check_targetlists_are_compatible(List *prev_target,
  62.  List *current_target);
  63. static void create_intersect_list(Node *ptr, List **intersect_list);
  64. static Node *intersect_tree_analyze(Node *tree, Node *first_select,
  65. Node *parsetree);
  66. /*
  67.  * gatherRewriteMeta -
  68.  *   Gather meta information about parsetree, and rule. Fix rule body
  69.  *   and qualifier so that they can be mixed with the parsetree and
  70.  *   maintain semantic validity
  71.  */
  72. static RewriteInfo *
  73. gatherRewriteMeta(Query *parsetree,
  74.   Query *rule_action,
  75.   Node *rule_qual,
  76.   int rt_index,
  77.   CmdType event,
  78.   bool *instead_flag)
  79. {
  80. RewriteInfo *info;
  81. int rt_length;
  82. int result_reln;
  83. info = (RewriteInfo *) palloc(sizeof(RewriteInfo));
  84. info->rt_index = rt_index;
  85. info->event = event;
  86. info->instead_flag = *instead_flag;
  87. info->rule_action = (Query *) copyObject(rule_action);
  88. info->rule_qual = (Node *) copyObject(rule_qual);
  89. if (info->rule_action == NULL)
  90. info->nothing = TRUE;
  91. else
  92. {
  93. info->nothing = FALSE;
  94. info->action = info->rule_action->commandType;
  95. info->current_varno = rt_index;
  96. info->rt = parsetree->rtable;
  97. rt_length = length(info->rt);
  98. info->rt = nconc(info->rt, copyObject(info->rule_action->rtable));
  99. info->new_varno = PRS2_NEW_VARNO + rt_length;
  100. OffsetVarNodes(info->rule_action->qual, rt_length, 0);
  101. OffsetVarNodes((Node *) info->rule_action->targetList, rt_length, 0);
  102. OffsetVarNodes(info->rule_qual, rt_length, 0);
  103. ChangeVarNodes((Node *) info->rule_action->qual,
  104.    PRS2_CURRENT_VARNO + rt_length, rt_index, 0);
  105. ChangeVarNodes((Node *) info->rule_action->targetList,
  106.    PRS2_CURRENT_VARNO + rt_length, rt_index, 0);
  107. ChangeVarNodes(info->rule_qual,
  108.    PRS2_CURRENT_VARNO + rt_length, rt_index, 0);
  109. /*
  110.  * bug here about replace CURRENT  -- sort of replace current is
  111.  * deprecated now so this code shouldn't really need to be so
  112.  * clutzy but.....
  113.  */
  114. if (info->action != CMD_SELECT)
  115. { /* i.e update XXXXX */
  116. int new_result_reln = 0;
  117. result_reln = info->rule_action->resultRelation;
  118. switch (result_reln)
  119. {
  120. case PRS2_CURRENT_VARNO:
  121. new_result_reln = rt_index;
  122. break;
  123. case PRS2_NEW_VARNO: /* XXX */
  124. default:
  125. new_result_reln = result_reln + rt_length;
  126. break;
  127. }
  128. info->rule_action->resultRelation = new_result_reln;
  129. }
  130. }
  131. return info;
  132. }
  133. /*
  134.  * rangeTableEntry_used -
  135.  * we need to process a RTE for RIR rules only if it is
  136.  * referenced somewhere in var nodes of the query.
  137.  */
  138. static bool
  139. rangeTableEntry_used(Node *node, int rt_index, int sublevels_up)
  140. {
  141. if (node == NULL)
  142. return FALSE;
  143. switch (nodeTag(node))
  144. {
  145. case T_TargetEntry:
  146. {
  147. TargetEntry *tle = (TargetEntry *) node;
  148. return rangeTableEntry_used(
  149. (Node *) (tle->expr),
  150. rt_index,
  151. sublevels_up);
  152. }
  153. break;
  154. case T_Aggref:
  155. {
  156. Aggref    *aggref = (Aggref *) node;
  157. return rangeTableEntry_used(
  158. (Node *) (aggref->target),
  159. rt_index,
  160. sublevels_up);
  161. }
  162. break;
  163. case T_GroupClause:
  164. return FALSE;
  165. case T_Expr:
  166. {
  167. Expr    *exp = (Expr *) node;
  168. return rangeTableEntry_used(
  169. (Node *) (exp->args),
  170. rt_index,
  171. sublevels_up);
  172. }
  173. break;
  174. case T_Iter:
  175. {
  176. Iter    *iter = (Iter *) node;
  177. return rangeTableEntry_used(
  178. (Node *) (iter->iterexpr),
  179. rt_index,
  180. sublevels_up);
  181. }
  182. break;
  183. case T_ArrayRef:
  184. {
  185. ArrayRef   *ref = (ArrayRef *) node;
  186. if (rangeTableEntry_used(
  187.  (Node *) (ref->refupperindexpr),
  188.  rt_index,
  189.  sublevels_up))
  190. return TRUE;
  191. if (rangeTableEntry_used(
  192.  (Node *) (ref->reflowerindexpr),
  193.  rt_index,
  194.  sublevels_up))
  195. return TRUE;
  196. if (rangeTableEntry_used(
  197.  (Node *) (ref->refexpr),
  198.  rt_index,
  199.  sublevels_up))
  200. return TRUE;
  201. if (rangeTableEntry_used(
  202.  (Node *) (ref->refassgnexpr),
  203.  rt_index,
  204.  sublevels_up))
  205. return TRUE;
  206. return FALSE;
  207. }
  208. break;
  209. case T_Var:
  210. {
  211. Var    *var = (Var *) node;
  212. if (var->varlevelsup == sublevels_up)
  213. return var->varno == rt_index;
  214. else
  215. return FALSE;
  216. }
  217. break;
  218. case T_Param:
  219. return FALSE;
  220. case T_Const:
  221. return FALSE;
  222. case T_List:
  223. {
  224. List    *l;
  225. foreach(l, (List *) node)
  226. {
  227. if (rangeTableEntry_used(
  228.  (Node *) lfirst(l),
  229.  rt_index,
  230.  sublevels_up))
  231. return TRUE;
  232. }
  233. return FALSE;
  234. }
  235. break;
  236. case T_SubLink:
  237. {
  238. SubLink    *sub = (SubLink *) node;
  239. if (rangeTableEntry_used(
  240.  (Node *) (sub->lefthand),
  241.  rt_index,
  242.  sublevels_up))
  243. return TRUE;
  244. if (rangeTableEntry_used(
  245.  (Node *) (sub->subselect),
  246.  rt_index,
  247.  sublevels_up + 1))
  248. return TRUE;
  249. return FALSE;
  250. }
  251. break;
  252. case T_CaseExpr:
  253. {
  254. CaseExpr   *exp = (CaseExpr *) node;
  255. if (rangeTableEntry_used(
  256.  (Node *) (exp->args),
  257.  rt_index,
  258.  sublevels_up))
  259. return TRUE;
  260. if (rangeTableEntry_used(
  261.  (Node *) (exp->defresult),
  262.  rt_index,
  263.  sublevels_up))
  264. return TRUE;
  265. return FALSE;
  266. }
  267. break;
  268. case T_CaseWhen:
  269. {
  270. CaseWhen   *when = (CaseWhen *) node;
  271. if (rangeTableEntry_used(
  272.  (Node *) (when->expr),
  273.  rt_index,
  274.  sublevels_up))
  275. return TRUE;
  276. if (rangeTableEntry_used(
  277.  (Node *) (when->result),
  278.  rt_index,
  279.  sublevels_up))
  280. return TRUE;
  281. return FALSE;
  282. }
  283. break;
  284. case T_Query:
  285. {
  286. Query    *qry = (Query *) node;
  287. if (rangeTableEntry_used(
  288.  (Node *) (qry->targetList),
  289.  rt_index,
  290.  sublevels_up))
  291. return TRUE;
  292. if (rangeTableEntry_used(
  293.  (Node *) (qry->qual),
  294.  rt_index,
  295.  sublevels_up))
  296. return TRUE;
  297. if (rangeTableEntry_used(
  298.  (Node *) (qry->havingQual),
  299.  rt_index,
  300.  sublevels_up))
  301. return TRUE;
  302. return FALSE;
  303. }
  304. break;
  305. default:
  306. elog(NOTICE, "unknown node tag %d in rangeTableEntry_used()", nodeTag(node));
  307. elog(NOTICE, "Node is: %s", nodeToString(node));
  308. break;
  309. }
  310. return FALSE;
  311. }
  312. /*
  313.  * attribute_used -
  314.  * Check if a specific attribute number of a RTE is used
  315.  * somewhere in the query
  316.  */
  317. static bool
  318. attribute_used(Node *node, int rt_index, int attno, int sublevels_up)
  319. {
  320. if (node == NULL)
  321. return FALSE;
  322. switch (nodeTag(node))
  323. {
  324. case T_TargetEntry:
  325. {
  326. TargetEntry *tle = (TargetEntry *) node;
  327. return attribute_used(
  328.   (Node *) (tle->expr),
  329.   rt_index,
  330.   attno,
  331.   sublevels_up);
  332. }
  333. break;
  334. case T_Aggref:
  335. {
  336. Aggref    *aggref = (Aggref *) node;
  337. return attribute_used(
  338.   (Node *) (aggref->target),
  339.   rt_index,
  340.   attno,
  341.   sublevels_up);
  342. }
  343. break;
  344. case T_GroupClause:
  345. return FALSE;
  346. case T_Expr:
  347. {
  348. Expr    *exp = (Expr *) node;
  349. return attribute_used(
  350.   (Node *) (exp->args),
  351.   rt_index,
  352.   attno,
  353.   sublevels_up);
  354. }
  355. break;
  356. case T_Iter:
  357. {
  358. Iter    *iter = (Iter *) node;
  359. return attribute_used(
  360.   (Node *) (iter->iterexpr),
  361.   rt_index,
  362.   attno,
  363.   sublevels_up);
  364. }
  365. break;
  366. case T_ArrayRef:
  367. {
  368. ArrayRef   *ref = (ArrayRef *) node;
  369. if (attribute_used(
  370.    (Node *) (ref->refupperindexpr),
  371.    rt_index,
  372.    attno,
  373.    sublevels_up))
  374. return TRUE;
  375. if (attribute_used(
  376.    (Node *) (ref->reflowerindexpr),
  377.    rt_index,
  378.    attno,
  379.    sublevels_up))
  380. return TRUE;
  381. if (attribute_used(
  382.    (Node *) (ref->refexpr),
  383.    rt_index,
  384.    attno,
  385.    sublevels_up))
  386. return TRUE;
  387. if (attribute_used(
  388.    (Node *) (ref->refassgnexpr),
  389.    rt_index,
  390.    attno,
  391.    sublevels_up))
  392. return TRUE;
  393. return FALSE;
  394. }
  395. break;
  396. case T_Var:
  397. {
  398. Var    *var = (Var *) node;
  399. if (var->varlevelsup == sublevels_up)
  400. return var->varno == rt_index;
  401. else
  402. return FALSE;
  403. }
  404. break;
  405. case T_Param:
  406. return FALSE;
  407. case T_Const:
  408. return FALSE;
  409. case T_List:
  410. {
  411. List    *l;
  412. foreach(l, (List *) node)
  413. {
  414. if (attribute_used(
  415.    (Node *) lfirst(l),
  416.    rt_index,
  417.    attno,
  418.    sublevels_up))
  419. return TRUE;
  420. }
  421. return FALSE;
  422. }
  423. break;
  424. case T_SubLink:
  425. {
  426. SubLink    *sub = (SubLink *) node;
  427. if (attribute_used(
  428.    (Node *) (sub->lefthand),
  429.    rt_index,
  430.    attno,
  431.    sublevels_up))
  432. return TRUE;
  433. if (attribute_used(
  434.    (Node *) (sub->subselect),
  435.    rt_index,
  436.    attno,
  437.    sublevels_up + 1))
  438. return TRUE;
  439. return FALSE;
  440. }
  441. break;
  442. case T_Query:
  443. {
  444. Query    *qry = (Query *) node;
  445. if (attribute_used(
  446.    (Node *) (qry->targetList),
  447.    rt_index,
  448.    attno,
  449.    sublevels_up))
  450. return TRUE;
  451. if (attribute_used(
  452.    (Node *) (qry->qual),
  453.    rt_index,
  454.    attno,
  455.    sublevels_up))
  456. return TRUE;
  457. if (attribute_used(
  458.    (Node *) (qry->havingQual),
  459.    rt_index,
  460.    attno,
  461.    sublevels_up))
  462. return TRUE;
  463. return FALSE;
  464. }
  465. break;
  466. default:
  467. elog(NOTICE, "unknown node tag %d in attribute_used()", nodeTag(node));
  468. elog(NOTICE, "Node is: %s", nodeToString(node));
  469. break;
  470. }
  471. return FALSE;
  472. }
  473. /*
  474.  * modifyAggrefUplevel -
  475.  * In the newly created sublink for an aggregate column used in
  476.  * the qualification, we must adjust the varlevelsup in all the
  477.  * var nodes.
  478.  */
  479. static void
  480. modifyAggrefUplevel(Node *node)
  481. {
  482. if (node == NULL)
  483. return;
  484. switch (nodeTag(node))
  485. {
  486. case T_TargetEntry:
  487. {
  488. TargetEntry *tle = (TargetEntry *) node;
  489. modifyAggrefUplevel(
  490. (Node *) (tle->expr));
  491. }
  492. break;
  493. case T_Aggref:
  494. {
  495. Aggref    *aggref = (Aggref *) node;
  496. modifyAggrefUplevel(
  497. (Node *) (aggref->target));
  498. }
  499. break;
  500. case T_Expr:
  501. {
  502. Expr    *exp = (Expr *) node;
  503. modifyAggrefUplevel(
  504. (Node *) (exp->args));
  505. }
  506. break;
  507. case T_Iter:
  508. {
  509. Iter    *iter = (Iter *) node;
  510. modifyAggrefUplevel(
  511. (Node *) (iter->iterexpr));
  512. }
  513. break;
  514. case T_ArrayRef:
  515. {
  516. ArrayRef   *ref = (ArrayRef *) node;
  517. modifyAggrefUplevel(
  518. (Node *) (ref->refupperindexpr));
  519. modifyAggrefUplevel(
  520. (Node *) (ref->reflowerindexpr));
  521. modifyAggrefUplevel(
  522. (Node *) (ref->refexpr));
  523. modifyAggrefUplevel(
  524. (Node *) (ref->refassgnexpr));
  525. }
  526. break;
  527. case T_Var:
  528. {
  529. Var    *var = (Var *) node;
  530. var->varlevelsup++;
  531. }
  532. break;
  533. case T_Param:
  534. break;
  535. case T_Const:
  536. break;
  537. case T_List:
  538. {
  539. List    *l;
  540. foreach(l, (List *) node)
  541. modifyAggrefUplevel(
  542. (Node *) lfirst(l));
  543. }
  544. break;
  545. case T_SubLink:
  546. {
  547. SubLink    *sub = (SubLink *) node;
  548. modifyAggrefUplevel(
  549. (Node *) (sub->lefthand));
  550. modifyAggrefUplevel(
  551. (Node *) (sub->oper));
  552. modifyAggrefUplevel(
  553. (Node *) (sub->subselect));
  554. }
  555. break;
  556. case T_Query:
  557. {
  558. Query    *qry = (Query *) node;
  559. modifyAggrefUplevel(
  560. (Node *) (qry->targetList));
  561. modifyAggrefUplevel(
  562. (Node *) (qry->qual));
  563. modifyAggrefUplevel(
  564. (Node *) (qry->havingQual));
  565. }
  566. break;
  567. default:
  568. elog(NOTICE, "unknown node tag %d in modifyAggrefUplevel()", nodeTag(node));
  569. elog(NOTICE, "Node is: %s", nodeToString(node));
  570. break;
  571. }
  572. }
  573. /*
  574.  * modifyAggrefChangeVarnodes -
  575.  * Change the var nodes in a sublink created for an aggregate column
  576.  * used in the qualification that is subject of the aggregate
  577.  * function to point to the correct local RTE.
  578.  */
  579. static void
  580. modifyAggrefChangeVarnodes(Node **nodePtr, int rt_index, int new_index, int sublevels_up)
  581. {
  582. Node    *node = *nodePtr;
  583. if (node == NULL)
  584. return;
  585. switch (nodeTag(node))
  586. {
  587. case T_TargetEntry:
  588. {
  589. TargetEntry *tle = (TargetEntry *) node;
  590. modifyAggrefChangeVarnodes(
  591.    (Node **) (&(tle->expr)),
  592.    rt_index,
  593.    new_index,
  594.    sublevels_up);
  595. }
  596. break;
  597. case T_Aggref:
  598. {
  599. Aggref    *aggref = (Aggref *) node;
  600. modifyAggrefChangeVarnodes(
  601.    (Node **) (&(aggref->target)),
  602.    rt_index,
  603.    new_index,
  604.    sublevels_up);
  605. }
  606. break;
  607. case T_GroupClause:
  608. break;
  609. case T_Expr:
  610. {
  611. Expr    *exp = (Expr *) node;
  612. modifyAggrefChangeVarnodes(
  613.    (Node **) (&(exp->args)),
  614.    rt_index,
  615.    new_index,
  616.    sublevels_up);
  617. }
  618. break;
  619. case T_Iter:
  620. {
  621. Iter    *iter = (Iter *) node;
  622. modifyAggrefChangeVarnodes(
  623.    (Node **) (&(iter->iterexpr)),
  624.    rt_index,
  625.    new_index,
  626.    sublevels_up);
  627. }
  628. break;
  629. case T_ArrayRef:
  630. {
  631. ArrayRef   *ref = (ArrayRef *) node;
  632. modifyAggrefChangeVarnodes(
  633.  (Node **) (&(ref->refupperindexpr)),
  634.    rt_index,
  635.    new_index,
  636.    sublevels_up);
  637. modifyAggrefChangeVarnodes(
  638.  (Node **) (&(ref->reflowerindexpr)),
  639.    rt_index,
  640.    new_index,
  641.    sublevels_up);
  642. modifyAggrefChangeVarnodes(
  643.    (Node **) (&(ref->refexpr)),
  644.    rt_index,
  645.    new_index,
  646.    sublevels_up);
  647. modifyAggrefChangeVarnodes(
  648. (Node **) (&(ref->refassgnexpr)),
  649.    rt_index,
  650.    new_index,
  651.    sublevels_up);
  652. }
  653. break;
  654. case T_Var:
  655. {
  656. Var    *var = (Var *) node;
  657. if (var->varlevelsup == sublevels_up &&
  658. var->varno == rt_index)
  659. {
  660. var = copyObject(var);
  661. var->varno = new_index;
  662. var->varnoold = new_index;
  663. var->varlevelsup = 0;
  664. *nodePtr = (Node *) var;
  665. }
  666. }
  667. break;
  668. case T_Param:
  669. break;
  670. case T_Const:
  671. break;
  672. case T_List:
  673. {
  674. List    *l;
  675. foreach(l, (List *) node)
  676. modifyAggrefChangeVarnodes(
  677.    (Node **) (&lfirst(l)),
  678.    rt_index,
  679.    new_index,
  680.    sublevels_up);
  681. }
  682. break;
  683. case T_SubLink:
  684. {
  685. SubLink    *sub = (SubLink *) node;
  686. modifyAggrefChangeVarnodes(
  687.    (Node **) (&(sub->lefthand)),
  688.    rt_index,
  689.    new_index,
  690.    sublevels_up);
  691. modifyAggrefChangeVarnodes(
  692.    (Node **) (&(sub->oper)),
  693.    rt_index,
  694.    new_index,
  695.    sublevels_up);
  696. modifyAggrefChangeVarnodes(
  697.    (Node **) (&(sub->subselect)),
  698.    rt_index,
  699.    new_index,
  700.    sublevels_up + 1);
  701. }
  702. break;
  703. case T_Query:
  704. {
  705. Query    *qry = (Query *) node;
  706. modifyAggrefChangeVarnodes(
  707.    (Node **) (&(qry->targetList)),
  708.    rt_index,
  709.    new_index,
  710.    sublevels_up);
  711. modifyAggrefChangeVarnodes(
  712.    (Node **) (&(qry->qual)),
  713.    rt_index,
  714.    new_index,
  715.    sublevels_up);
  716. modifyAggrefChangeVarnodes(
  717.    (Node **) (&(qry->havingQual)),
  718.    rt_index,
  719.    new_index,
  720.    sublevels_up);
  721. }
  722. break;
  723. default:
  724. elog(NOTICE, "unknown node tag %d in modifyAggrefChangeVarnodes()", nodeTag(node));
  725. elog(NOTICE, "Node is: %s", nodeToString(node));
  726. break;
  727. }
  728. }
  729. /*
  730.  * modifyAggrefDropQual -
  731.  * remove the pure aggref clase from a qualification
  732.  */
  733. static void
  734. modifyAggrefDropQual(Node **nodePtr, Node *orignode, Expr *expr)
  735. {
  736. Node    *node = *nodePtr;
  737. if (node == NULL)
  738. return;
  739. switch (nodeTag(node))
  740. {
  741. case T_Var:
  742. break;
  743. case T_Aggref:
  744. {
  745. Aggref    *aggref = (Aggref *) node;
  746. Aggref    *oaggref = (Aggref *) orignode;
  747. modifyAggrefDropQual(
  748.  (Node **) (&(aggref->target)),
  749.  (Node *) (oaggref->target),
  750.  expr);
  751. }
  752. break;
  753. case T_Param:
  754. break;
  755. case T_Const:
  756. break;
  757. case T_GroupClause:
  758. break;
  759. case T_Expr:
  760. {
  761. Expr    *this_expr = (Expr *) node;
  762. Expr    *orig_expr = (Expr *) orignode;
  763. if (orig_expr == expr)
  764. {
  765. Const    *ctrue;
  766. if (expr->typeOid != BOOLOID)
  767. elog(ERROR,
  768.  "aggregate expression in qualification isn't of type bool");
  769. ctrue = makeNode(Const);
  770. ctrue->consttype = BOOLOID;
  771. ctrue->constlen = 1;
  772. ctrue->constisnull = FALSE;
  773. ctrue->constvalue = (Datum) TRUE;
  774. ctrue->constbyval = TRUE;
  775. *nodePtr = (Node *) ctrue;
  776. }
  777. else
  778. modifyAggrefDropQual(
  779.  (Node **) (&(this_expr->args)),
  780.  (Node *) (orig_expr->args),
  781.  expr);
  782. }
  783. break;
  784. case T_Iter:
  785. {
  786. Iter    *iter = (Iter *) node;
  787. Iter    *oiter = (Iter *) orignode;
  788. modifyAggrefDropQual(
  789.  (Node **) (&(iter->iterexpr)),
  790.  (Node *) (oiter->iterexpr),
  791.  expr);
  792. }
  793. break;
  794. case T_ArrayRef:
  795. {
  796. ArrayRef   *ref = (ArrayRef *) node;
  797. ArrayRef   *oref = (ArrayRef *) orignode;
  798. modifyAggrefDropQual(
  799.  (Node **) (&(ref->refupperindexpr)),
  800.  (Node *) (oref->refupperindexpr),
  801.  expr);
  802. modifyAggrefDropQual(
  803.  (Node **) (&(ref->reflowerindexpr)),
  804.  (Node *) (oref->reflowerindexpr),
  805.  expr);
  806. modifyAggrefDropQual(
  807.  (Node **) (&(ref->refexpr)),
  808.  (Node *) (oref->refexpr),
  809.  expr);
  810. modifyAggrefDropQual(
  811.  (Node **) (&(ref->refassgnexpr)),
  812.  (Node *) (oref->refassgnexpr),
  813.  expr);
  814. }
  815. break;
  816. case T_List:
  817. {
  818. List    *l;
  819. List    *ol = (List *) orignode;
  820. int li = 0;
  821. foreach(l, (List *) node)
  822. {
  823. modifyAggrefDropQual(
  824.  (Node **) (&(lfirst(l))),
  825.  (Node *) nth(li, ol),
  826.  expr);
  827. li++;
  828. }
  829. }
  830. break;
  831. case T_SubLink:
  832. {
  833. SubLink    *sub = (SubLink *) node;
  834. SubLink    *osub = (SubLink *) orignode;
  835. modifyAggrefDropQual(
  836.  (Node **) (&(sub->subselect)),
  837.  (Node *) (osub->subselect),
  838.  expr);
  839. }
  840. break;
  841. case T_Query:
  842. {
  843. Query    *qry = (Query *) node;
  844. Query    *oqry = (Query *) orignode;
  845. modifyAggrefDropQual(
  846.  (Node **) (&(qry->qual)),
  847.  (Node *) (oqry->qual),
  848.  expr);
  849. modifyAggrefDropQual(
  850.  (Node **) (&(qry->havingQual)),
  851.  (Node *) (oqry->havingQual),
  852.  expr);
  853. }
  854. break;
  855. default:
  856. elog(NOTICE, "unknown node tag %d in modifyAggrefDropQual()", nodeTag(node));
  857. elog(NOTICE, "Node is: %s", nodeToString(node));
  858. break;
  859. }
  860. }
  861. /*
  862.  * modifyAggrefMakeSublink -
  863.  * Create a sublink node for a qualification expression that
  864.  * uses an aggregate column of a view
  865.  */
  866. static SubLink *
  867. modifyAggrefMakeSublink(Expr *origexp, Query *parsetree)
  868. {
  869. SubLink    *sublink;
  870. Query    *subquery;
  871. Node    *subqual;
  872. RangeTblEntry *rte;
  873. Aggref    *aggref;
  874. Var    *target;
  875. TargetEntry *tle;
  876. Resdom    *resdom;
  877. Expr    *exp = copyObject(origexp);
  878. if (nodeTag(nth(0, exp->args)) == T_Aggref)
  879. {
  880. if (nodeTag(nth(1, exp->args)) == T_Aggref)
  881. elog(ERROR, "rewrite: comparision of 2 aggregate columns not supported");
  882. else
  883. elog(ERROR, "rewrite: aggregate column of view must be at rigth side in qual");
  884. }
  885. aggref = (Aggref *) nth(1, exp->args);
  886. target = (Var *) (aggref->target);
  887. rte = (RangeTblEntry *) nth(target->varno - 1, parsetree->rtable);
  888. tle = makeNode(TargetEntry);
  889. resdom = makeNode(Resdom);
  890. aggref->usenulls = TRUE;
  891. resdom->resno = 1;
  892. resdom->restype = ((Oper *) (exp->oper))->opresulttype;
  893. resdom->restypmod = -1;
  894. resdom->resname = pstrdup("<noname>");
  895. resdom->reskey = 0;
  896. resdom->reskeyop = 0;
  897. resdom->resjunk = false;
  898. tle->resdom = resdom;
  899. tle->expr = (Node *) aggref;
  900. subqual = copyObject(parsetree->qual);
  901. modifyAggrefDropQual((Node **) &subqual, (Node *) parsetree->qual, origexp);
  902. sublink = makeNode(SubLink);
  903. sublink->subLinkType = EXPR_SUBLINK;
  904. sublink->useor = FALSE;
  905. sublink->lefthand = lappend(NIL, copyObject(lfirst(exp->args)));
  906. sublink->oper = lappend(NIL, copyObject(exp));
  907. sublink->subselect = NULL;
  908. subquery = makeNode(Query);
  909. sublink->subselect = (Node *) subquery;
  910. subquery->commandType = CMD_SELECT;
  911. subquery->utilityStmt = NULL;
  912. subquery->resultRelation = 0;
  913. subquery->into = NULL;
  914. subquery->isPortal = FALSE;
  915. subquery->isBinary = FALSE;
  916. subquery->isTemp = FALSE;
  917. subquery->unionall = FALSE;
  918. subquery->uniqueFlag = NULL;
  919. subquery->sortClause = NULL;
  920. subquery->rtable = lappend(NIL, rte);
  921. subquery->targetList = lappend(NIL, tle);
  922. subquery->qual = subqual;
  923. subquery->groupClause = NIL;
  924. subquery->havingQual = NULL;
  925. subquery->hasAggs = TRUE;
  926. subquery->hasSubLinks = FALSE;
  927. subquery->unionClause = NULL;
  928. modifyAggrefUplevel((Node *) sublink);
  929. modifyAggrefChangeVarnodes((Node **) &(sublink->lefthand), target->varno,
  930.    1, target->varlevelsup);
  931. modifyAggrefChangeVarnodes((Node **) &(sublink->oper), target->varno,
  932.    1, target->varlevelsup);
  933. modifyAggrefChangeVarnodes((Node **) &(sublink->subselect), target->varno,
  934.    1, target->varlevelsup);
  935. return sublink;
  936. }
  937. /*
  938.  * modifyAggrefQual -
  939.  * Search for qualification expressions that contain aggregate
  940.  * functions and substiture them by sublinks. These expressions
  941.  * originally come from qualifications that use aggregate columns
  942.  * of a view.
  943.  */
  944. static void
  945. modifyAggrefQual(Node **nodePtr, Query *parsetree)
  946. {
  947. Node    *node = *nodePtr;
  948. if (node == NULL)
  949. return;
  950. switch (nodeTag(node))
  951. {
  952. case T_Var:
  953. break;
  954. case T_Param:
  955. break;
  956. case T_Const:
  957. break;
  958. case T_GroupClause:
  959. break;
  960. case T_Expr:
  961. {
  962. Expr    *exp = (Expr *) node;
  963. SubLink    *sub;
  964. if (length(exp->args) != 2)
  965. {
  966. modifyAggrefQual(
  967.  (Node **) (&(exp->args)),
  968.  parsetree);
  969. break;
  970. }
  971. if (nodeTag(nth(0, exp->args)) != T_Aggref &&
  972. nodeTag(nth(1, exp->args)) != T_Aggref)
  973. {
  974. modifyAggrefQual(
  975.  (Node **) (&(exp->args)),
  976.  parsetree);
  977. break;
  978. }
  979. sub = modifyAggrefMakeSublink(exp,
  980.   parsetree);
  981. *nodePtr = (Node *) sub;
  982. parsetree->hasSubLinks = TRUE;
  983. }
  984. break;
  985. case T_CaseExpr:
  986. {
  987. /*
  988.  * We're calling recursively, and this routine knows how
  989.  * to handle lists so let it do the work to handle the
  990.  * WHEN clauses...
  991.  */
  992. modifyAggrefQual(
  993.  (Node **) (&(((CaseExpr *) node)->args)),
  994.  parsetree);
  995. modifyAggrefQual(
  996.    (Node **) (&(((CaseExpr *) node)->defresult)),
  997.  parsetree);
  998. }
  999. break;
  1000. case T_CaseWhen:
  1001. {
  1002. modifyAggrefQual(
  1003.  (Node **) (&(((CaseWhen *) node)->expr)),
  1004.  parsetree);
  1005. modifyAggrefQual(
  1006.   (Node **) (&(((CaseWhen *) node)->result)),
  1007.  parsetree);
  1008. }
  1009. break;
  1010. case T_Iter:
  1011. {
  1012. Iter    *iter = (Iter *) node;
  1013. modifyAggrefQual(
  1014.  (Node **) (&(iter->iterexpr)),
  1015.  parsetree);
  1016. }
  1017. break;
  1018. case T_ArrayRef:
  1019. {
  1020. ArrayRef   *ref = (ArrayRef *) node;
  1021. modifyAggrefQual(
  1022.  (Node **) (&(ref->refupperindexpr)),
  1023.  parsetree);
  1024. modifyAggrefQual(
  1025.  (Node **) (&(ref->reflowerindexpr)),
  1026.  parsetree);
  1027. modifyAggrefQual(
  1028.  (Node **) (&(ref->refexpr)),
  1029.  parsetree);
  1030. modifyAggrefQual(
  1031.  (Node **) (&(ref->refassgnexpr)),
  1032.  parsetree);
  1033. }
  1034. break;
  1035. case T_List:
  1036. {
  1037. List    *l;
  1038. foreach(l, (List *) node)
  1039. modifyAggrefQual(
  1040.  (Node **) (&(lfirst(l))),
  1041.  parsetree);
  1042. }
  1043. break;
  1044. case T_SubLink:
  1045. {
  1046. SubLink    *sub = (SubLink *) node;
  1047. modifyAggrefQual(
  1048.  (Node **) (&(sub->subselect)),
  1049.  (Query *) (sub->subselect));
  1050. }
  1051. break;
  1052. case T_Query:
  1053. {
  1054. Query    *qry = (Query *) node;
  1055. modifyAggrefQual(
  1056.  (Node **) (&(qry->qual)),
  1057.  parsetree);
  1058. modifyAggrefQual(
  1059.  (Node **) (&(qry->havingQual)),
  1060.  parsetree);
  1061. }
  1062. break;
  1063. default:
  1064. elog(NOTICE, "unknown node tag %d in modifyAggrefQual()", nodeTag(node));
  1065. elog(NOTICE, "Node is: %s", nodeToString(node));
  1066. break;
  1067. }
  1068. }
  1069. /*
  1070.  * checkQueryHasAggs -
  1071.  * Queries marked hasAggs might not have them any longer after
  1072.  * rewriting. Check it.
  1073.  */
  1074. static bool
  1075. checkQueryHasAggs(Node *node)
  1076. {
  1077. return checkQueryHasAggs_walker(node, NULL);
  1078. }
  1079. static bool
  1080. checkQueryHasAggs_walker(Node *node, void *context)
  1081. {
  1082. if (node == NULL)
  1083. return false;
  1084. if (IsA(node, Aggref))
  1085. return true; /* abort the tree traversal and return true */
  1086. return expression_tree_walker(node, checkQueryHasAggs_walker, context);
  1087. }
  1088. /*
  1089.  * checkQueryHasSubLink -
  1090.  * Queries marked hasSubLinks might not have them any longer after
  1091.  * rewriting. Check it.
  1092.  */
  1093. static bool
  1094. checkQueryHasSubLink(Node *node)
  1095. {
  1096. return checkQueryHasSubLink_walker(node, NULL);
  1097. }
  1098. static bool
  1099. checkQueryHasSubLink_walker(Node *node, void *context)
  1100. {
  1101. if (node == NULL)
  1102. return false;
  1103. if (IsA(node, SubLink))
  1104. return true; /* abort the tree traversal and return true */
  1105. /* Note: we assume the tree has not yet been rewritten by subselect.c,
  1106.  * therefore we will find bare SubLink nodes and not SUBPLAN nodes.
  1107.  */
  1108. return expression_tree_walker(node, checkQueryHasSubLink_walker, context);
  1109. }
  1110. static Node *
  1111. FindMatchingTLEntry(List *tlist, char *e_attname)
  1112. {
  1113. List    *i;
  1114. foreach(i, tlist)
  1115. {
  1116. TargetEntry *tle = lfirst(i);
  1117. char    *resname;
  1118. resname = tle->resdom->resname;
  1119. if (!strcmp(e_attname, resname))
  1120. return (tle->expr);
  1121. }
  1122. return NULL;
  1123. }
  1124. static Node *
  1125. make_null(Oid type)
  1126. {
  1127. Const    *c = makeNode(Const);
  1128. c->consttype = type;
  1129. c->constlen = get_typlen(type);
  1130. c->constvalue = PointerGetDatum(NULL);
  1131. c->constisnull = true;
  1132. c->constbyval = get_typbyval(type);
  1133. return (Node *) c;
  1134. }
  1135. static void
  1136. apply_RIR_adjust_sublevel(Node *node, int sublevels_up)
  1137. {
  1138. if (node == NULL)
  1139. return;
  1140. switch (nodeTag(node))
  1141. {
  1142. case T_TargetEntry:
  1143. {
  1144. TargetEntry *tle = (TargetEntry *) node;
  1145. apply_RIR_adjust_sublevel(
  1146.   (Node *) (tle->expr),
  1147.   sublevels_up);
  1148. }
  1149. break;
  1150. case T_Aggref:
  1151. {
  1152. Aggref    *aggref = (Aggref *) node;
  1153. apply_RIR_adjust_sublevel(
  1154.   (Node *) (aggref->target),
  1155.   sublevels_up);
  1156. }
  1157. break;
  1158. case T_GroupClause:
  1159. break;
  1160. case T_Expr:
  1161. {
  1162. Expr    *exp = (Expr *) node;
  1163. apply_RIR_adjust_sublevel(
  1164.   (Node *) (exp->args),
  1165.   sublevels_up);
  1166. }
  1167. break;
  1168. case T_Iter:
  1169. {
  1170. Iter    *iter = (Iter *) node;
  1171. apply_RIR_adjust_sublevel(
  1172.   (Node *) (iter->iterexpr),
  1173.   sublevels_up);
  1174. }
  1175. break;
  1176. case T_ArrayRef:
  1177. {
  1178. ArrayRef   *ref = (ArrayRef *) node;
  1179. apply_RIR_adjust_sublevel(
  1180.   (Node *) (ref->refupperindexpr),
  1181.   sublevels_up);
  1182. apply_RIR_adjust_sublevel(
  1183.   (Node *) (ref->reflowerindexpr),
  1184.   sublevels_up);
  1185. apply_RIR_adjust_sublevel(
  1186.   (Node *) (ref->refexpr),
  1187.   sublevels_up);
  1188. apply_RIR_adjust_sublevel(
  1189.   (Node *) (ref->refassgnexpr),
  1190.   sublevels_up);
  1191. }
  1192. break;
  1193. case T_Var:
  1194. {
  1195. Var    *var = (Var *) node;
  1196. var->varlevelsup = sublevels_up;
  1197. }
  1198. break;
  1199. case T_Param:
  1200. break;
  1201. case T_Const:
  1202. break;
  1203. case T_List:
  1204. {
  1205. List    *l;
  1206. foreach(l, (List *) node)
  1207. {
  1208. apply_RIR_adjust_sublevel(
  1209.   (Node *) lfirst(l),
  1210.   sublevels_up);
  1211. }
  1212. }
  1213. break;
  1214. case T_CaseExpr:
  1215. {
  1216. CaseExpr   *exp = (CaseExpr *) node;
  1217. apply_RIR_adjust_sublevel(
  1218.   (Node *) (exp->args),
  1219.   sublevels_up);
  1220. apply_RIR_adjust_sublevel(
  1221.   (Node *) (exp->defresult),
  1222.   sublevels_up);
  1223. }
  1224. break;
  1225. case T_CaseWhen:
  1226. {
  1227. CaseWhen   *exp = (CaseWhen *) node;
  1228. apply_RIR_adjust_sublevel(
  1229.   (Node *) (exp->expr),
  1230.   sublevels_up);
  1231. apply_RIR_adjust_sublevel(
  1232.   (Node *) (exp->result),
  1233.   sublevels_up);
  1234. }
  1235. break;
  1236. default:
  1237. elog(NOTICE, "unknown node tag %d in attribute_used()", nodeTag(node));
  1238. elog(NOTICE, "Node is: %s", nodeToString(node));
  1239. break;
  1240. }
  1241. }
  1242. static void
  1243. apply_RIR_view(Node **nodePtr, int rt_index, RangeTblEntry *rte, List *tlist, int *modified, int sublevels_up)
  1244. {
  1245. Node    *node = *nodePtr;
  1246. if (node == NULL)
  1247. return;
  1248. switch (nodeTag(node))
  1249. {
  1250. case T_TargetEntry:
  1251. {
  1252. TargetEntry *tle = (TargetEntry *) node;
  1253. apply_RIR_view(
  1254.    (Node **) (&(tle->expr)),
  1255.    rt_index,
  1256.    rte,
  1257.    tlist,
  1258.    modified,
  1259.    sublevels_up);
  1260. }
  1261. break;
  1262. case T_Aggref:
  1263. {
  1264. Aggref    *aggref = (Aggref *) node;
  1265. apply_RIR_view(
  1266.    (Node **) (&(aggref->target)),
  1267.    rt_index,
  1268.    rte,
  1269.    tlist,
  1270.    modified,
  1271.    sublevels_up);
  1272. }
  1273. break;
  1274. case T_GroupClause:
  1275. break;
  1276. case T_Expr:
  1277. {
  1278. Expr    *exp = (Expr *) node;
  1279. apply_RIR_view(
  1280.    (Node **) (&(exp->args)),
  1281.    rt_index,
  1282.    rte,
  1283.    tlist,
  1284.    modified,
  1285.    sublevels_up);
  1286. }
  1287. break;
  1288. case T_Iter:
  1289. {
  1290. Iter    *iter = (Iter *) node;
  1291. apply_RIR_view(
  1292.    (Node **) (&(iter->iterexpr)),
  1293.    rt_index,
  1294.    rte,
  1295.    tlist,
  1296.    modified,
  1297.    sublevels_up);
  1298. }
  1299. break;
  1300. case T_ArrayRef:
  1301. {
  1302. ArrayRef   *ref = (ArrayRef *) node;
  1303. apply_RIR_view(
  1304.    (Node **) (&(ref->refupperindexpr)),
  1305.    rt_index,
  1306.    rte,
  1307.    tlist,
  1308.    modified,
  1309.    sublevels_up);
  1310. apply_RIR_view(
  1311.    (Node **) (&(ref->reflowerindexpr)),
  1312.    rt_index,
  1313.    rte,
  1314.    tlist,
  1315.    modified,
  1316.    sublevels_up);
  1317. apply_RIR_view(
  1318.    (Node **) (&(ref->refexpr)),
  1319.    rt_index,
  1320.    rte,
  1321.    tlist,
  1322.    modified,
  1323.    sublevels_up);
  1324. apply_RIR_view(
  1325.    (Node **) (&(ref->refassgnexpr)),
  1326.    rt_index,
  1327.    rte,
  1328.    tlist,
  1329.    modified,
  1330.    sublevels_up);
  1331. }
  1332. break;
  1333. case T_Var:
  1334. {
  1335. Var    *var = (Var *) node;
  1336. if (var->varlevelsup == sublevels_up &&
  1337. var->varno == rt_index)
  1338. {
  1339. Node    *exp;
  1340. if (var->varattno < 0)
  1341. elog(ERROR, "system column %s not available - %s is a view", get_attname(rte->relid, var->varattno), rte->relname);
  1342. exp = FindMatchingTLEntry(
  1343.   tlist,
  1344.   get_attname(rte->relid,
  1345.   var->varattno));
  1346. if (exp == NULL)
  1347. {
  1348. *nodePtr = make_null(var->vartype);
  1349. return;
  1350. }
  1351. exp = copyObject(exp);
  1352. if (var->varlevelsup > 0)
  1353. apply_RIR_adjust_sublevel(exp, var->varlevelsup);
  1354. *nodePtr = exp;
  1355. *modified = TRUE;
  1356. }
  1357. }
  1358. break;
  1359. case T_Param:
  1360. break;
  1361. case T_Const:
  1362. break;
  1363. case T_List:
  1364. {
  1365. List    *l;
  1366. foreach(l, (List *) node)
  1367. apply_RIR_view(
  1368.    (Node **) (&(lfirst(l))),
  1369.    rt_index,
  1370.    rte,
  1371.    tlist,
  1372.    modified,
  1373.    sublevels_up);
  1374. }
  1375. break;
  1376. case T_SubLink:
  1377. {
  1378. SubLink    *sub = (SubLink *) node;
  1379. List    *tmp_lefthand,
  1380.    *tmp_oper;
  1381. apply_RIR_view(
  1382.    (Node **) (&(sub->lefthand)),
  1383.    rt_index,
  1384.    rte,
  1385.    tlist,
  1386.    modified,
  1387.    sublevels_up);
  1388. apply_RIR_view(
  1389.    (Node **) (&(sub->subselect)),
  1390.    rt_index,
  1391.    rte,
  1392.    tlist,
  1393.    modified,
  1394.    sublevels_up + 1);
  1395. /***S*I***/
  1396. tmp_lefthand = sub->lefthand;
  1397. foreach(tmp_oper, sub->oper)
  1398. {
  1399. lfirst(((Expr *) lfirst(tmp_oper))->args) =
  1400. lfirst(tmp_lefthand);
  1401. tmp_lefthand = lnext(tmp_lefthand);
  1402. }
  1403. }
  1404. break;
  1405. case T_Query:
  1406. {
  1407. Query    *qry = (Query *) node;
  1408. apply_RIR_view(
  1409.    (Node **) (&(qry->targetList)),
  1410.    rt_index,
  1411.    rte,
  1412.    tlist,
  1413.    modified,
  1414.    sublevels_up);
  1415. apply_RIR_view(
  1416.    (Node **) (&(qry->qual)),
  1417.    rt_index,
  1418.    rte,
  1419.    tlist,
  1420.    modified,
  1421.    sublevels_up);
  1422. apply_RIR_view(
  1423.    (Node **) (&(qry->havingQual)),
  1424.    rt_index,
  1425.    rte,
  1426.    tlist,
  1427.    modified,
  1428.    sublevels_up);
  1429. }
  1430. break;
  1431. case T_CaseExpr:
  1432. {
  1433. CaseExpr   *exp = (CaseExpr *) node;
  1434. apply_RIR_view(
  1435.    (Node **) (&(exp->args)),
  1436.    rt_index,
  1437.    rte,
  1438.    tlist,
  1439.    modified,
  1440.    sublevels_up);
  1441. apply_RIR_view(
  1442.    (Node **) (&(exp->defresult)),
  1443.    rt_index,
  1444.    rte,
  1445.    tlist,
  1446.    modified,
  1447.    sublevels_up);
  1448. }
  1449. break;
  1450. case T_CaseWhen:
  1451. {
  1452. CaseWhen   *exp = (CaseWhen *) node;
  1453. apply_RIR_view(
  1454.    (Node **) (&(exp->expr)),
  1455.    rt_index,
  1456.    rte,
  1457.    tlist,
  1458.    modified,
  1459.    sublevels_up);
  1460. apply_RIR_view(
  1461.    (Node **) (&(exp->result)),
  1462.    rt_index,
  1463.    rte,
  1464.    tlist,
  1465.    modified,
  1466.    sublevels_up);
  1467. }
  1468. break;
  1469. default:
  1470. elog(NOTICE, "unknown node tag %d in apply_RIR_view()", nodeTag(node));
  1471. elog(NOTICE, "Node is: %s", nodeToString(node));
  1472. break;
  1473. }
  1474. }
  1475. extern void CheckSelectForUpdate(Query *rule_action); /* in analyze.c */
  1476. static void
  1477. ApplyRetrieveRule(Query *parsetree,
  1478.   RewriteRule *rule,
  1479.   int rt_index,
  1480.   int relation_level,
  1481.   Relation relation,
  1482.   int *modified)
  1483. {
  1484. Query    *rule_action = NULL;
  1485. Node    *rule_qual;
  1486. List    *rtable,
  1487.    *rt,
  1488.    *l;
  1489. int nothing,
  1490. rt_length;
  1491. int badsql = FALSE;
  1492. rule_qual = rule->qual;
  1493. if (rule->actions)
  1494. {
  1495. if (length(rule->actions) > 1) /* ??? because we don't handle
  1496.  * rules with more than one
  1497.  * action? -ay */
  1498. return;
  1499. rule_action = copyObject(lfirst(rule->actions));
  1500. nothing = FALSE;
  1501. }
  1502. else
  1503. nothing = TRUE;
  1504. rtable = copyObject(parsetree->rtable);
  1505. foreach(rt, rtable)
  1506. {
  1507. RangeTblEntry *rte = lfirst(rt);
  1508. /*
  1509.  * this is to prevent add_missing_vars_to_base_rels() from adding
  1510.  * a bogus entry to the new target list.
  1511.  */
  1512. rte->inFromCl = false;
  1513. }
  1514. rt_length = length(rtable);
  1515. rtable = nconc(rtable, copyObject(rule_action->rtable));
  1516. parsetree->rtable = rtable;
  1517. /* FOR UPDATE of view... */
  1518. foreach(l, parsetree->rowMark)
  1519. {
  1520. if (((RowMark *) lfirst(l))->rti == rt_index)
  1521. break;
  1522. }
  1523. if (l != NULL) /* oh, hell -:) */
  1524. {
  1525. RowMark    *newrm;
  1526. Index rti = 1;
  1527. List    *l2;
  1528. CheckSelectForUpdate(rule_action);
  1529. /*
  1530.  * We believe that rt_index is VIEW - nothing should be marked for
  1531.  * VIEW, but ACL check must be done. As for real tables of VIEW -
  1532.  * their rows must be marked, but we have to skip ACL check for
  1533.  * them.
  1534.  */
  1535. ((RowMark *) lfirst(l))->info &= ~ROW_MARK_FOR_UPDATE;
  1536. foreach(l2, rule_action->rtable)
  1537. {
  1538. /*
  1539.  * RTable of VIEW has two entries of VIEW itself - we use
  1540.  * relid to skip them.
  1541.  */
  1542. if (relation->rd_id != ((RangeTblEntry *) lfirst(l2))->relid)
  1543. {
  1544. newrm = makeNode(RowMark);
  1545. newrm->rti = rti + rt_length;
  1546. newrm->info = ROW_MARK_FOR_UPDATE;
  1547. lnext(l) = lcons(newrm, lnext(l));
  1548. l = lnext(l);
  1549. }
  1550. rti++;
  1551. }
  1552. }
  1553. rule_action->rtable = rtable;
  1554. OffsetVarNodes((Node *) rule_qual, rt_length, 0);
  1555. OffsetVarNodes((Node *) rule_action, rt_length, 0);
  1556. ChangeVarNodes((Node *) rule_qual,
  1557.    PRS2_CURRENT_VARNO + rt_length, rt_index, 0);
  1558. ChangeVarNodes((Node *) rule_action,
  1559.    PRS2_CURRENT_VARNO + rt_length, rt_index, 0);
  1560. if (relation_level)
  1561. {
  1562. apply_RIR_view((Node **) &parsetree, rt_index,
  1563.    (RangeTblEntry *) nth(rt_index - 1, rtable),
  1564.    rule_action->targetList, modified, 0);
  1565. apply_RIR_view((Node **) &rule_action, rt_index,
  1566.    (RangeTblEntry *) nth(rt_index - 1, rtable),
  1567.    rule_action->targetList, modified, 0);
  1568. }
  1569. else
  1570. {
  1571. HandleRIRAttributeRule(parsetree, rtable, rule_action->targetList,
  1572.    rt_index, rule->attrno, modified, &badsql);
  1573. }
  1574. if (*modified && !badsql)
  1575. {
  1576. AddQual(parsetree, rule_action->qual);
  1577. AddGroupClause(parsetree, rule_action->groupClause,
  1578.    rule_action->targetList);
  1579. AddHavingQual(parsetree, rule_action->havingQual);
  1580. parsetree->hasAggs = (rule_action->hasAggs || parsetree->hasAggs);
  1581. parsetree->hasSubLinks = (rule_action->hasSubLinks || parsetree->hasSubLinks);
  1582. }
  1583. }
  1584. static void
  1585. fireRIRonSubselect(Node *node)
  1586. {
  1587. if (node == NULL)
  1588. return;
  1589. switch (nodeTag(node))
  1590. {
  1591. case T_TargetEntry:
  1592. {
  1593. TargetEntry *tle = (TargetEntry *) node;
  1594. fireRIRonSubselect(
  1595.    (Node *) (tle->expr));
  1596. }
  1597. break;
  1598. case T_Aggref:
  1599. {
  1600. Aggref    *aggref = (Aggref *) node;
  1601. fireRIRonSubselect(
  1602.    (Node *) (aggref->target));
  1603. }
  1604. break;
  1605. case T_GroupClause:
  1606. break;
  1607. case T_Expr:
  1608. {
  1609. Expr    *exp = (Expr *) node;
  1610. fireRIRonSubselect(
  1611.    (Node *) (exp->args));
  1612. }
  1613. break;
  1614. case T_Iter:
  1615. {
  1616. Iter    *iter = (Iter *) node;
  1617. fireRIRonSubselect(
  1618.    (Node *) (iter->iterexpr));
  1619. }
  1620. break;
  1621. case T_ArrayRef:
  1622. {
  1623. ArrayRef   *ref = (ArrayRef *) node;
  1624. fireRIRonSubselect(
  1625.    (Node *) (ref->refupperindexpr));
  1626. fireRIRonSubselect(
  1627.    (Node *) (ref->reflowerindexpr));
  1628. fireRIRonSubselect(
  1629.    (Node *) (ref->refexpr));
  1630. fireRIRonSubselect(
  1631.    (Node *) (ref->refassgnexpr));
  1632. }
  1633. break;
  1634. case T_Var:
  1635. break;
  1636. case T_Param:
  1637. break;
  1638. case T_Const:
  1639. break;
  1640. case T_List:
  1641. {
  1642. List    *l;
  1643. foreach(l, (List *) node)
  1644. fireRIRonSubselect(
  1645.    (Node *) (lfirst(l)));
  1646. }
  1647. break;
  1648. case T_SubLink:
  1649. {
  1650. SubLink    *sub = (SubLink *) node;
  1651. Query    *qry;
  1652. fireRIRonSubselect(
  1653.    (Node *) (sub->lefthand));
  1654. qry = fireRIRrules((Query *) (sub->subselect));
  1655. fireRIRonSubselect(
  1656.    (Node *) qry);
  1657. sub->subselect = (Node *) qry;
  1658. }
  1659. break;
  1660. case T_CaseExpr:
  1661. {
  1662. CaseExpr   *exp = (CaseExpr *) node;
  1663. fireRIRonSubselect(
  1664.    (Node *) (exp->args));
  1665. fireRIRonSubselect(
  1666.    (Node *) (exp->defresult));
  1667. }
  1668. break;
  1669. case T_CaseWhen:
  1670. {
  1671. CaseWhen   *exp = (CaseWhen *) node;
  1672. fireRIRonSubselect(
  1673.    (Node *) (exp->expr));
  1674. fireRIRonSubselect(
  1675.    (Node *) (exp->result));
  1676. }
  1677. break;
  1678. case T_Query:
  1679. {
  1680. Query    *qry = (Query *) node;
  1681. fireRIRonSubselect(
  1682.    (Node *) (qry->targetList));
  1683. fireRIRonSubselect(
  1684.    (Node *) (qry->qual));
  1685. fireRIRonSubselect(
  1686.    (Node *) (qry->havingQual));
  1687. }
  1688. break;
  1689. default:
  1690. elog(NOTICE, "unknown node tag %d in fireRIRonSubselect()", nodeTag(node));
  1691. elog(NOTICE, "Node is: %s", nodeToString(node));
  1692. break;
  1693. }
  1694. }
  1695. /*
  1696.  * fireRIRrules -
  1697.  * Apply all RIR rules on each rangetable entry in a query
  1698.  */
  1699. static Query *
  1700. fireRIRrules(Query *parsetree)
  1701. {
  1702. int rt_index;
  1703. RangeTblEntry *rte;
  1704. Relation rel;
  1705. List    *locks;
  1706. RuleLock   *rules;
  1707. RewriteRule *rule;
  1708. RewriteRule RIRonly;
  1709. int modified;
  1710. int i;
  1711. List    *l;
  1712. rt_index = 0;
  1713. while (rt_index < length(parsetree->rtable))
  1714. {
  1715. ++rt_index;
  1716. rte = nth(rt_index - 1, parsetree->rtable);
  1717. if (!rangeTableEntry_used((Node *) parsetree, rt_index, 0))
  1718. {
  1719. /*
  1720.  * Unused range table entries must not be marked as coming
  1721.  * from a clause. Otherwise the planner will generate joins
  1722.  * over relations that in fact shouldn't be scanned at all and
  1723.  * the result will contain duplicates
  1724.  *
  1725.  * Jan
  1726.  *
  1727.  */
  1728. rte->inFromCl = FALSE;
  1729. continue;
  1730. }
  1731. rel = heap_openr(rte->relname);
  1732. if (rel->rd_rules == NULL)
  1733. {
  1734. heap_close(rel);
  1735. continue;
  1736. }
  1737. rules = rel->rd_rules;
  1738. locks = NIL;
  1739. /*
  1740.  * Collect the RIR rules that we must apply
  1741.  */
  1742. for (i = 0; i < rules->numLocks; i++)
  1743. {
  1744. rule = rules->rules[i];
  1745. if (rule->event != CMD_SELECT)
  1746. continue;
  1747. if (rule->attrno > 0 &&
  1748. !attribute_used((Node *) parsetree,
  1749. rt_index,
  1750. rule->attrno, 0))
  1751. continue;
  1752. locks = lappend(locks, rule);
  1753. }
  1754. /*
  1755.  * Check permissions
  1756.  */
  1757. checkLockPerms(locks, parsetree, rt_index);
  1758. /*
  1759.  * Now apply them
  1760.  */
  1761. foreach(l, locks)
  1762. {
  1763. rule = lfirst(l);
  1764. RIRonly.event = rule->event;
  1765. RIRonly.attrno = rule->attrno;
  1766. RIRonly.qual = rule->qual;
  1767. RIRonly.actions = rule->actions;
  1768. ApplyRetrieveRule(parsetree,
  1769.   &RIRonly,
  1770.   rt_index,
  1771.   RIRonly.attrno == -1,
  1772.   rel,
  1773.   &modified);
  1774. }
  1775. heap_close(rel);
  1776. }
  1777. fireRIRonSubselect((Node *) parsetree);
  1778. modifyAggrefQual((Node **) &(parsetree->qual), parsetree);
  1779. return parsetree;
  1780. }
  1781. /*
  1782.  * idea is to fire regular rules first, then qualified instead
  1783.  * rules and unqualified instead rules last. Any lemming is counted for.
  1784.  */
  1785. static List *
  1786. orderRules(List *locks)
  1787. {
  1788. List    *regular = NIL;
  1789. List    *instead_rules = NIL;
  1790. List    *instead_qualified = NIL;
  1791. List    *i;
  1792. foreach(i, locks)
  1793. {
  1794. RewriteRule *rule_lock = (RewriteRule *) lfirst(i);
  1795. if (rule_lock->isInstead)
  1796. {
  1797. if (rule_lock->qual == NULL)
  1798. instead_rules = lappend(instead_rules, rule_lock);
  1799. else
  1800. instead_qualified = lappend(instead_qualified, rule_lock);
  1801. }
  1802. else
  1803. regular = lappend(regular, rule_lock);
  1804. }
  1805. regular = nconc(regular, instead_qualified);
  1806. return nconc(regular, instead_rules);
  1807. }
  1808. static Query *
  1809. CopyAndAddQual(Query *parsetree,
  1810.    List *actions,
  1811.    Node *rule_qual,
  1812.    int rt_index,
  1813.    CmdType event)
  1814. {
  1815. Query    *new_tree = (Query *) copyObject(parsetree);
  1816. Node    *new_qual = NULL;
  1817. Query    *rule_action = NULL;
  1818. if (actions)
  1819. rule_action = lfirst(actions);
  1820. if (rule_qual != NULL)
  1821. new_qual = (Node *) copyObject(rule_qual);
  1822. if (rule_action != NULL)
  1823. {
  1824. List    *rtable;
  1825. int rt_length;
  1826. rtable = new_tree->rtable;
  1827. rt_length = length(rtable);
  1828. rtable = nconc(rtable, copyObject(rule_action->rtable));
  1829. new_tree->rtable = rtable;
  1830. OffsetVarNodes(new_qual, rt_length, 0);
  1831. ChangeVarNodes(new_qual, PRS2_CURRENT_VARNO + rt_length, rt_index, 0);
  1832. }
  1833. /* XXX -- where current doesn't work for instead nothing.... yet */
  1834. AddNotQual(new_tree, new_qual);
  1835. return new_tree;
  1836. }
  1837. /*
  1838.  * fireRules -
  1839.  *    Iterate through rule locks applying rules.
  1840.  *    All rules create their own parsetrees. Instead rules
  1841.  *    with rule qualification save the original parsetree
  1842.  *    and add their negated qualification to it. Real instead
  1843.  *    rules finally throw away the original parsetree.
  1844.  *
  1845.  *    remember: reality is for dead birds -- glass
  1846.  *
  1847.  */
  1848. static List *
  1849. fireRules(Query *parsetree,
  1850.   int rt_index,
  1851.   CmdType event,
  1852.   bool *instead_flag,
  1853.   List *locks,
  1854.   List **qual_products)
  1855. {
  1856. RewriteInfo *info;
  1857. List    *results = NIL;
  1858. List    *i;
  1859. /* choose rule to fire from list of rules */
  1860. if (locks == NIL)
  1861. return NIL;
  1862. locks = orderRules(locks); /* real instead rules last */
  1863. foreach(i, locks)
  1864. {
  1865. RewriteRule *rule_lock = (RewriteRule *) lfirst(i);
  1866. Node    *qual,
  1867.    *event_qual;
  1868. List    *actions;
  1869. List    *r;
  1870. /*
  1871.  * Instead rules change the resultRelation of the query. So the
  1872.  * permission checks on the initial resultRelation would never be
  1873.  * done (this is normally done in the executor deep down). So we
  1874.  * must do it here. The result relations resulting from earlier
  1875.  * rewrites are already checked against the rules eventrelation
  1876.  * owner (during matchLocks) and have the skipAcl flag set.
  1877.  */
  1878. if (rule_lock->isInstead &&
  1879. parsetree->commandType != CMD_SELECT)
  1880. {
  1881. RangeTblEntry *rte;
  1882. int32 acl_rc;
  1883. int32 reqperm;
  1884. switch (parsetree->commandType)
  1885. {
  1886. case CMD_INSERT:
  1887. reqperm = ACL_AP;
  1888. break;
  1889. default:
  1890. reqperm = ACL_WR;
  1891. break;
  1892. }
  1893. rte = (RangeTblEntry *) nth(parsetree->resultRelation - 1,
  1894. parsetree->rtable);
  1895. if (!rte->skipAcl)
  1896. {
  1897. acl_rc = pg_aclcheck(rte->relname,
  1898.  GetPgUserName(), reqperm);
  1899. if (acl_rc != ACLCHECK_OK)
  1900. {
  1901. elog(ERROR, "%s: %s",
  1902.  rte->relname,
  1903.  aclcheck_error_strings[acl_rc]);
  1904. }
  1905. }
  1906. }
  1907. /* multiple rule action time */
  1908. *instead_flag = rule_lock->isInstead;
  1909. event_qual = rule_lock->qual;
  1910. actions = rule_lock->actions;
  1911. if (event_qual != NULL && *instead_flag)
  1912. {
  1913. Query    *qual_product;
  1914. RewriteInfo qual_info;
  1915. /* ----------
  1916.  * If there are instead rules with qualifications,
  1917.  * the original query is still performed. But all
  1918.  * the negated rule qualifications of the instead
  1919.  * rules are added so it does it's actions only
  1920.  * in cases where the rule quals of all instead
  1921.  * rules are false. Think of it as the default
  1922.  * action in a case. We save this in *qual_products
  1923.  * so deepRewriteQuery() can add it to the query
  1924.  * list after we mangled it up enough.
  1925.  * ----------
  1926.  */
  1927. if (*qual_products == NIL)
  1928. qual_product = parsetree;
  1929. else
  1930. qual_product = (Query *) nth(0, *qual_products);
  1931. qual_info.event = qual_product->commandType;
  1932. qual_info.new_varno = length(qual_product->rtable) + 2;
  1933. qual_product = CopyAndAddQual(qual_product,
  1934.   actions,
  1935.   event_qual,
  1936.   rt_index,
  1937.   event);
  1938. qual_info.rule_action = qual_product;
  1939. if (event == CMD_INSERT || event == CMD_UPDATE)
  1940. FixNew(&qual_info, qual_product);
  1941. *qual_products = lappend(NIL, qual_product);
  1942. }
  1943. foreach(r, actions)
  1944. {
  1945. Query    *rule_action = lfirst(r);
  1946. Node    *rule_qual = copyObject(event_qual);
  1947. if (rule_action->commandType == CMD_NOTHING)
  1948. continue;
  1949. /*--------------------------------------------------
  1950.  * We copy the qualifications of the parsetree
  1951.  * to the action and vice versa. So force
  1952.  * hasSubLinks if one of them has it.
  1953.  *
  1954.  * As of 6.4 only parsetree qualifications can
  1955.  * have sublinks. If this changes, we must make
  1956.  * this a node lookup at the end of rewriting.
  1957.  *
  1958.  * Jan
  1959.  *--------------------------------------------------
  1960.  */
  1961. if (parsetree->hasSubLinks && !rule_action->hasSubLinks)
  1962. {
  1963. rule_action = copyObject(rule_action);
  1964. rule_action->hasSubLinks = TRUE;
  1965. }
  1966. if (!parsetree->hasSubLinks && rule_action->hasSubLinks)
  1967. parsetree->hasSubLinks = TRUE;
  1968. /*--------------------------------------------------
  1969.  * Step 1:
  1970.  *   Rewrite current.attribute or current to tuple variable
  1971.  *   this appears to be done in parser?
  1972.  *--------------------------------------------------
  1973.  */
  1974. info = gatherRewriteMeta(parsetree, rule_action, rule_qual,
  1975.  rt_index, event, instead_flag);
  1976. /* handle escapable cases, or those handled by other code */
  1977. if (info->nothing)
  1978. {
  1979. if (*instead_flag)
  1980. return NIL;
  1981. else
  1982. continue;
  1983. }
  1984. if (info->action == info->event &&
  1985. info->event == CMD_SELECT)
  1986. continue;
  1987. /*
  1988.  * Event Qualification forces copying of parsetree and
  1989.  * splitting into two queries one w/rule_qual, one w/NOT
  1990.  * rule_qual. Also add user query qual onto rule action
  1991.  */
  1992. qual = parsetree->qual;
  1993. AddQual(info->rule_action, qual);
  1994. if (info->rule_qual != NULL)
  1995. AddQual(info->rule_action, info->rule_qual);
  1996. /*--------------------------------------------------
  1997.  * Step 2:
  1998.  *   Rewrite new.attribute w/ right hand side of target-list
  1999.  *   entry for appropriate field name in insert/update
  2000.  *--------------------------------------------------
  2001.  */
  2002. if ((info->event == CMD_INSERT) || (info->event == CMD_UPDATE))
  2003. FixNew(info, parsetree);
  2004. /*--------------------------------------------------
  2005.  * Step 3:
  2006.  *   rewriting due to retrieve rules
  2007.  *--------------------------------------------------
  2008.  */
  2009. info->rule_action->rtable = info->rt;
  2010. /*
  2011.  * ProcessRetrieveQuery(info->rule_action, info->rt,
  2012.  * &orig_instead_flag, TRUE);
  2013.  */
  2014. /*--------------------------------------------------
  2015.  * Step 4
  2016.  *   Simplify? hey, no algorithm for simplification... let
  2017.  *   the planner do it.
  2018.  *--------------------------------------------------
  2019.  */
  2020. results = lappend(results, info->rule_action);
  2021. pfree(info);
  2022. }
  2023. /* ----------
  2024.  * If this was an unqualified instead rule,
  2025.  * throw away an eventually saved 'default' parsetree
  2026.  * ----------
  2027.  */
  2028. if (event_qual == NULL && *instead_flag)
  2029. *qual_products = NIL;
  2030. }
  2031. return results;
  2032. }
  2033. static List *
  2034. RewriteQuery(Query *parsetree, bool *instead_flag, List **qual_products)
  2035. {
  2036. CmdType event;
  2037. List    *product_queries = NIL;
  2038. int result_relation = 0;
  2039. RangeTblEntry *rt_entry;
  2040. Relation rt_entry_relation = NULL;
  2041. RuleLock   *rt_entry_locks = NULL;
  2042. Assert(parsetree != NULL);
  2043. event = parsetree->commandType;
  2044. /*
  2045.  * SELECT rules are handled later when we have all the queries that
  2046.  * should get executed
  2047.  */
  2048. if (event == CMD_SELECT)
  2049. return NIL;
  2050. /*
  2051.  * Utilities aren't rewritten at all - why is this here?
  2052.  */
  2053. if (event == CMD_UTILITY)
  2054. return NIL;
  2055. /*
  2056.  * only for a delete may the targetlist be NULL
  2057.  */
  2058. if (event != CMD_DELETE)
  2059. Assert(parsetree->targetList != NULL);
  2060. result_relation = parsetree->resultRelation;
  2061. /*
  2062.  * the statement is an update, insert or delete - fire rules on it.
  2063.  */
  2064. rt_entry = rt_fetch(result_relation, parsetree->rtable);
  2065. rt_entry_relation = heap_openr(rt_entry->relname);
  2066. rt_entry_locks = rt_entry_relation->rd_rules;
  2067. heap_close(rt_entry_relation);
  2068. if (rt_entry_locks != NULL)
  2069. {
  2070. List    *locks = matchLocks(event, rt_entry_locks, result_relation, parsetree);
  2071. product_queries = fireRules(parsetree,
  2072. result_relation,
  2073. event,
  2074. instead_flag,
  2075. locks,
  2076. qual_products);
  2077. }
  2078. return product_queries;
  2079. }
  2080. /*
  2081.  * to avoid infinite recursion, we restrict the number of times a query
  2082.  * can be rewritten. Detecting cycles is left for the reader as an excercise.
  2083.  */
  2084. #ifndef REWRITE_INVOKE_MAX
  2085. #define REWRITE_INVOKE_MAX 10
  2086. #endif
  2087. static int numQueryRewriteInvoked = 0;
  2088. /*
  2089.  * deepRewriteQuery -
  2090.  *   rewrites the query and apply the rules again on the queries rewritten
  2091.  */
  2092. static List *
  2093. deepRewriteQuery(Query *parsetree)
  2094. {
  2095. List    *n;
  2096. List    *rewritten = NIL;
  2097. List    *result = NIL;
  2098. bool instead;
  2099. List    *qual_products = NIL;
  2100. if (++numQueryRewriteInvoked > REWRITE_INVOKE_MAX)
  2101. {
  2102. elog(ERROR, "query rewritten %d times, may contain cycles",
  2103.  numQueryRewriteInvoked - 1);
  2104. }
  2105. instead = FALSE;
  2106. result = RewriteQuery(parsetree, &instead, &qual_products);
  2107. foreach(n, result)
  2108. {
  2109. Query    *pt = lfirst(n);
  2110. List    *newstuff = NIL;
  2111. newstuff = deepRewriteQuery(pt);
  2112. if (newstuff != NIL)
  2113. rewritten = nconc(rewritten, newstuff);
  2114. }
  2115. /* ----------
  2116.  * qual_products are the original query with the negated
  2117.  * rule qualification of an instead rule
  2118.  * ----------
  2119.  */
  2120. if (qual_products != NIL)
  2121. rewritten = nconc(rewritten, qual_products);
  2122. /* ----------
  2123.  * The original query is appended last if not instead
  2124.  * because update and delete rule actions might not do
  2125.  * anything if they are invoked after the update or
  2126.  * delete is performed. The command counter increment
  2127.  * between the query execution makes the deleted (and
  2128.  * maybe the updated) tuples disappear so the scans
  2129.  * for them in the rule actions cannot find them.
  2130.  * ----------
  2131.  */
  2132. if (!instead)
  2133. rewritten = lappend(rewritten, parsetree);
  2134. return rewritten;
  2135. }
  2136. /*
  2137.  * QueryOneRewrite -
  2138.  *   rewrite one query
  2139.  */
  2140. static List *
  2141. QueryRewriteOne(Query *parsetree)
  2142. {
  2143. numQueryRewriteInvoked = 0;
  2144. /*
  2145.  * take a deep breath and apply all the rewrite rules - ay
  2146.  */
  2147. return deepRewriteQuery(parsetree);
  2148. }
  2149. /* ----------
  2150.  * RewritePreprocessQuery -
  2151.  * adjust details in the parsetree, the rule system
  2152.  * depends on
  2153.  * ----------
  2154.  */
  2155. static void
  2156. RewritePreprocessQuery(Query *parsetree)
  2157. {
  2158. /* ----------
  2159.  * if the query has a resultRelation, reassign the
  2160.  * result domain numbers to the attribute numbers in the
  2161.  * target relation. FixNew() depends on it when replacing
  2162.  * *new* references in a rule action by the expressions
  2163.  * from the rewritten query.
  2164.  * resjunk targets are somewhat arbitrarily given a resno of 0;
  2165.  * this is to prevent FixNew() from matching them to var nodes.
  2166.  * ----------
  2167.  */
  2168. if (parsetree->resultRelation > 0)
  2169. {
  2170. RangeTblEntry *rte;
  2171. Relation rd;
  2172. List    *tl;
  2173. rte = (RangeTblEntry *) nth(parsetree->resultRelation - 1,
  2174. parsetree->rtable);
  2175. rd = heap_openr(rte->relname);
  2176. foreach(tl, parsetree->targetList)
  2177. {
  2178. TargetEntry *tle = (TargetEntry *) lfirst(tl);
  2179. if (! tle->resdom->resjunk)
  2180. tle->resdom->resno = attnameAttNum(rd, tle->resdom->resname);
  2181. else
  2182. tle->resdom->resno = 0;
  2183. }
  2184. heap_close(rd);
  2185. }
  2186. }
  2187. /*
  2188.  * BasicQueryRewrite -
  2189.  *   rewrite one query via query rewrite system, possibly returning 0
  2190.  *   or many queries
  2191.  */
  2192. static List *
  2193. BasicQueryRewrite(Query *parsetree)
  2194. {
  2195. List    *querylist;
  2196. List    *results = NIL;
  2197. List    *l;
  2198. Query    *query;
  2199. /*
  2200.  * Step 1
  2201.  *
  2202.  * There still seems something broken with the resdom numbers so we
  2203.  * reassign them first.
  2204.  */
  2205. RewritePreprocessQuery(parsetree);
  2206. /*
  2207.  * Step 2
  2208.  *
  2209.  * Apply all non-SELECT rules possibly getting 0 or many queries
  2210.  */
  2211. querylist = QueryRewriteOne(parsetree);
  2212. /*
  2213.  * Step 3
  2214.  *
  2215.  * Apply all the RIR rules on each query
  2216.  */
  2217. foreach(l, querylist)
  2218. {
  2219. query = fireRIRrules((Query *) lfirst(l));
  2220. /*
  2221.  * If the query was marked having aggregates, check if this is
  2222.  * still true after rewriting. This check must get expanded when
  2223.  * someday aggregates can appear somewhere else than in the
  2224.  * targetlist or the having qual.
  2225.  */
  2226. if (query->hasAggs)
  2227. query->hasAggs = checkQueryHasAggs((Node *) (query->targetList))
  2228. | checkQueryHasAggs((Node *) (query->havingQual));
  2229. query->hasSubLinks = checkQueryHasSubLink((Node *) (query->qual))
  2230. | checkQueryHasSubLink((Node *) (query->havingQual));
  2231. results = lappend(results, query);
  2232. }
  2233. return results;
  2234. }
  2235. /*
  2236.  * QueryRewrite -
  2237.  *   Primary entry point to the query rewriter.
  2238.  *   Rewrite one query via query rewrite system, possibly returning 0
  2239.  *   or many queries.
  2240.  *
  2241.  * NOTE: The code in QueryRewrite was formerly in pg_parse_and_plan(), and was
  2242.  * moved here so that it would be invoked during EXPLAIN.  The division of
  2243.  * labor between this routine and BasicQueryRewrite is not obviously correct
  2244.  * ... at least not to me ... tgl 5/99.
  2245.  */
  2246. List *
  2247. QueryRewrite(Query *parsetree)
  2248. {
  2249. List    *rewritten,
  2250.    *rewritten_item;
  2251. /***S*I***/
  2252. /*
  2253.  * Rewrite Union, Intersect and Except Queries to normal Union Queries
  2254.  * using IN and NOT IN subselects
  2255.  */
  2256. if (parsetree->intersectClause)
  2257. parsetree = Except_Intersect_Rewrite(parsetree);
  2258. /* Rewrite basic queries (retrieve, append, delete, replace) */
  2259. rewritten = BasicQueryRewrite(parsetree);
  2260. /*
  2261.  * Rewrite the UNIONS.
  2262.  */
  2263. foreach(rewritten_item, rewritten)
  2264. {
  2265. Query    *qry = (Query *) lfirst(rewritten_item);
  2266. List    *union_result = NIL;
  2267. List    *union_item;
  2268. foreach(union_item, qry->unionClause)
  2269. {
  2270. union_result = nconc(union_result,
  2271. BasicQueryRewrite((Query *) lfirst(union_item)));
  2272. }
  2273. qry->unionClause = union_result;
  2274. }
  2275. return rewritten;
  2276. }
  2277. /***S*I***/
  2278. /* This function takes two targetlists as arguments and checks if the
  2279.  * targetlists are compatible (i.e. both select for the same number of
  2280.  * attributes and the types are compatible */
  2281. static void
  2282. check_targetlists_are_compatible(List *prev_target, List *current_target)
  2283. {
  2284. List    *tl,
  2285.    *next_target;
  2286. int prev_len = 0,
  2287. next_len = 0;
  2288. foreach(tl, prev_target)
  2289. if (!((TargetEntry *) lfirst(tl))->resdom->resjunk)
  2290. prev_len++;
  2291. foreach(next_target, current_target)
  2292. if (!((TargetEntry *) lfirst(next_target))->resdom->resjunk)
  2293. next_len++;
  2294. if (prev_len != next_len)
  2295. elog(ERROR, "Each UNION | EXCEPT | INTERSECT query must have the same number of columns.");
  2296. foreach(next_target, current_target)
  2297. {
  2298. Oid itype;
  2299. Oid otype;
  2300. otype = ((TargetEntry *) lfirst(prev_target))->resdom->restype;
  2301. itype = ((TargetEntry *) lfirst(next_target))->resdom->restype;
  2302. /* one or both is a NULL column? then don't convert... */
  2303. if (otype == InvalidOid)
  2304. {
  2305. /* propagate a known type forward, if available */
  2306. if (itype != InvalidOid)
  2307. ((TargetEntry *) lfirst(prev_target))->resdom->restype = itype;
  2308. #ifdef NOT_USED
  2309. else
  2310. {
  2311. ((TargetEntry *) lfirst(prev_target))->resdom->restype = UNKNOWNOID;
  2312. ((TargetEntry *) lfirst(next_target))->resdom->restype = UNKNOWNOID;
  2313. }
  2314. #endif
  2315. }
  2316. else if (itype == InvalidOid)
  2317. {
  2318. }
  2319. /* they don't match in type? then convert... */
  2320. else if (itype != otype)
  2321. {
  2322. Node    *expr;
  2323. expr = ((TargetEntry *) lfirst(next_target))->expr;
  2324. expr = CoerceTargetExpr(NULL, expr, itype, otype);
  2325. if (expr == NULL)
  2326. {
  2327. elog(ERROR, "Unable to transform %s to %s"
  2328.  "ntEach UNION | EXCEPT | INTERSECT clause must have compatible target types",
  2329.  typeidTypeName(itype),
  2330.  typeidTypeName(otype));
  2331. }
  2332. ((TargetEntry *) lfirst(next_target))->expr = expr;
  2333. ((TargetEntry *) lfirst(next_target))->resdom->restype = otype;
  2334. }
  2335. /* both are UNKNOWN? then evaluate as text... */
  2336. else if (itype == UNKNOWNOID)
  2337. {
  2338. ((TargetEntry *) lfirst(next_target))->resdom->restype = TEXTOID;
  2339. ((TargetEntry *) lfirst(prev_target))->resdom->restype = TEXTOID;
  2340. }
  2341. prev_target = lnext(prev_target);
  2342. }
  2343. }
  2344. /***S*I***/
  2345. /* Rewrites UNION INTERSECT and EXCEPT queries to semantiacally equivalent
  2346.  * queries that use IN and NOT IN subselects.
  2347.  *
  2348.  * The operator tree is attached to 'intersectClause' (see rule
  2349.  * 'SelectStmt' in gram.y) of the 'parsetree' given as an
  2350.  * argument. First we remember some clauses (the sortClause, the
  2351.  * unique flag etc.)  Then we translate the operator tree to DNF
  2352.  * (disjunctive normal form) by 'cnfify'. (Note that 'cnfify' produces
  2353.  * CNF but as we exchanged ANDs with ORs in function A_Expr_to_Expr()
  2354.  * earlier we get DNF after exchanging ANDs and ORs again in the
  2355.  * result.) Now we create a new query by evaluating the new operator
  2356.  * tree which is in DNF now. For every AND we create an entry in the
  2357.  * union list and for every OR we create an IN subselect. (NOT IN
  2358.  * subselects are created for OR NOT nodes). The first entry of the
  2359.  * union list is handed back but before that the remembered clauses
  2360.  * (sortClause etc) are attached to the new top Node (Note that the
  2361.  * new top Node can differ from the parsetree given as argument because of
  2362.  * the translation to DNF. That's why we have to remember the sortClause or
  2363.  * unique flag!) */
  2364. static Query *
  2365. Except_Intersect_Rewrite(Query *parsetree)
  2366. {
  2367. SubLink    *n;
  2368. Query    *result,
  2369.    *intersect_node;
  2370. List    *elist,
  2371.    *intersect_list = NIL,
  2372.    *intersect,
  2373.    *intersectClause;
  2374. List    *union_list = NIL,
  2375.    *sortClause;
  2376. List    *left_expr,
  2377.    *right_expr,
  2378.    *resnames = NIL;
  2379. char    *op,
  2380.    *uniqueFlag,
  2381.    *into;
  2382. bool isBinary,
  2383. isPortal,
  2384. isTemp;
  2385. CmdType commandType = CMD_SELECT;
  2386. List    *rtable_insert = NIL;
  2387. List    *prev_target = NIL;
  2388. /*
  2389.  * Remember the Resnames of the given parsetree's targetlist (these
  2390.  * are the resnames of the first Select Statement of the query
  2391.  * formulated by the user and he wants the columns named by these
  2392.  * strings. The transformation to DNF can cause another Select
  2393.  * Statment to be the top one which uses other names for its columns.
  2394.  * Therefore we remeber the original names and attach them to the
  2395.  * targetlist of the new topmost Node at the end of this function
  2396.  */
  2397. foreach(elist, parsetree->targetList)
  2398. {
  2399. TargetEntry *tent = (TargetEntry *) lfirst(elist);
  2400. resnames = lappend(resnames, tent->resdom->resname);
  2401. }
  2402. /*
  2403.  * If the Statement is an INSERT INTO ... (SELECT...) statement using
  2404.  * UNIONs, INTERSECTs or EXCEPTs and the transformation to DNF makes
  2405.  * another Node to the top node we have to transform the new top node
  2406.  * to an INSERT node and the original INSERT node to a SELECT node
  2407.  */
  2408. if (parsetree->commandType == CMD_INSERT)
  2409. {
  2410. parsetree->commandType = CMD_SELECT;
  2411. commandType = CMD_INSERT;
  2412. parsetree->resultRelation = 0;
  2413. /*
  2414.  * The result relation ( = the one to insert into) has to be
  2415.  * attached to the rtable list of the new top node
  2416.  */
  2417. rtable_insert = nth(length(parsetree->rtable) - 1, parsetree->rtable);
  2418. }
  2419. /*
  2420.  * Save some items, to be able to attach them to the resulting top
  2421.  * node at the end of the function
  2422.  */
  2423. sortClause = parsetree->sortClause;
  2424. uniqueFlag = parsetree->uniqueFlag;
  2425. into = parsetree->into;
  2426. isBinary = parsetree->isBinary;
  2427. isPortal = parsetree->isPortal;
  2428. isTemp = parsetree->isTemp;
  2429. /*
  2430.  * The operator tree attached to parsetree->intersectClause is still
  2431.  * 'raw' ( = the leaf nodes are still SelectStmt nodes instead of
  2432.  * Query nodes) So step through the tree and transform the nodes using
  2433.  * parse_analyze().
  2434.  *
  2435.  * The parsetree (given as an argument to Except_Intersect_Rewrite()) has
  2436.  * already been transformed and transforming it again would cause
  2437.  * troubles.  So we give the 'raw' version (of the cooked parsetree)
  2438.  * to the function to prevent an additional transformation. Instead we
  2439.  * hand back the 'cooked' version also given as an argument to
  2440.  * intersect_tree_analyze()
  2441.  */
  2442. intersectClause =
  2443. (List *) intersect_tree_analyze((Node *) parsetree->intersectClause,
  2444.  (Node *) lfirst(parsetree->unionClause),
  2445. (Node *) parsetree);
  2446. /* intersectClause is no longer needed so set it to NIL */
  2447. parsetree->intersectClause = NIL;
  2448. /*
  2449.  * unionClause will be needed later on but the list it delivered is no
  2450.  * longer needed, so set it to NIL
  2451.  */
  2452. parsetree->unionClause = NIL;
  2453. /*
  2454.  * Transform the operator tree to DNF (remember ANDs and ORs have been
  2455.  * exchanged, that's why we get DNF by using cnfify)
  2456.  *
  2457.  * After the call, explicit ANDs are removed and all AND operands are
  2458.  * simply items in the intersectClause list
  2459.  */
  2460. intersectClause = cnfify((Expr *) intersectClause, true);
  2461. /*
  2462.  * For every entry of the intersectClause list we generate one entry
  2463.  * in the union_list
  2464.  */
  2465. foreach(intersect, intersectClause)
  2466. {
  2467. /*
  2468.  * for every OR we create an IN subselect and for every OR NOT we
  2469.  * create a NOT IN subselect, so first extract all the Select
  2470.  * Query nodes from the tree (that contains only OR or OR NOTs any
  2471.  * more because we did a transformation to DNF
  2472.  *
  2473.  * There must be at least one node that is not negated (i.e. just OR
  2474.  * and not OR NOT) and this node will be the first in the list
  2475.  * returned
  2476.  */
  2477. intersect_list = NIL;
  2478. create_intersect_list((Node *) lfirst(intersect), &intersect_list);
  2479. /*
  2480.  * This one will become the Select Query node, all other nodes are
  2481.  * transformed into subselects under this node!
  2482.  */
  2483. intersect_node = (Query *) lfirst(intersect_list);
  2484. intersect_list = lnext(intersect_list);
  2485. /*
  2486.  * Check if all Select Statements use the same number of
  2487.  * attributes and if all corresponding attributes are of the same
  2488.  * type
  2489.  */
  2490. if (prev_target)
  2491. check_targetlists_are_compatible(prev_target, intersect_node->targetList);
  2492. prev_target = intersect_node->targetList;
  2493. /* End of check for corresponding targetlists */
  2494. /*
  2495.  * Transform all nodes remaining into subselects and add them to
  2496.  * the qualifications of the Select Query node
  2497.  */
  2498. while (intersect_list != NIL)
  2499. {
  2500. n = makeNode(SubLink);
  2501. /* Here we got an OR so transform it to an IN subselect */
  2502. if (IsA(lfirst(intersect_list), Query))
  2503. {
  2504. /*
  2505.  * Check if all Select Statements use the same number of
  2506.  * attributes and if all corresponding attributes are of
  2507.  * the same type
  2508.  */
  2509. check_targetlists_are_compatible(prev_target,
  2510.  ((Query *) lfirst(intersect_list))->targetList);
  2511. /* End of check for corresponding targetlists */
  2512. n->subselect = lfirst(intersect_list);
  2513. op = "=";
  2514. n->subLinkType = ANY_SUBLINK;
  2515. n->useor = false;
  2516. }
  2517. /*
  2518.  * Here we got an OR NOT node so transform it to a NOT IN
  2519.  * subselect
  2520.  */
  2521. else
  2522. {
  2523. /*
  2524.  * Check if all Select Statements use the same number of
  2525.  * attributes and if all corresponding attributes are of
  2526.  * the same type
  2527.  */
  2528. check_targetlists_are_compatible(prev_target,
  2529.  ((Query *) lfirst(((Expr *) lfirst(intersect_list))->args))->targetList);
  2530. /* End of check for corresponding targetlists */
  2531. n->subselect = (Node *) lfirst(((Expr *) lfirst(intersect_list))->args);
  2532. op = "<>";
  2533. n->subLinkType = ALL_SUBLINK;
  2534. n->useor = true;
  2535. }
  2536. /*
  2537.  * Prepare the lefthand side of the Sublinks: All the entries
  2538.  * of the targetlist must be (IN) or must not be (NOT IN) the
  2539.  * subselect
  2540.  */
  2541. foreach(elist, intersect_node->targetList)
  2542. {
  2543. Node    *expr = lfirst(elist);
  2544. TargetEntry *tent = (TargetEntry *) expr;
  2545. n->lefthand = lappend(n->lefthand, tent->expr);
  2546. }
  2547. /*
  2548.  * The first arguments of oper also have to be created for the
  2549.  * sublink (they are the same as the lefthand side!)
  2550.  */
  2551. left_expr = n->lefthand;
  2552. right_expr = ((Query *) (n->subselect))->targetList;
  2553. foreach(elist, left_expr)
  2554. {
  2555. Node    *lexpr = lfirst(elist);
  2556. Node    *rexpr = lfirst(right_expr);
  2557. TargetEntry *tent = (TargetEntry *) rexpr;
  2558. Expr    *op_expr;
  2559. op_expr = make_op(op, lexpr, tent->expr);
  2560. n->oper = lappend(n->oper, op_expr);
  2561. right_expr = lnext(right_expr);
  2562. }
  2563. /*
  2564.  * If the Select Query node has aggregates in use add all the
  2565.  * subselects to the HAVING qual else to the WHERE qual
  2566.  */
  2567. if (intersect_node->hasAggs == false)
  2568. AddQual(intersect_node, (Node *) n);
  2569. else
  2570. AddHavingQual(intersect_node, (Node *) n);
  2571. /* Now we got sublinks */
  2572. intersect_node->hasSubLinks = true;
  2573. intersect_list = lnext(intersect_list);
  2574. }
  2575. intersect_node->intersectClause = NIL;
  2576. union_list = lappend(union_list, intersect_node);
  2577. }
  2578. /* The first entry to union_list is our new top node */
  2579. result = (Query *) lfirst(union_list);
  2580. /* attach the rest to unionClause */
  2581. result->unionClause = lnext(union_list);
  2582. /* Attach all the items remembered in the beginning of the function */
  2583. result->sortClause = sortClause;
  2584. result->uniqueFlag = uniqueFlag;
  2585. result->into = into;
  2586. result->isPortal = isPortal;
  2587. result->isBinary = isBinary;
  2588. result->isTemp = isTemp;
  2589. /*
  2590.  * The relation to insert into is attached to the range table of the
  2591.  * new top node
  2592.  */
  2593. if (commandType == CMD_INSERT)
  2594. {
  2595. result->rtable = lappend(result->rtable, rtable_insert);
  2596. result->resultRelation = length(result->rtable);
  2597. result->commandType = commandType;
  2598. }
  2599. /*
  2600.  * The resnames of the originally first SelectStatement are attached
  2601.  * to the new first SelectStatement
  2602.  */
  2603. foreach(elist, result->targetList)
  2604. {
  2605. TargetEntry *tent = (TargetEntry *) lfirst(elist);
  2606. tent->resdom->resname = lfirst(resnames);
  2607. resnames = lnext(resnames);
  2608. }
  2609. return result;
  2610. }
  2611. /* Create a list of nodes that are either Query nodes of NOT Expr
  2612.  * nodes followed by a Query node. The tree given in ptr contains at
  2613.  * least one non negated Query node. This node is attached to the
  2614.  * beginning of the list */
  2615. static void
  2616. create_intersect_list(Node *ptr, List **intersect_list)
  2617. {
  2618. List    *arg;
  2619. if (IsA(ptr, Query))
  2620. {
  2621. /* The non negated node is attached at the beginning (lcons) */
  2622. *intersect_list = lcons(ptr, *intersect_list);
  2623. return;
  2624. }
  2625. if (IsA(ptr, Expr))
  2626. {
  2627. if (((Expr *) ptr)->opType == NOT_EXPR)
  2628. {
  2629. /* negated nodes are appended to the end (lappend) */
  2630. *intersect_list = lappend(*intersect_list, ptr);
  2631. return;
  2632. }
  2633. else
  2634. {
  2635. foreach(arg, ((Expr *) ptr)->args)
  2636. create_intersect_list(lfirst(arg), intersect_list);
  2637. return;
  2638. }
  2639. return;
  2640. }
  2641. }
  2642. /* The nodes given in 'tree' are still 'raw' so 'cook' them using parse_analyze().
  2643.  * The node given in first_select has already been cooked, so don't transform
  2644.  * it again but return a pointer to the previously cooked version given in 'parsetree'
  2645.  * instead. */
  2646. static Node *
  2647. intersect_tree_analyze(Node *tree, Node *first_select, Node *parsetree)
  2648. {
  2649. Node    *result = (Node *) NIL;
  2650. List    *arg;
  2651. if (IsA(tree, SelectStmt))
  2652. {
  2653. /*
  2654.  * If we get to the tree given in first_select return parsetree
  2655.  * instead of performing parse_analyze()
  2656.  */
  2657. if (tree == first_select)
  2658. result = parsetree;
  2659. else
  2660. {
  2661. /* transform the 'raw' nodes to 'cooked' Query nodes */
  2662. List    *qtree = parse_analyze(lcons(tree, NIL), NULL);
  2663. result = (Node *) lfirst(qtree);
  2664. }
  2665. }
  2666. if (IsA(tree, Expr))
  2667. {
  2668. /* Call recursively for every argument of the node */
  2669. foreach(arg, ((Expr *) tree)->args)
  2670. lfirst(arg) = intersect_tree_analyze(lfirst(arg), first_select, parsetree);
  2671. result = tree;
  2672. }
  2673. return result;
  2674. }