keys.c
上传用户:blenddy
上传日期:2007-01-07
资源大小:6495k
文件大小:5k
- /*-------------------------------------------------------------------------
- *
- * keys.c
- * Key manipulation routines
- *
- * Copyright (c) 1994, Regents of the University of California
- *
- *
- * IDENTIFICATION
- * $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 $
- *
- *-------------------------------------------------------------------------
- */
- #include "postgres.h"
- #include "optimizer/keys.h"
- static Expr *matching2_tlvar(int var, List *tlist, bool (*test) ());
- static bool equal_indexkey_var(int index_key, Var *var);
- /*
- * 1. index key
- * one of:
- * attnum
- * (attnum arrayindex)
- * 2. path key
- * (subkey1 ... subkeyN)
- * where subkeyI is a var node
- * note that the 'Keys field is a list of these
- * 3. join key
- * (outer_subkey inner_subkey)
- * where each subkey is a var node
- * 4. sort key
- * one of:
- * SortKey node
- * number
- * nil
- * (may also refer to the 'SortKey field of a SortKey node,
- * which looks exactly like an index key)
- *
- */
- /*
- * match_indexkey_operand
- * Returns t iff an index key 'index_key' matches the given clause
- * operand.
- *
- */
- bool
- match_indexkey_operand(int indexkey, Var *operand, RelOptInfo *rel)
- {
- if (IsA(operand, Var) &&
- (lfirsti(rel->relids) == operand->varno) &&
- equal_indexkey_var(indexkey, operand))
- return true;
- else
- return false;
- }
- /*
- * equal_indexkey_var
- * Returns t iff an index key 'index_key' matches the corresponding
- * fields of var node 'var'.
- *
- */
- static bool
- equal_indexkey_var(int index_key, Var *var)
- {
- if (index_key == var->varattno)
- return true;
- else
- return false;
- }
- /*
- * extract_join_key
- * Returns the subkey in a join key corresponding to the outer or inner
- * relation.
- *
- */
- Var *
- extract_join_key(JoinKey *jk, int outer_or_inner)
- {
- Var *retval;
- switch (outer_or_inner)
- {
- case OUTER:
- retval = jk->outer;
- break;
- case INNER:
- retval = jk->inner;
- break;
- default: /* do nothing */
- elog(DEBUG, "extract_join_key with neither INNER or OUTER");
- retval = NULL;
- }
- return retval;
- }
- /*
- * pathkeys_match
- * Returns t iff two sets of path keys are equivalent. They are
- * equivalent if the first Var nodes match the second Var nodes.
- *
- * See the top of optimizer/path/pathkeys.c for a description of pathkeys.
- * Each pathkey is ordered by its join order, so they not pre-ordered to
- * match. We must search them ourselves.
- *
- * This gets called a lot, so it is optimized.
- */
- bool
- pathkeys_match(List *keys1, List *keys2, int *better_key)
- {
- List *key1,
- *key2;
- bool key1_subsetof_key2 = true,
- key2_subsetof_key1 = true;
- for (key1 = keys1, key2 = keys2;
- key1 != NIL && key2 != NIL;
- key1 = lnext(key1), key2 = lnext(key2))
- {
- List *i;
- if (key1_subsetof_key2)
- foreach(i, lfirst(key1))
- {
- Var *subkey = lfirst(i);
- if (!member(subkey, lfirst(key2)))
- {
- key1_subsetof_key2 = false;
- break;
- }
- }
- if (key2_subsetof_key1)
- foreach(i, lfirst(key2))
- {
- Var *subkey = lfirst(i);
- if (!member(subkey, lfirst(key1)))
- {
- key2_subsetof_key1 = false;
- break;
- }
- }
- if (!key1_subsetof_key2 && !key2_subsetof_key1)
- break; /* no need to continue comparisons. */
- }
- if (!key1_subsetof_key2 && !key2_subsetof_key1)
- {
- *better_key = 0;
- return false;
- }
- if (key1_subsetof_key2 && !key2_subsetof_key1)
- {
- *better_key = 2;
- return true;
- }
- if (!key1_subsetof_key2 && key2_subsetof_key1)
- {
- *better_key = 1;
- return true;
- }
- *better_key = 0;
- return true;
- }
- /*
- * collect_index_pathkeys
- * Creates a list of subkeys by retrieving var nodes corresponding to
- * each index key in 'index_keys' from the relation's target list
- * 'tlist'. If the key is not in the target list, the key is irrelevant
- * and is thrown away. The returned subkey list is of the form:
- * ((var1) (var2) ... (varn))
- *
- * 'index_keys' is a list of index keys
- * 'tlist' is a relation target list
- *
- * Returns the list of cons'd subkeys.
- *
- */
- /* This function is identical to matching_tlvar and tlistentry_member.
- * They should be merged.
- */
- static Expr *
- matching2_tlvar(int var, List *tlist, bool (*test) ())
- {
- TargetEntry *tlentry = NULL;
- if (var)
- {
- List *temp;
- foreach(temp, tlist)
- {
- if ((*test) (var, get_expr(lfirst(temp))))
- {
- tlentry = lfirst(temp);
- break;
- }
- }
- }
- if (tlentry)
- return (Expr *) get_expr(tlentry);
- else
- return (Expr *) NULL;
- }
- List *
- collect_index_pathkeys(int *index_keys, List *tlist)
- {
- List *retval = NIL;
- Assert(index_keys != NULL);
- while (index_keys[0] != 0)
- {
- Expr *mvar;
- mvar = matching2_tlvar(index_keys[0],
- tlist,
- equal_indexkey_var);
- if (mvar)
- retval = lappend(retval, lcons(mvar, NIL));
- index_keys++;
- }
- return retval;
- }