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

数据库系统

开发平台:

Unix_Linux

  1. /*-------------------------------------------------------------------------
  2.  *
  3.  * initsplan.c
  4.  *   Target list, qualification, joininfo initialization routines
  5.  *
  6.  * Copyright (c) 1994, Regents of the University of California
  7.  *
  8.  *
  9.  * IDENTIFICATION
  10.  *   $Header: /usr/local/cvsroot/pgsql/src/backend/optimizer/plan/initsplan.c,v 1.31.2.1 1999/08/02 06:27:01 scrappy Exp $
  11.  *
  12.  *-------------------------------------------------------------------------
  13.  */
  14. #include <sys/types.h>
  15. #include "postgres.h"
  16. #include "postgres.h"
  17. #include "catalog/pg_type.h"
  18. #include "nodes/makefuncs.h"
  19. #include "optimizer/clauses.h"
  20. #include "optimizer/cost.h"
  21. #include "optimizer/joininfo.h"
  22. #include "optimizer/pathnode.h"
  23. #include "optimizer/planmain.h"
  24. #include "optimizer/tlist.h"
  25. #include "optimizer/var.h"
  26. #include "utils/lsyscache.h"
  27. extern int Quiet;
  28. static void add_restrict_and_join_to_rel(Query *root, List *clause);
  29. static void add_join_info_to_rels(Query *root, RestrictInfo *restrictinfo,
  30.   Relids join_relids);
  31. static void add_vars_to_targetlist(Query *root, List *vars, Relids join_relids);
  32. static MergeOrder *mergejoinop(Expr *clause);
  33. static Oid hashjoinop(Expr *clause);
  34. /*****************************************************************************
  35.  *
  36.  *  TARGET LISTS
  37.  *
  38.  *****************************************************************************/
  39. /*
  40.  * make_var_only_tlist
  41.  *   Creates rel nodes for every relation mentioned in the target list
  42.  *   'tlist' (if a node hasn't already been created) and adds them to
  43.  *   *query_relation_list*.  Creates targetlist entries for each member of
  44.  *   'tlist' and adds them to the tlist field of the appropriate rel node.
  45.  */
  46. void
  47. make_var_only_tlist(Query *root, List *tlist)
  48. {
  49. List    *tlist_vars = NIL;
  50. List    *l = NIL;
  51. List    *tvar = NIL;
  52. foreach(l, tlist)
  53. {
  54. TargetEntry *entry = (TargetEntry *) lfirst(l);
  55. tlist_vars = nconc(tlist_vars, pull_var_clause(entry->expr));
  56. }
  57. /* now, the target list only contains Var nodes */
  58. foreach(tvar, tlist_vars)
  59. {
  60. Var    *var = (Var *) lfirst(tvar);
  61. Index varno;
  62. RelOptInfo *result;
  63. varno = var->varno;
  64. result = get_base_rel(root, varno);
  65. add_var_to_tlist(result, var);
  66. }
  67. }
  68. /*
  69.  * add_missing_vars_to_tlist
  70.  *   If we have range variable(s) in the FROM clause that does not appear
  71.  *   in the target list nor qualifications, we add it to the base relation
  72.  *   list. For instance, "select f.x from foo f, foo f2" is a join of f and
  73.  *   f2. Note that if we have "select foo.x from foo f", it also gets turned
  74.  *   into a join.
  75.  */
  76. void
  77. add_missing_vars_to_tlist(Query *root, List *tlist)
  78. {
  79. List    *l;
  80. int varno;
  81. varno = 1;
  82. foreach(l, root->rtable)
  83. {
  84. RangeTblEntry *rte = (RangeTblEntry *) lfirst(l);
  85. Relids relids;
  86. RelOptInfo *result;
  87. Var    *var;
  88. relids = lconsi(varno, NIL);
  89. if (rte->inFromCl && !rel_member(relids, root->base_rel_list))
  90. {
  91. var = makeVar(varno, ObjectIdAttributeNumber,
  92.   OIDOID, -1, 0, varno, ObjectIdAttributeNumber);
  93. /* add it to base_rel_list */
  94. result = get_base_rel(root, varno);
  95. add_var_to_tlist(result, var);
  96. }
  97. pfree(relids);
  98. varno++;
  99. }
  100. return;
  101. }
  102. /*****************************************************************************
  103.  *
  104.  *   QUALIFICATIONS
  105.  *
  106.  *****************************************************************************/
  107. /*
  108.  * add_restrict_and_join_to_rels-
  109.  *   Initializes RestrictInfo and JoinInfo fields of relation entries for all
  110.  *   relations appearing within clauses.  Creates new relation entries if
  111.  *   necessary, adding them to *query_relation_list*.
  112.  *
  113.  *   Returns nothing of interest.
  114.  */
  115. void
  116. add_restrict_and_join_to_rels(Query *root, List *clauses)
  117. {
  118. List    *clause;
  119. foreach(clause, clauses)
  120. add_restrict_and_join_to_rel(root, lfirst(clause));
  121. return;
  122. }
  123. /*
  124.  * add_restrict_and_join_to_rel-
  125.  *   Add clause information to either the 'RestrictInfo' or 'JoinInfo' field
  126.  *   of a relation entry(depending on whether or not the clause is a join)
  127.  *   by creating a new RestrictInfo node and setting appropriate fields
  128.  *   within the nodes.
  129.  *
  130.  *   Returns nothing of interest.
  131.  */
  132. static void
  133. add_restrict_and_join_to_rel(Query *root, List *clause)
  134. {
  135. Relids relids;
  136. List    *vars;
  137. RestrictInfo *restrictinfo = makeNode(RestrictInfo);
  138. /*
  139.  * Retrieve all relids and vars contained within the clause.
  140.  */
  141. clause_get_relids_vars((Node *) clause, &relids, &vars);
  142. restrictinfo->clause = (Expr *) clause;
  143. restrictinfo->notclause = contains_not((Node *) clause);
  144. restrictinfo->selectivity = 0;
  145. restrictinfo->indexids = NIL;
  146. restrictinfo->mergejoinorder = (MergeOrder *) NULL;
  147. restrictinfo->hashjoinoperator = (Oid) 0;
  148. if (length(relids) == 1)
  149. {
  150. /*
  151.  * There is only one relation participating in 'clause', so
  152.  * 'clause' must be a restriction clause.
  153.  */
  154. RelOptInfo *rel = get_base_rel(root, lfirsti(relids));
  155. /*
  156.  * The selectivity of the clause must be computed regardless of
  157.  * whether it's a restriction or a join clause
  158.  */
  159. if (is_funcclause((Node *) clause))
  160. /*
  161.  * XXX If we have a func clause set selectivity to 1/3, really
  162.  * need a true selectivity function.
  163.  */
  164. restrictinfo->selectivity = (Cost) 0.3333333;
  165. else
  166. restrictinfo->selectivity = compute_clause_selec(root, (Node *) clause, NIL);
  167. rel->restrictinfo = lcons(restrictinfo, rel->restrictinfo);
  168. }
  169. else
  170. {
  171. /*
  172.  * 'clause' is a join clause, since there is more than one atom in
  173.  * the relid list.
  174.  */
  175. if (is_funcclause((Node *) clause))
  176. /*
  177.  * XXX If we have a func clause set selectivity to 1/3, really
  178.  * need a true selectivity function.
  179.  */
  180. restrictinfo->selectivity = (Cost) 0.3333333;
  181. else
  182. restrictinfo->selectivity = compute_clause_selec(root, (Node *) clause, NIL);
  183. add_join_info_to_rels(root, restrictinfo, relids);
  184. /* we are going to be doing a join, so add var to targetlist */
  185. add_vars_to_targetlist(root, vars, relids);
  186. }
  187. }
  188. /*
  189.  * add_join_info_to_rels
  190.  *   For every relation participating in a join clause, add 'restrictinfo' to
  191.  *   the appropriate joininfo node(creating a new one and adding it to the
  192.  *   appropriate rel node if necessary).
  193.  *
  194.  * 'restrictinfo' describes the join clause
  195.  * 'join_relids' is the list of relations participating in the join clause
  196.  *
  197.  */
  198. static void
  199. add_join_info_to_rels(Query *root, RestrictInfo *restrictinfo,
  200.   Relids join_relids)
  201. {
  202. List    *join_relid;
  203. /* For every relid, find the rel, and add the proper join entries */
  204. foreach(join_relid, join_relids)
  205. {
  206. JoinInfo   *joininfo;
  207. Relids unjoined_relids = NIL;
  208. List    *rel;
  209. /* Get the relids not equal to the current relid */
  210. foreach(rel, join_relids)
  211. {
  212. if (lfirsti(rel) != lfirsti(join_relid))
  213. unjoined_relids = lappendi(unjoined_relids, lfirsti(rel));
  214. }
  215. joininfo = find_joininfo_node(get_base_rel(root, lfirsti(join_relid)),
  216.   unjoined_relids);
  217. joininfo->jinfo_restrictinfo = lcons(copyObject((void *) restrictinfo),
  218.    joininfo->jinfo_restrictinfo);
  219. }
  220. }
  221. /*
  222.  * add_vars_to_targetlist
  223.  *   For each variable appearing in a clause,
  224.  *   (1) If a targetlist entry for the variable is not already present in
  225.  *   the appropriate relation's target list, add one.
  226.  *   (2) If a targetlist entry is already present, but the var is part of a
  227.  *   join clause, add the relids of the join relations to the JoinList
  228.  *   entry of the targetlist entry.
  229.  *
  230.  *   'vars' is the list of var nodes
  231.  *   'join_relids' is the list of relids appearing in the join clause
  232.  * (if this is a join clause)
  233.  *
  234.  *   Returns nothing.
  235.  */
  236. static void
  237. add_vars_to_targetlist(Query *root, List *vars, Relids join_relids)
  238. {
  239. Var    *var;
  240. List    *temp = NIL;
  241. RelOptInfo *rel = (RelOptInfo *) NULL;
  242. TargetEntry *tlistentry;
  243. foreach(temp, vars)
  244. {
  245. var = (Var *) lfirst(temp);
  246. rel = get_base_rel(root, var->varno);
  247. tlistentry = tlistentry_member(var, rel->targetlist);
  248. if (tlistentry == NULL)
  249. /* add a new entry */
  250. add_var_to_tlist(rel, var);
  251. }
  252. }
  253. /*****************************************************************************
  254.  *
  255.  *  JOININFO
  256.  *
  257.  *****************************************************************************/
  258. /*
  259.  * set_joininfo_mergeable_hashable
  260.  *   Set the MergeJoinable or HashJoinable field for every joininfo node
  261.  *   (within a rel node) and the mergejoinorder or hashjoinop field for
  262.  *   each restrictinfo node(within a joininfo node) for all relations in a
  263.  *   query.
  264.  *
  265.  *   Returns nothing.
  266.  */
  267. void
  268. set_joininfo_mergeable_hashable(List *rel_list)
  269. {
  270. List    *x,
  271.    *y,
  272.    *z;
  273. RelOptInfo *rel;
  274. JoinInfo   *joininfo;
  275. RestrictInfo *restrictinfo;
  276. Expr    *clause;
  277. foreach(x, rel_list)
  278. {
  279. rel = (RelOptInfo *) lfirst(x);
  280. foreach(y, rel->joininfo)
  281. {
  282. joininfo = (JoinInfo *) lfirst(y);
  283. foreach(z, joininfo->jinfo_restrictinfo)
  284. {
  285. restrictinfo = (RestrictInfo *) lfirst(z);
  286. clause = restrictinfo->clause;
  287. if (is_joinable((Node *) clause))
  288. {
  289. MergeOrder *sortop = (MergeOrder *) NULL;
  290. Oid hashop = (Oid) NULL;
  291. if (_enable_mergejoin_)
  292. sortop = mergejoinop(clause);
  293. if (sortop)
  294. {
  295. restrictinfo->mergejoinorder = sortop;
  296. joininfo->mergejoinable = true;
  297. }
  298. if (_enable_hashjoin_)
  299. hashop = hashjoinop(clause);
  300. if (hashop)
  301. {
  302. restrictinfo->hashjoinoperator = hashop;
  303. joininfo->hashjoinable = true;
  304. }
  305. }
  306. }
  307. }
  308. }
  309. }
  310. /*
  311.  * mergejoinop
  312.  *   Returns the mergejoin operator of an operator iff 'clause' is
  313.  *   mergejoinable, i.e., both operands are single vars and the operator is
  314.  *   a mergejoinable operator.
  315.  */
  316. static MergeOrder *
  317. mergejoinop(Expr *clause)
  318. {
  319. Var    *left,
  320.    *right;
  321. Oid opno,
  322. leftOp,
  323. rightOp;
  324. bool sortable;
  325. if (!is_opclause((Node *) clause))
  326. return NULL;
  327. left = get_leftop(clause);
  328. right = get_rightop(clause);
  329. /* caution: is_opclause accepts more than I do, so check it */
  330. if (!right)
  331. return NULL; /* unary opclauses need not apply */
  332. if (!IsA(left, Var) ||!IsA(right, Var))
  333. return NULL;
  334. opno = ((Oper *) clause->oper)->opno;
  335. sortable = op_mergejoinable(opno,
  336. left->vartype,
  337. right->vartype,
  338. &leftOp,
  339. &rightOp);
  340. if (sortable)
  341. {
  342. MergeOrder *morder = makeNode(MergeOrder);
  343. morder->join_operator = opno;
  344. morder->left_operator = leftOp;
  345. morder->right_operator = rightOp;
  346. morder->left_type = left->vartype;
  347. morder->right_type = right->vartype;
  348. return morder;
  349. }
  350. else
  351. return NULL;
  352. }
  353. /*
  354.  * hashjoinop
  355.  *   Returns the hashjoin operator of an operator iff 'clause' is
  356.  *   hashjoinable, i.e., both operands are single vars and the operator is
  357.  *   a hashjoinable operator.
  358.  */
  359. static Oid
  360. hashjoinop(Expr *clause)
  361. {
  362. Var    *left,
  363.    *right;
  364. if (!is_opclause((Node *) clause))
  365. return InvalidOid;
  366. left = get_leftop(clause);
  367. right = get_rightop(clause);
  368. /* caution: is_opclause accepts more than I do, so check it */
  369. if (!right)
  370. return InvalidOid; /* unary opclauses need not apply */
  371. if (!IsA(left, Var) ||!IsA(right, Var))
  372. return InvalidOid;
  373. return op_hashjoinable(((Oper *) clause->oper)->opno,
  374.    left->vartype,
  375.    right->vartype);
  376. }