← Back to team overview

maria-developers team mailing list archive

Rev 2721: MWL#17: Address 2nd post-review feedback in file:///home/psergey/dev/maria-5.1-table-elim-r10/

 

At file:///home/psergey/dev/maria-5.1-table-elim-r10/

------------------------------------------------------------
revno: 2721
revision-id: psergey@xxxxxxxxxxxx-20090815060803-0yvp5mmgo87emykp
parent: psergey@xxxxxxxxxxxx-20090813211212-jghejwxsl6adtopl
committer: Sergey Petrunya <psergey@xxxxxxxxxxxx>
branch nick: maria-5.1-table-elim-r10
timestamp: Sat 2009-08-15 10:08:03 +0400
message:
  MWL#17: Address 2nd post-review feedback
  - Switch from uniform graph to bipartite graph with two kinds of nodes:
    "values" (tables and fields) and "modules" (t.col=func(...) equalities, 
    multi-equalities, unique keys, inner sides of outer joins).
  - Rename functions, classes, etc.
=== modified file 'sql/opt_table_elimination.cc'
--- a/sql/opt_table_elimination.cc	2009-08-13 20:44:52 +0000
+++ b/sql/opt_table_elimination.cc	2009-08-15 06:08:03 +0000
@@ -40,19 +40,78 @@
   Table elimination is redone on every PS re-execution.
 */
 
-
-/*
-  An abstract structure that represents some entity that's being dependent on
-  some other entity.
-*/
-
-class Func_dep : public Sql_alloc
-{
-public:
-  enum {
-    FD_INVALID,
+class Value_dep
+{
+public:
+  enum {
+    VALUE_FIELD,
+    VALUE_TABLE,
+  } type; /* Type of the object */
+
+  bool bound;
+  Value_dep *next;
+};
+
+class Field_value;
+class Table_value;
+class Outer_join_module;
+class Key_module;
+
+/*
+  A table field. There is only one such object for any tblX.fieldY
+  - the field epends on its table and equalities
+  - expressions that use the field are its dependencies
+*/
+class Field_value : public Value_dep
+{
+public:
+  Field_value(Table_value *table_arg, Field *field_arg) :
+    table(table_arg), field(field_arg)
+  {
+    type= Value_dep::VALUE_FIELD;
+  }
+
+  Table_value *table; /* Table this field is from */
+  Field *field;
+  
+  /* 
+    Field_deps that belong to one table form a linked list. list members are
+    ordered by field_index 
+  */
+  Field_value *next_table_field;
+  uint bitmap_offset; /* Offset of our part of the bitmap */
+};
+
+
+/*
+  A table.
+  - table depends on any of its unique keys
+  - has its fields and embedding outer join as dependency.
+*/
+class Table_value : public Value_dep
+{
+public:
+  Table_value(TABLE *table_arg) : 
+    table(table_arg), fields(NULL), keys(NULL), outer_join_dep(NULL)
+  {
+    type= Value_dep::VALUE_TABLE;
+  }
+  TABLE *table;
+  Field_value *fields; /* Ordered list of fields that belong to this table */
+  Key_module *keys; /* Ordered list of Unique keys in this table */
+  Outer_join_module *outer_join_dep; /* Innermost eliminable outer join we're in */
+};
+
+
+/*
+  A 'module'
+*/
+
+class Module_dep : public Sql_alloc
+{
+public:
+  enum {
     FD_EXPRESSION,
-    FD_FIELD,
     FD_MULTI_EQUALITY,
     FD_UNIQUE_KEY,
     FD_TABLE,
@@ -63,58 +122,26 @@
     Used to make a linked list of elements that became bound and thus can
     make elements that depend on them bound, too.
   */
-  Func_dep *next; 
-  bool bound; /* TRUE<=> The entity is considered bound */
-  Func_dep() : next(NULL), bound(FALSE) {}
+  Module_dep *next; 
+  uint unknown_args; /* TRUE<=> The entity is considered bound */
+
+  Module_dep() : next(NULL), unknown_args(0) {}
 };
 
 
-class Field_dep;
-class Table_dep;
-class Outer_join_dep;
-
 
 /*
   A "tbl.column= expr" equality dependency.  tbl.column depends on fields 
   used in expr.
 */
-class Equality_dep : public Func_dep
+class Equality_module : public Module_dep
 {
 public:
-  Field_dep *field;
+  Field_value *field;
   Item  *val;
   
   /* Used during condition analysis only, similar to KEYUSE::level */
   uint level;
-  
-  /* Number of fields referenced from *val that are not yet 'bound' */
-  uint unknown_args;
-};
-
-
-/*
-  A table field. There is only one such object for any tblX.fieldY
-  - the field epends on its table and equalities
-  - expressions that use the field are its dependencies
-*/
-class Field_dep : public Func_dep
-{
-public:
-  Field_dep(Table_dep *table_arg, Field *field_arg) :
-    table(table_arg), field(field_arg)
-  {
-    type= Func_dep::FD_FIELD;
-  }
-
-  Table_dep *table; /* Table this field is from */
-  Field *field;
-  
-  /* 
-    Field_deps that belong to one table form a linked list. list members are
-    ordered by field_index 
-  */
-  Field_dep *next_table_field;
-  uint bitmap_offset; /* Offset of our part of the bitmap */
 };
 
 
@@ -123,41 +150,21 @@
    - Unique key depends on all of its components
    - Key's table is its dependency
 */
-class Key_dep: public Func_dep
+class Key_module: public Module_dep
 {
 public:
-  Key_dep(Table_dep *table_arg, uint keyno_arg, uint n_parts_arg) :
-    table(table_arg), keyno(keyno_arg), n_missing_keyparts(n_parts_arg),
-    next_table_key(NULL)
+  Key_module(Table_value *table_arg, uint keyno_arg, uint n_parts_arg) :
+    table(table_arg), keyno(keyno_arg), next_table_key(NULL)
   {
-    type= Func_dep::FD_UNIQUE_KEY;
+    type= Module_dep::FD_UNIQUE_KEY;
+    unknown_args= n_parts_arg;
   }
-  Table_dep *table; /* Table this key is from */
+  Table_value *table; /* Table this key is from */
   uint keyno;
-  uint n_missing_keyparts;
   /* Unique keys form a linked list, ordered by keyno */
-  Key_dep *next_table_key;
-};
-
-
-/*
-  A table.
-  - table depends on any of its unique keys
-  - has its fields and embedding outer join as dependency.
-*/
-class Table_dep : public Func_dep
-{
-public:
-  Table_dep(TABLE *table_arg) : 
-    table(table_arg), fields(NULL), keys(NULL), outer_join_dep(NULL)
-  {
-    type= Func_dep::FD_TABLE;
-  }
-  TABLE *table;
-  Field_dep *fields; /* Ordered list of fields that belong to this table */
-  Key_dep *keys; /* Ordered list of Unique keys in this table */
-  Outer_join_dep *outer_join_dep; /* Innermost eliminable outer join we're in */
-};
+  Key_module *next_table_key;
+};
+
 
 
 /*
@@ -165,14 +172,14 @@
   - it depends on all tables inside it
   - has its parent outer join as dependency
 */
-class Outer_join_dep: public Func_dep
+class Outer_join_module: public Module_dep
 {
 public:
-  Outer_join_dep(TABLE_LIST *table_list_arg, table_map missing_tables_arg) : 
-    table_list(table_list_arg), missing_tables(missing_tables_arg),
-    all_tables(missing_tables_arg), parent(NULL)
+  Outer_join_module(TABLE_LIST *table_list_arg, uint n_children) : 
+    table_list(table_list_arg), parent(NULL)
   {
-    type= Func_dep::FD_OUTER_JOIN;
+    type= Module_dep::FD_OUTER_JOIN;
+    unknown_args= n_children;
   }
   /* 
     Outer join we're representing. This can be a join nest or a one table that
@@ -184,11 +191,11 @@
     Tables within this outer join (and its descendants) that are not yet known
     to be functionally dependent.
   */
-  table_map missing_tables;
+  table_map missing_tables; //psergey-todo: remove 
   /* All tables within this outer join and its descendants */ 
-  table_map all_tables;
+  table_map all_tables; //psergey-todo: remove 
   /* Parent eliminable outer join, if any */
-  Outer_join_dep *parent;
+  Outer_join_module *parent;
 };
 
 
@@ -205,44 +212,45 @@
 
   JOIN *join;
   /* Array of equality dependencies */
-  Equality_dep *equality_deps;
+  Equality_module *equality_deps;
   uint n_equality_deps; /* Number of elements in the array */
 
-  /* tablenr -> Table_dep* mapping. */
-  Table_dep *table_deps[MAX_KEY];
+  /* tablenr -> Table_value* mapping. */
+  Table_value *table_deps[MAX_KEY];
 
   /* Outer joins that are candidates for elimination */
-  List<Outer_join_dep> oj_deps;
+  List<Outer_join_module> oj_deps;
 
   /* Bitmap of how expressions depend on bits */
   MY_BITMAP expr_deps;
 };
 
-
 static 
-void build_eq_deps_for_cond(Table_elimination *te, Equality_dep **fdeps, 
+void build_eq_deps_for_cond(Table_elimination *te, Equality_module **fdeps, 
                             uint *and_level, Item *cond, 
                             table_map usable_tables);
 static 
 void add_eq_dep(Table_elimination *te, 
-                Equality_dep **eq_dep, uint and_level,
+                Equality_module **eq_dep, uint and_level,
                 Item_func *cond, Field *field,
                 bool eq_func, Item **value,
                 uint num_values, table_map usable_tables);
 static 
-Equality_dep *merge_func_deps(Equality_dep *start, Equality_dep *new_fields, 
-                              Equality_dep *end, uint and_level);
-
-static Table_dep *get_table_dep(Table_elimination *te, TABLE *table);
-static Field_dep *get_field_dep(Table_elimination *te, Field *field);
-
+Equality_module *merge_func_deps(Equality_module *start, Equality_module *new_fields, 
+                              Equality_module *end, uint and_level);
+
+static Table_value *get_table_value(Table_elimination *te, TABLE *table);
+static Field_value *get_field_value(Table_elimination *te, Field *field);
+static 
+void run_elimination_wave(Table_elimination *te, Module_dep *bound_modules);
 void eliminate_tables(JOIN *join);
 static void mark_as_eliminated(JOIN *join, TABLE_LIST *tbl);
 
+#if 0
 #ifndef DBUG_OFF
 static void dbug_print_deps(Table_elimination *te);
 #endif 
-
+#endif 
 /*******************************************************************************************/
 
 /*
@@ -262,14 +270,14 @@
 */
 
 static 
-void build_eq_deps_for_cond(Table_elimination *te, Equality_dep **fdeps, 
+void build_eq_deps_for_cond(Table_elimination *te, Equality_module **fdeps, 
                             uint *and_level, Item *cond, 
                             table_map usable_tables)
 {
   if (cond->type() == Item_func::COND_ITEM)
   {
     List_iterator_fast<Item> li(*((Item_cond*) cond)->argument_list());
-    Equality_dep *org_key_fields= *fdeps;
+    Equality_module *org_key_fields= *fdeps;
     
     /* AND/OR */
     if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
@@ -293,7 +301,7 @@
       Item *item;
       while ((item=li++))
       {
-        Equality_dep *start_key_fields= *fdeps;
+        Equality_module *start_key_fields= *fdeps;
         (*and_level)++;
         build_eq_deps_for_cond(te, fdeps, and_level, item, usable_tables);
         *fdeps= merge_func_deps(org_key_fields, start_key_fields, *fdeps,
@@ -432,7 +440,7 @@
 
 
 /*
-  Perform an OR operation on two (adjacent) Equality_dep arrays.
+  Perform an OR operation on two (adjacent) Equality_module arrays.
 
   SYNOPSIS
      merge_func_deps()
@@ -442,7 +450,7 @@
        and_level    AND-level.
 
   DESCRIPTION
-  This function is invoked for two adjacent arrays of Equality_dep elements:
+  This function is invoked for two adjacent arrays of Equality_module elements:
 
                       $LEFT_PART             $RIGHT_PART
              +-----------------------+-----------------------+
@@ -477,19 +485,19 @@
 */
 
 static 
-Equality_dep *merge_func_deps(Equality_dep *start, Equality_dep *new_fields, 
-                              Equality_dep *end, uint and_level)
+Equality_module *merge_func_deps(Equality_module *start, Equality_module *new_fields, 
+                              Equality_module *end, uint and_level)
 {
   if (start == new_fields)
     return start;				// Impossible or
   if (new_fields == end)
     return start;				// No new fields, skip all
 
-  Equality_dep *first_free=new_fields;
+  Equality_module *first_free=new_fields;
 
   for (; new_fields != end ; new_fields++)
   {
-    for (Equality_dep *old=start ; old != first_free ; old++)
+    for (Equality_module *old=start ; old != first_free ; old++)
     {
       /* 
          TODO: does it make sense to attempt to merging multiple-equalities? 
@@ -534,7 +542,7 @@
     Ok, the results are within the [start, first_free) range, and the useful
     elements have level==and_level. Now, lets remove all unusable elements:
   */
-  for (Equality_dep *old=start ; old != first_free ;)
+  for (Equality_module *old=start ; old != first_free ;)
   {
     if (old->level != and_level)
     {						// Not used in all levels
@@ -550,14 +558,14 @@
 
 
 /*
-  Add an Equality_dep element for a given predicate, if applicable 
+  Add an Equality_module element for a given predicate, if applicable 
 
   DESCRIPTION 
     This function is modeled after add_key_field().
 */
 
 static 
-void add_eq_dep(Table_elimination *te, Equality_dep **eq_dep,
+void add_eq_dep(Table_elimination *te, Equality_module **eq_dep,
                 uint and_level, Item_func *cond, Field *field,
                 bool eq_func, Item **value, uint num_values,
                 table_map usable_tables)
@@ -622,22 +630,21 @@
 
   DBUG_ASSERT(eq_func);
   /* Store possible eq field */
-  (*eq_dep)->type=  Func_dep::FD_EXPRESSION; //psergey-todo;
-  (*eq_dep)->field= get_field_dep(te, field); 
+  (*eq_dep)->type=  Module_dep::FD_EXPRESSION; //psergey-todo;
+  (*eq_dep)->field= get_field_value(te, field); 
   (*eq_dep)->val=   *value;
   (*eq_dep)->level= and_level;
   (*eq_dep)++;
 }
 
-
 /*
-  Get a Table_dep object for the given table, creating it if necessary.
+  Get a Table_value object for the given table, creating it if necessary.
 */
 
-static Table_dep *get_table_dep(Table_elimination *te, TABLE *table)
+static Table_value *get_table_value(Table_elimination *te, TABLE *table)
 {
-  Table_dep *tbl_dep= new Table_dep(table);
-  Key_dep **key_list= &(tbl_dep->keys);
+  Table_value *tbl_dep= new Table_value(table);
+  Key_module **key_list= &(tbl_dep->keys);
 
   /* Add dependencies for unique keys */
   for (uint i=0; i < table->s->keys; i++)
@@ -645,7 +652,7 @@
     KEY *key= table->key_info + i; 
     if ((key->flags & (HA_NOSAME | HA_END_SPACE_KEY)) == HA_NOSAME)
     {
-      Key_dep *key_dep= new Key_dep(tbl_dep, i, key->key_parts);
+      Key_module *key_dep= new Key_module(tbl_dep, i, key->key_parts);
       *key_list= key_dep;
       key_list= &(key_dep->next_table_key);
     }
@@ -655,20 +662,20 @@
 
 
 /* 
-  Get a Field_dep object for the given field, creating it if necessary
+  Get a Field_value object for the given field, creating it if necessary
 */
 
-static Field_dep *get_field_dep(Table_elimination *te, Field *field)
+static Field_value *get_field_value(Table_elimination *te, Field *field)
 {
   TABLE *table= field->table;
-  Table_dep *tbl_dep;
+  Table_value *tbl_dep;
 
   /* First, get the table*/
   if (!(tbl_dep= te->table_deps[table->tablenr]))
-    tbl_dep= get_table_dep(te, table);
+    tbl_dep= get_table_value(te, table);
  
   /* Try finding the field in field list */
-  Field_dep **pfield= &(tbl_dep->fields);
+  Field_value **pfield= &(tbl_dep->fields);
   while (*pfield && (*pfield)->field->field_index < field->field_index)
   {
     pfield= &((*pfield)->next_table_field);
@@ -677,7 +684,7 @@
     return *pfield;
   
   /* Create the field and insert it in the list */
-  Field_dep *new_field= new Field_dep(tbl_dep, field);
+  Field_value *new_field= new Field_value(tbl_dep, field);
   new_field->next_table_field= *pfield;
   *pfield= new_field;
 
@@ -686,19 +693,19 @@
 
 
 /*
-  Create an Outer_join_dep object for the given outer join
+  Create an Outer_join_module object for the given outer join
 
   DESCRIPTION
-    Outer_join_dep objects for children (or further descendants) are always
+    Outer_join_module objects for children (or further descendants) are always
     created before the parents.
 */
 
 static 
-Outer_join_dep *get_outer_join_dep(Table_elimination *te, 
+Outer_join_module *get_outer_join_dep(Table_elimination *te, 
                                    TABLE_LIST *outer_join, table_map deps_map)
 {
-  Outer_join_dep *oj_dep;
-  oj_dep= new Outer_join_dep(outer_join, deps_map);
+  Outer_join_module *oj_dep;
+  oj_dep= new Outer_join_module(outer_join, my_count_bits(deps_map));
   
   /* 
     Collect a bitmap fo tables that we depend on, and also set parent pointer
@@ -708,7 +715,7 @@
   int idx;
   while ((idx= it.next_bit()) != Table_map_iterator::BITMAP_END)
   {
-    Table_dep *table_dep;
+    Table_value *table_dep;
     if (!(table_dep= te->table_deps[idx]))
     {
       /*
@@ -727,23 +734,24 @@
         }
       }
       DBUG_ASSERT(table);
-      table_dep= get_table_dep(te, table);
+      table_dep= get_table_value(te, table);
     }
     
     /* 
       Walk from the table up to its embedding outer joins. The goal is to
       find the least embedded outer join nest and set its parent pointer to
-      point to the newly created Outer_join_dep.
+      point to the newly created Outer_join_module.
       to set the pointer of its near 
     */
     if (!table_dep->outer_join_dep)
       table_dep->outer_join_dep= oj_dep;
     else
     {
-      Outer_join_dep *oj= table_dep->outer_join_dep;
+      Outer_join_module *oj= table_dep->outer_join_dep;
       while (oj->parent)
         oj= oj->parent;
-      oj->parent=oj_dep;
+      if (oj != oj_dep)
+        oj->parent=oj_dep;
     }
   }
   return oj_dep;
@@ -757,7 +765,7 @@
     collect_funcdeps_for_join_list()
       te                       Table elimination context.
       join_list                Join list to work on 
-      build_eq_deps            TRUE <=> build Equality_dep elements for all
+      build_eq_deps            TRUE <=> build Equality_module elements for all
                                members of the join list, even if they cannot 
                                be individually eliminated
       tables_used_elsewhere    Bitmap of tables that are referred to from
@@ -779,7 +787,7 @@
                                bool build_eq_deps,
                                table_map tables_used_elsewhere,
                                table_map *eliminable_tables,
-                               Equality_dep **eq_dep)
+                               Equality_module **eq_dep)
 {
   TABLE_LIST *tbl;
   List_iterator<TABLE_LIST> it(*join_list);
@@ -845,10 +853,10 @@
   
   void see_field(Field *field)
   {
-    Table_dep *tbl_dep;
+    Table_value *tbl_dep;
     if ((tbl_dep= te->table_deps[field->table->tablenr]))
     {
-      for (Field_dep *field_dep= tbl_dep->fields; field_dep; 
+      for (Field_value *field_dep= tbl_dep->fields; field_dep; 
            field_dep= field_dep->next_table_field)
       {
         if (field->field_index == field_dep->field->field_index)
@@ -888,21 +896,21 @@
 */
 
 static 
-bool setup_equality_deps(Table_elimination *te, Func_dep **bound_deps_list)
+bool setup_equality_deps(Table_elimination *te, Module_dep **bound_deps_list)
 {
   DBUG_ENTER("setup_equality_deps");
   
   /*
-    Count Field_dep objects and assign each of them a unique bitmap_offset.
+    Count Field_value objects and assign each of them a unique bitmap_offset.
   */
   uint offset= 0;
-  for (Table_dep **tbl_dep=te->table_deps; 
+  for (Table_value **tbl_dep=te->table_deps; 
        tbl_dep < te->table_deps + MAX_TABLES;
        tbl_dep++)
   {
     if (*tbl_dep)
     {
-      for (Field_dep *field_dep= (*tbl_dep)->fields;
+      for (Field_value *field_dep= (*tbl_dep)->fields;
            field_dep;
            field_dep= field_dep->next_table_field)
       {
@@ -926,9 +934,9 @@
 
     Also collect a linked list of equalities that are bound.
   */
-  Func_dep *bound_dep= NULL;
+  Module_dep *bound_dep= NULL;
   Field_dependency_setter deps_setter(te);
-  for (Equality_dep *eq_dep= te->equality_deps; 
+  for (Equality_module *eq_dep= te->equality_deps; 
        eq_dep < te->equality_deps + te->n_equality_deps;
        eq_dep++)
   {
@@ -940,12 +948,11 @@
     {
       eq_dep->next= bound_dep;
       bound_dep= eq_dep;
-      eq_dep->bound= TRUE;
     }
   }
   *bound_deps_list= bound_dep;
 
-  DBUG_EXECUTE("test", dbug_print_deps(te); );
+  //DBUG_EXECUTE("test", dbug_print_deps(te); );
   DBUG_RETURN(FALSE);
 }
 
@@ -1042,9 +1049,9 @@
     uint m= max(thd->lex->current_select->max_equal_elems,1);
     uint max_elems= ((thd->lex->current_select->cond_count+1)*2 +
                       thd->lex->current_select->between_count)*m + 1 + 10; 
-    if (!(te.equality_deps= new Equality_dep[max_elems]))
+    if (!(te.equality_deps= new Equality_module[max_elems]))
       DBUG_VOID_RETURN;
-    Equality_dep *eq_deps_end= te.equality_deps;
+    Equality_module *eq_deps_end= te.equality_deps;
     table_map eliminable_tables= 0;
     collect_funcdeps_for_join_list(&te, join->join_list,
                                    FALSE,
@@ -1052,96 +1059,125 @@
                                    &eliminable_tables,
                                    &eq_deps_end);
     te.n_equality_deps= eq_deps_end - te.equality_deps;
-    Func_dep *bound_dep;
-    setup_equality_deps(&te, &bound_dep);
-
-    /* 
-      Run the wave.
-      All Func_dep-derived objects are divided into three classes:
-      - Those that have bound=FALSE
-      - Those that have bound=TRUE 
-      - Those that have bound=TRUE and are in the list..
-
-    */
-    while (bound_dep)
-    {
-      Func_dep *next= bound_dep->next;
-      //e= list.remove_first();
-      switch (bound_dep->type)
+    
+    Module_dep *bound_modules;
+    //Value_dep  *bound_values;
+    setup_equality_deps(&te, &bound_modules);
+    
+    run_elimination_wave(&te, bound_modules);
+  }
+  DBUG_VOID_RETURN;
+}
+
+
+static 
+void signal_from_field_to_exprs(Table_elimination* te, Field_value *field_dep,
+                                Module_dep **bound_modules)
+{
+  /* Now, expressions */
+  for (uint i=0; i < te->n_equality_deps; i++)
+  {
+    if (bitmap_is_set(&te->expr_deps, field_dep->bitmap_offset + i) &&
+        te->equality_deps[i].unknown_args &&
+        !--te->equality_deps[i].unknown_args)
+    {
+      /* Mark as bound and add to the list */
+      Equality_module* eq_dep= &te->equality_deps[i];
+      eq_dep->next= *bound_modules;
+      *bound_modules= eq_dep;
+    }
+  }
+}
+
+
+static 
+void run_elimination_wave(Table_elimination *te, Module_dep *bound_modules)
+{
+  Value_dep *bound_values= NULL;
+  /* 
+    Run the wave.
+    All Func_dep-derived objects are divided into three classes:
+    - Those that have bound=FALSE
+    - Those that have bound=TRUE 
+    - Those that have bound=TRUE and are in the list..
+
+  */
+  while (bound_modules)
+  {
+    for (;bound_modules; bound_modules= bound_modules->next)
+    {
+      switch (bound_modules->type)
       {
-        case Func_dep::FD_EXPRESSION:
+        case Module_dep::FD_EXPRESSION:
         {
           /*  It's a field=expr and we got to know the expr, so we know the field */
-          Equality_dep *eq_dep= (Equality_dep*)bound_dep;
+          Equality_module *eq_dep= (Equality_module*)bound_modules;
           if (!eq_dep->field->bound)
           {
             /* Mark as bound and add to the list */
             eq_dep->field->bound= TRUE;
-            eq_dep->field->next= next;
-            next= eq_dep->field;
-          }
-          break;
-        }
-        case Func_dep::FD_FIELD:
+            eq_dep->field->next= bound_values;
+            bound_values= eq_dep->field;
+          }
+          break;
+        }
+        case Module_dep::FD_UNIQUE_KEY:
+        {
+          /* Unique key is known means the table is known */
+          Table_value *table_dep=((Key_module*)bound_modules)->table;
+          if (!table_dep->bound)
+          {
+            /* Mark as bound and add to the list */
+            table_dep->bound= TRUE;
+            table_dep->next= bound_values;
+            bound_values= table_dep;
+          }
+          break;
+        }
+        case Module_dep::FD_OUTER_JOIN:
+        {
+          Outer_join_module *outer_join_dep= (Outer_join_module*)bound_modules;
+          mark_as_eliminated(te->join, outer_join_dep->table_list);
+          break;
+        }
+        case Module_dep::FD_MULTI_EQUALITY:
+        default:
+          DBUG_ASSERT(0);
+      }
+    }
+
+    for (;bound_values; bound_values=bound_values->next)
+    {
+      switch (bound_values->type)
+      {
+        case Value_dep::VALUE_FIELD:
         {
           /*
             Field became known. Check out
             - unique keys we belong to
             - expressions that depend on us.
           */
-          Field_dep *field_dep= (Field_dep*)bound_dep;
-          for (Key_dep *key_dep= field_dep->table->keys; key_dep;
+          Field_value *field_dep= (Field_value*)bound_values;
+          for (Key_module *key_dep= field_dep->table->keys; key_dep;
                key_dep= key_dep->next_table_key)
           {
             DBUG_PRINT("info", ("key %s.%s is now bound",
                                 key_dep->table->table->alias, 
                                 key_dep->table->table->key_info[key_dep->keyno].name));
             if (field_dep->field->part_of_key.is_set(key_dep->keyno) && 
-                !key_dep->bound)
-            {
-              if (!--key_dep->n_missing_keyparts)
-              {
-                /* Mark as bound and add to the list */
-                key_dep->bound= TRUE;
-                key_dep->next= next;
-                next= key_dep;
-              }
-            }
-          }
-
-          /* Now, expressions */
-          for (uint i=0; i < te.n_equality_deps; i++)
-          {
-            if (bitmap_is_set(&te.expr_deps, field_dep->bitmap_offset + i))
-            {
-              Equality_dep* eq_dep= &te.equality_deps[i];
-              if (!--eq_dep->unknown_args)
-              {
-                /* Mark as bound and add to the list */
-                eq_dep->bound= TRUE;
-                eq_dep->next= next;
-                next= eq_dep;
-              }
-            }
-          }
-          break;
-        }
-        case Func_dep::FD_UNIQUE_KEY:
-        {
-          /* Unique key is known means the table is known */
-          Table_dep *table_dep=((Key_dep*)bound_dep)->table;
-          if (!table_dep->bound)
-          {
-            /* Mark as bound and add to the list */
-            table_dep->bound= TRUE;
-            table_dep->next= next;
-            next= table_dep;
-          }
-          break;
-        }
-        case Func_dep::FD_TABLE:
-        {
-          Table_dep *table_dep=(Table_dep*)bound_dep; 
+                key_dep->unknown_args && !--key_dep->unknown_args)
+            {
+              /* Mark as bound and add to the list */
+              key_dep->next= bound_modules;
+              bound_modules= key_dep;
+            }
+          }
+          signal_from_field_to_exprs(te, field_dep, &bound_modules);
+          break;
+        }
+        case Value_dep::VALUE_TABLE:
+        {
+          Table_value *table_dep=(Table_value*)bound_values; 
           DBUG_PRINT("info", ("table %s is now bound",
                               table_dep->table->alias));
           /*
@@ -1149,50 +1185,35 @@
             - all its fields are known
             - one more element in outer join nest is known
           */
-          for (Field_dep *field_dep= table_dep->fields; field_dep; 
+          for (Field_value *field_dep= table_dep->fields; field_dep; 
                field_dep= field_dep->next_table_field)
           {
             if (!field_dep->bound)
             {
               /* Mark as bound and add to the list */
               field_dep->bound= TRUE;
-              field_dep->next= next;
-              next= field_dep;
-            }
-          }
-          Outer_join_dep *outer_join_dep= table_dep->outer_join_dep;
-          if (!(outer_join_dep->missing_tables &= ~table_dep->table->map))
-          {
-            /* Mark as bound and add to the list */
-            outer_join_dep->bound= TRUE;
-            outer_join_dep->next= next;
-            next= outer_join_dep;
-          }
-          break;
-        }
-        case Func_dep::FD_OUTER_JOIN:
-        {
-          Outer_join_dep *outer_join_dep= (Outer_join_dep*)bound_dep;
-          mark_as_eliminated(te.join, outer_join_dep->table_list);
-          Outer_join_dep *parent= outer_join_dep->parent;
-          if (parent && 
-              !(parent->missing_tables &= ~outer_join_dep->all_tables))
-          {
-            /* Mark as bound and add to the list */
-            parent->bound= TRUE;
-            parent->next= next;
-            next= parent;
-          }
-          break;
-        }
-        case Func_dep::FD_MULTI_EQUALITY:
-        default:
+              signal_from_field_to_exprs(te, field_dep, &bound_modules);
+            }
+          }
+          for (Outer_join_module *outer_join_dep= table_dep->outer_join_dep;
+               outer_join_dep; outer_join_dep= outer_join_dep->parent)
+          {
+            //if (!(outer_join_dep->missing_tables &= ~table_dep->table->map))
+            if (outer_join_dep->unknown_args && 
+                !--outer_join_dep->unknown_args)
+            {
+              /* Mark as bound and add to the list */
+              outer_join_dep->next= bound_modules;
+              bound_modules= outer_join_dep;
+            }
+          }
+          break;
+        }
+        default: 
           DBUG_ASSERT(0);
       }
-      bound_dep= next;
     }
   }
-  DBUG_VOID_RETURN;
 }
 
 
@@ -1232,7 +1253,7 @@
 }
 
 
-
+#if 0
 #ifndef DBUG_OFF
 static 
 void dbug_print_deps(Table_elimination *te)
@@ -1243,7 +1264,7 @@
   fprintf(DBUG_FILE,"deps {\n");
   
   /* Start with printing equalities */
-  for (Equality_dep *eq_dep= te->equality_deps; 
+  for (Equality_module *eq_dep= te->equality_deps; 
        eq_dep != te->equality_deps + te->n_equality_deps; eq_dep++)
   {
     char buf[128];
@@ -1261,13 +1282,13 @@
   /* Then tables and their fields */
   for (uint i=0; i < MAX_TABLES; i++)
   {
-    Table_dep *table_dep;
+    Table_value *table_dep;
     if ((table_dep= te->table_deps[i]))
     {
       /* Print table */
       fprintf(DBUG_FILE, "  table %s\n", table_dep->table->alias);
       /* Print fields */
-      for (Field_dep *field_dep= table_dep->fields; field_dep; 
+      for (Field_value *field_dep= table_dep->fields; field_dep; 
            field_dep= field_dep->next_table_field)
       {
         fprintf(DBUG_FILE, "    field %s.%s ->", table_dep->table->alias,
@@ -1288,7 +1309,7 @@
 }
 
 #endif 
-
+#endif 
 /**
   @} (end of group Table_Elimination)
 */