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

数据库系统

开发平台:

Unix_Linux

  1. /*-------------------------------------------------------------------------
  2.  *
  3.  * keys.c
  4.  *   Key manipulation 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/util/Attic/keys.c,v 1.21.2.1 1999/08/02 06:27:07 scrappy Exp $
  11.  *
  12.  *-------------------------------------------------------------------------
  13.  */
  14. #include "postgres.h"
  15. #include "optimizer/keys.h"
  16. static Expr *matching2_tlvar(int var, List *tlist, bool (*test) ());
  17. static bool equal_indexkey_var(int index_key, Var *var);
  18. /*
  19.  * 1. index key
  20.  * one of:
  21.  * attnum
  22.  * (attnum arrayindex)
  23.  * 2. path key
  24.  * (subkey1 ... subkeyN)
  25.  * where subkeyI is a var node
  26.  * note that the 'Keys field is a list of these
  27.  * 3. join key
  28.  * (outer_subkey inner_subkey)
  29.  * where each subkey is a var node
  30.  * 4. sort key
  31.  * one of:
  32.  * SortKey node
  33.  * number
  34.  * nil
  35.  * (may also refer to the 'SortKey field of a SortKey node,
  36.  *  which looks exactly like an index key)
  37.  *
  38.  */
  39. /*
  40.  * match_indexkey_operand
  41.  *   Returns t iff an index key 'index_key' matches the given clause
  42.  *   operand.
  43.  *
  44.  */
  45. bool
  46. match_indexkey_operand(int indexkey, Var *operand, RelOptInfo *rel)
  47. {
  48. if (IsA(operand, Var) &&
  49. (lfirsti(rel->relids) == operand->varno) &&
  50. equal_indexkey_var(indexkey, operand))
  51. return true;
  52. else
  53. return false;
  54. }
  55. /*
  56.  * equal_indexkey_var
  57.  *   Returns t iff an index key 'index_key' matches the corresponding
  58.  *   fields of var node 'var'.
  59.  *
  60.  */
  61. static bool
  62. equal_indexkey_var(int index_key, Var *var)
  63. {
  64. if (index_key == var->varattno)
  65. return true;
  66. else
  67. return false;
  68. }
  69. /*
  70.  * extract_join_key
  71.  *  Returns the subkey in a join key corresponding to the outer or inner
  72.  *  relation.
  73.  *
  74.  */
  75. Var *
  76. extract_join_key(JoinKey *jk, int outer_or_inner)
  77. {
  78. Var    *retval;
  79. switch (outer_or_inner)
  80. {
  81. case OUTER:
  82. retval = jk->outer;
  83. break;
  84. case INNER:
  85. retval = jk->inner;
  86. break;
  87. default: /* do nothing */
  88. elog(DEBUG, "extract_join_key with neither INNER or OUTER");
  89. retval = NULL;
  90. }
  91. return retval;
  92. }
  93. /*
  94.  * pathkeys_match
  95.  *   Returns t iff two sets of path keys are equivalent.  They are
  96.  *   equivalent if the first Var nodes match the second Var nodes.
  97.  *
  98.  * See the top of optimizer/path/pathkeys.c for a description of pathkeys.
  99.  * Each pathkey is ordered by its join order, so they not pre-ordered to
  100.  * match. We must search them ourselves.
  101.  *
  102.  * This gets called a lot, so it is optimized.
  103.  */
  104. bool
  105. pathkeys_match(List *keys1, List *keys2, int *better_key)
  106. {
  107. List    *key1,
  108.    *key2;
  109. bool key1_subsetof_key2 = true,
  110. key2_subsetof_key1 = true;
  111. for (key1 = keys1, key2 = keys2;
  112.  key1 != NIL && key2 != NIL;
  113.  key1 = lnext(key1), key2 = lnext(key2))
  114. {
  115. List    *i;
  116. if (key1_subsetof_key2)
  117. foreach(i, lfirst(key1))
  118. {
  119. Var    *subkey = lfirst(i);
  120. if (!member(subkey, lfirst(key2)))
  121. {
  122. key1_subsetof_key2 = false;
  123. break;
  124. }
  125. }
  126. if (key2_subsetof_key1)
  127. foreach(i, lfirst(key2))
  128. {
  129. Var    *subkey = lfirst(i);
  130. if (!member(subkey, lfirst(key1)))
  131. {
  132. key2_subsetof_key1 = false;
  133. break;
  134. }
  135. }
  136. if (!key1_subsetof_key2 && !key2_subsetof_key1)
  137. break; /* no need to continue comparisons. */
  138. }
  139. if (!key1_subsetof_key2 && !key2_subsetof_key1)
  140. {
  141. *better_key = 0;
  142. return false;
  143. }
  144. if (key1_subsetof_key2 && !key2_subsetof_key1)
  145. {
  146. *better_key = 2;
  147. return true;
  148. }
  149. if (!key1_subsetof_key2 && key2_subsetof_key1)
  150. {
  151. *better_key = 1;
  152. return true;
  153. }
  154. *better_key = 0;
  155. return true;
  156. }
  157. /*
  158.  * collect_index_pathkeys
  159.  *   Creates a list of subkeys by retrieving var nodes corresponding to
  160.  *   each index key in 'index_keys' from the relation's target list
  161.  *   'tlist'. If the key is not in the target list, the key is irrelevant
  162.  *   and is thrown away.  The returned subkey list is of the form:
  163.  * ((var1) (var2) ... (varn))
  164.  *
  165.  * 'index_keys' is a list of index keys
  166.  * 'tlist' is a relation target list
  167.  *
  168.  * Returns the list of cons'd subkeys.
  169.  *
  170.  */
  171. /* This function is identical to matching_tlvar and tlistentry_member.
  172.  * They should be merged.
  173.  */
  174. static Expr *
  175. matching2_tlvar(int var, List *tlist, bool (*test) ())
  176. {
  177. TargetEntry *tlentry = NULL;
  178. if (var)
  179. {
  180. List    *temp;
  181. foreach(temp, tlist)
  182. {
  183. if ((*test) (var, get_expr(lfirst(temp))))
  184. {
  185. tlentry = lfirst(temp);
  186. break;
  187. }
  188. }
  189. }
  190. if (tlentry)
  191. return (Expr *) get_expr(tlentry);
  192. else
  193. return (Expr *) NULL;
  194. }
  195. List *
  196. collect_index_pathkeys(int *index_keys, List *tlist)
  197. {
  198. List    *retval = NIL;
  199. Assert(index_keys != NULL);
  200. while (index_keys[0] != 0)
  201. {
  202. Expr    *mvar;
  203. mvar = matching2_tlvar(index_keys[0],
  204.    tlist,
  205.    equal_indexkey_var);
  206. if (mvar)
  207. retval = lappend(retval, lcons(mvar, NIL));
  208. index_keys++;
  209. }
  210. return retval;
  211. }