sort_keyuse(KEYUSE *a,KEYUSE *b)
{
  int res;
  if (a->table->tablenr != b->table->tablenr)
    return (int) (a->table->tablenr - b->table->tablenr);
  if (a->key != b->key)
    return (int) (a->key - b->key);
  if (a->key == MAX_KEY && b->key == MAX_KEY &&
      a->used_tables != b->used_tables)
    return (int) ((ulong) a->used_tables - (ulong) b->used_tables);
  if (a->keypart != b->keypart)
    return (int) (a->keypart - b->keypart);
  // Place const values before other ones
  if ((res= MY_TEST((a->used_tables & ~OUTER_REF_TABLE_BIT)) -
       MY_TEST((b->used_tables & ~OUTER_REF_TABLE_BIT))))
    return res;
  /* Place rows that are not 'OPTIMIZE_REF_OR_NULL' first */
  return (int) ((a->optimize & KEY_OPTIMIZE_REF_OR_NULL) -
		(b->optimize & KEY_OPTIMIZE_REF_OR_NULL));
}


Field *Item::create_tmp_field_int(TABLE *table, uint convert_int_length)
{
  const Type_handler *h= &type_handler_long;
  if (max_char_length() > convert_int_length)
    h= &type_handler_longlong;
  return h->make_and_init_table_field(&name, Record_addr(maybe_null),
                                      *this, table);
}

MDEV-22464 Server crash on UPDATE with nested subquery

Uninitialized ref_pointer_array[] because setup_fields() got empty
fields list.  mysql_multi_update() for some reason does that by
substituting the fields list with empty total_list for the
mysql_select() call (looks like wrong merge since total_list is not
used anywhere else and is always empty). The fix would be to return
back the original fields list. But this fails update_use_source.test
case:

  --error ER_BAD_FIELD_ERROR
  update v1 set t1c1=2 order by 1;

Actually not failing the above seems to be ok.

The other fix would be to keep resolve_in_select_list false (and that
keeps outer context from being resolved in
Item_ref::fix_fields()). This fix is more consistent with how SELECT
behaves:

  --error ER_SUBQUERY_NO_1_ROW
  select a from t1 where a= (select 2 from t1 having (a = 3));

So this patch implements this fix.


join_read_next_same(READ_RECORD *info)
{
  int error;
  TABLE *table= info->table;
  JOIN_TAB *tab=table->reginfo.join_tab;

  if (unlikely((error= table->file->ha_index_next_same(table->record[0],
                                                       tab->ref.key_buff,
                                                       tab->ref.key_length))))
  {
    if (error != HA_ERR_END_OF_FILE)
      return report_error(table, error);
    table->status= STATUS_GARBAGE;
    return -1;
  }
  return 0;
}


static void update_const_equal_items(THD *thd, COND *cond, JOIN_TAB *tab,
                                     bool const_key)
{
  if (!(cond->used_tables() & tab->table->map))
    return;

  if (cond->type() == Item::COND_ITEM)
  {
    List<Item> *cond_list= ((Item_cond*) cond)->argument_list();
    List_iterator_fast<Item> li(*cond_list);
    Item *item;
    while ((item= li++))
      update_const_equal_items(thd, item, tab,
                               (((Item_cond*) cond)->top_level() &&
                                ((Item_cond*) cond)->functype() ==
                                Item_func::COND_AND_FUNC));
  }
  else if (cond->type() == Item::FUNC_ITEM &&
           ((Item_cond*) cond)->functype() == Item_func::MULT_EQUAL_FUNC)
  {
    Item_equal *item_equal= (Item_equal *) cond;
    bool contained_const= item_equal->get_const() != NULL;
    item_equal->update_const(thd);
    if (!contained_const && item_equal->get_const())
    {
      /* Update keys for range analysis */
      Item_equal_fields_iterator it(*item_equal);
      while (it++)
      {
        Field *field= it.get_curr_field();
        JOIN_TAB *stat= field->table->reginfo.join_tab;
        key_map possible_keys= field->key_start;
        possible_keys.intersect(field->table->keys_in_use_for_query);
        stat[0].const_keys.merge(possible_keys);

        /*
          For each field in the multiple equality (for which we know that it
          is a constant) we have to find its corresponding key part, and set
          that key part in const_key_parts.
        */
        if (!possible_keys.is_clear_all())
        {
          TABLE *field_tab= field->table;
          KEYUSE *use;
          for (use= stat->keyuse; use && use->table == field_tab; use++)
            if (const_key &&
                !use->is_for_hash_join() && possible_keys.is_set(use->key) &&
                field_tab->key_info[use->key].key_part[use->keypart].field ==
                field)
              field_tab->const_key_parts[use->key]|= use->keypart_map;
        }
      }
    }
  }
}


static int test_if_order_by_key(JOIN *join,
                                ORDER *order, TABLE *table, uint idx,
				uint *used_key_parts)
{
  KEY_PART_INFO *key_part,*key_part_end;
  key_part=table->key_info[idx].key_part;
  key_part_end=key_part + table->key_info[idx].ext_key_parts;
  key_part_map const_key_parts=table->const_key_parts[idx];
  uint user_defined_kp= table->key_info[idx].user_defined_key_parts;
  int reverse=0;
  uint key_parts;
  bool have_pk_suffix= false;
  uint pk= table->s->primary_key;
  DBUG_ENTER("test_if_order_by_key");

  if ((table->file->ha_table_flags() & HA_PRIMARY_KEY_IN_READ_INDEX) &&
      table->key_info[idx].ext_key_part_map &&
      pk != MAX_KEY && pk != idx)
  {
    have_pk_suffix= true;
  }

  for (; order ; order=order->next, const_key_parts>>=1)
  {
    Item_field *item_field= ((Item_field*) (*order->item)->real_item());
    Field *field= item_field->field;
    int flag;

    /*
      Skip key parts that are constants in the WHERE clause.
      These are already skipped in the ORDER BY by const_expression_in_where()
    */
    for (; const_key_parts & 1 ; const_key_parts>>= 1)
      key_part++;

    /*
      This check was in this function historically (although I think it's
      better to check it outside of this function):

      "Test if the primary key parts were all const (i.e. there's one row).
       The sorting doesn't matter"

       So, we're checking that
       (1) this is an extended key
       (2) we've reached its end
    */
    key_parts= (uint)(key_part - table->key_info[idx].key_part);
    if (have_pk_suffix &&
        reverse == 0 && // all were =const so far
        key_parts == table->key_info[idx].ext_key_parts &&
        table->const_key_parts[pk] == PREV_BITS(uint,
                                                table->key_info[pk].
                                                user_defined_key_parts))
    {
      key_parts= 0;
      reverse= 1;                           // Key is ok to use
      goto ok;
    }

    if (key_part == key_part_end)
    {
      /*
        There are some items left in ORDER BY that we don't
      */
      DBUG_RETURN(0);
    }

    if (key_part->field != field)
    {
      /*
        Check if there is a multiple equality that allows to infer that field
        and key_part->field are equal
        (see also: compute_part_of_sort_key_for_equals)
      */
      if (item_field->item_equal &&
          item_field->item_equal->contains(key_part->field))
        field= key_part->field;
    }
    if (key_part->field != field || !field->part_of_sortkey.is_set(idx))
      DBUG_RETURN(0);

    const ORDER::enum_order keypart_order=
      (key_part->key_part_flag & HA_REVERSE_SORT) ?
      ORDER::ORDER_DESC : ORDER::ORDER_ASC;
    /* set flag to 1 if we can use read-next on key, else to -1 */
    flag= (order->direction == keypart_order) ? 1 : -1;
    if (reverse && flag != reverse)
      DBUG_RETURN(0);
    reverse=flag;				// Remember if reverse
    if (key_part < key_part_end)
      key_part++;
  }

  key_parts= (uint) (key_part - table->key_info[idx].key_part);

  if (reverse == -1 &&
      !(table->file->index_flags(idx, user_defined_kp-1, 1) & HA_READ_PREV))
    reverse= 0;                               // Index can't be used

  if (have_pk_suffix && reverse == -1)
  {
    uint pk_parts= table->key_info[pk].user_defined_key_parts;
    if (!(table->file->index_flags(pk, pk_parts, 1) & HA_READ_PREV))
      reverse= 0;                               // Index can't be used
  }

ok:
  if (used_key_parts != NULL)
    *used_key_parts= key_parts;
  DBUG_RETURN(reverse);
}


static void print_table_array(THD *thd,
                              table_map eliminated_tables,
                              String *str, TABLE_LIST **table,
                              TABLE_LIST **end,
                              enum_query_type query_type)
{
  (*table)->print(thd, eliminated_tables, str, query_type);

  for (TABLE_LIST **tbl= table + 1; tbl < end; tbl++)
  {
    TABLE_LIST *curr= *tbl;

    /*
      The "eliminated_tables &&" check guards againist the case of
      printing the query for CREATE VIEW. We do that without having run
      JOIN::optimize() and so will have nested_join->used_tables==0.
    */
    if (eliminated_tables &&
        ((curr->table && (curr->table->map & eliminated_tables)) ||
         (curr->nested_join && !(curr->nested_join->used_tables &
                                ~eliminated_tables))))
    {
      /* as of 5.5, print_join doesnt put eliminated elements into array */
      DBUG_ASSERT(0);
      continue;
    }

    /* JOIN_TYPE_OUTER is just a marker unrelated to real join */
    if (curr->outer_join & (JOIN_TYPE_LEFT|JOIN_TYPE_RIGHT))
    {
      /* MySQL converts right to left joins */
      str->append(STRING_WITH_LEN(" left join "));
    }
    else if (curr->straight)
      str->append(STRING_WITH_LEN(" straight_join "));
    else if (curr->sj_inner_tables)
      str->append(STRING_WITH_LEN(" semi join "));
    else
      str->append(STRING_WITH_LEN(" join "));

    curr->print(thd, eliminated_tables, str, query_type);
    if (curr->on_expr)
    {
      str->append(STRING_WITH_LEN(" on("));
      curr->on_expr->print(str, query_type);
      str->append(')');
    }
  }
}


make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
{
  THD *thd= join->thd;
  DBUG_ENTER("make_join_select");
  if (select)
  {
    add_not_null_conds(join);
    table_map used_tables;
    /*
      Step #1: Extract constant condition
       - Extract and check the constant part of the WHERE
       - Extract constant parts of ON expressions from outer
         joins and attach them appropriately.
    */
    if (cond)                /* Because of QUICK_GROUP_MIN_MAX_SELECT */
    {                        /* there may be a select without a cond. */
      if (join->table_count > 1)
        cond->update_used_tables();		// Tablenr may have changed

      /*
        Extract expressions that depend on constant tables
        1. Const part of the join's WHERE clause can be checked immediately
           and if it is not satisfied then the join has empty result
        2. Constant parts of outer joins' ON expressions must be attached
           there inside the triggers.
      */
      {						// Check const tables
        join->exec_const_cond=
	  make_cond_for_table(thd, cond,
                              join->const_table_map,
                              (table_map) 0, -1, FALSE, FALSE);
        /* Add conditions added by add_not_null_conds(). */
        for (uint i= 0 ; i < join->const_tables ; i++)
          add_cond_and_fix(thd, &join->exec_const_cond,
                           join->join_tab[i].select_cond);

        DBUG_EXECUTE("where",print_where(join->exec_const_cond,"constants",
					 QT_ORDINARY););
        if (join->exec_const_cond && !join->exec_const_cond->is_expensive() &&
            !join->exec_const_cond->val_int())
        {
          DBUG_PRINT("info",("Found impossible WHERE condition"));
          join->exec_const_cond= NULL;
          DBUG_RETURN(1);	 // Impossible const condition
        }

        if (join->table_count != join->const_tables)
        {
          COND *outer_ref_cond= make_cond_for_table(thd, cond,
                                                    join->const_table_map |
                                                    OUTER_REF_TABLE_BIT,
                                                    OUTER_REF_TABLE_BIT,
                                                    -1, FALSE, FALSE);
          if (outer_ref_cond)
          {
            add_cond_and_fix(thd, &outer_ref_cond, join->outer_ref_cond);
            join->outer_ref_cond= outer_ref_cond;
          }
        }
        else
        {
          COND *pseudo_bits_cond=
            make_cond_for_table(thd, cond,
                                join->const_table_map |
                                PSEUDO_TABLE_BITS,
                                PSEUDO_TABLE_BITS,
                                -1, FALSE, FALSE);
          if (pseudo_bits_cond)
          {
            add_cond_and_fix(thd, &pseudo_bits_cond,
                             join->pseudo_bits_cond);
            join->pseudo_bits_cond= pseudo_bits_cond;
          }
        }
      }
    }

    /*
      Step #2: Extract WHERE/ON parts
    */
    uint i;
    for (i= join->top_join_tab_count - 1; i >= join->const_tables; i--)
    {
      if (!join->join_tab[i].bush_children)
        break;
    }
    uint last_top_base_tab_idx= i;

    table_map save_used_tables= 0;
    used_tables=((select->const_tables=join->const_table_map) |
		 OUTER_REF_TABLE_BIT | RAND_TABLE_BIT);
    JOIN_TAB *tab;
    table_map current_map;
    i= join->const_tables;
    for (tab= first_depth_first_tab(join); tab;
         tab= next_depth_first_tab(join, tab))
    {
      bool is_hj;

      /*
        first_inner is the X in queries like:
        SELECT * FROM t1 LEFT OUTER JOIN (t2 JOIN t3) ON X
      */
      JOIN_TAB *first_inner_tab= tab->first_inner;

      if (!tab->bush_children)
        current_map= tab->table->map;
      else
        current_map= tab->bush_children->start->emb_sj_nest->sj_inner_tables;

      bool use_quick_range=0;
      COND *tmp;

      /*
        Tables that are within SJ-Materialization nests cannot have their
        conditions referring to preceding non-const tables.
         - If we're looking at the first SJM table, reset used_tables
           to refer to only allowed tables
      */
      if (tab->emb_sj_nest && tab->emb_sj_nest->sj_mat_info &&
          tab->emb_sj_nest->sj_mat_info->is_used &&
          !(used_tables & tab->emb_sj_nest->sj_inner_tables))
      {
        save_used_tables= used_tables;
        used_tables= join->const_table_map | OUTER_REF_TABLE_BIT |
                     RAND_TABLE_BIT;
      }

      used_tables|=current_map;

      if (tab->type == JT_REF && tab->quick &&
	  (((uint) tab->ref.key == tab->quick->index &&
	    tab->ref.key_length < tab->quick->max_used_key_length) ||
           (!is_hash_join_key_no(tab->ref.key) &&
            tab->table->intersect_keys.is_set(tab->ref.key))))
      {
	/* Range uses longer key;  Use this instead of ref on key */
	tab->type=JT_ALL;
	use_quick_range=1;
	tab->use_quick=1;
        tab->ref.key= -1;
	tab->ref.key_parts=0;		// Don't use ref key.
	join->best_positions[i].records_read= rows2double(tab->quick->records);
        /*
          We will use join cache here : prevent sorting of the first
          table only and sort at the end.
        */
        if (i != join->const_tables &&
            join->table_count > join->const_tables + 1 &&
            join->best_positions[i].use_join_buffer)
          join->full_join= 1;
      }

      tmp= NULL;

      if (cond)
      {
        if (tab->bush_children)
        {
          // Reached the materialization tab
          tmp= make_cond_after_sjm(thd, cond, cond, save_used_tables,
                                   used_tables, /*inside_or_clause=*/FALSE);
          used_tables= save_used_tables | used_tables;
          save_used_tables= 0;
        }
        else
        {
          tmp= make_cond_for_table(thd, cond, used_tables, current_map, i,
                                   FALSE, FALSE);
          if (tab == join->join_tab + last_top_base_tab_idx)
          {
            /*
              This pushes conjunctive conditions of WHERE condition such that:
              - their used_tables() contain RAND_TABLE_BIT
              - the conditions does not refer to any fields
              (such like rand() > 0.5)
            */
            table_map rand_table_bit= (table_map) RAND_TABLE_BIT;
            COND *rand_cond= make_cond_for_table(thd, cond, used_tables,
                                                 rand_table_bit, -1,
                                                 FALSE, FALSE);
            add_cond_and_fix(thd, &tmp, rand_cond);
          }
        }
        /* Add conditions added by add_not_null_conds(). */
        if (tab->select_cond)
          add_cond_and_fix(thd, &tmp, tab->select_cond);
      }

      is_hj= (tab->type == JT_REF || tab->type == JT_EQ_REF) &&
             (join->allowed_join_cache_types & JOIN_CACHE_HASHED_BIT) &&
	     ((join->max_allowed_join_cache_level+1)/2 == 2 ||
              ((join->max_allowed_join_cache_level+1)/2 > 2 &&
	       is_hash_join_key_no(tab->ref.key))) &&
              (!tab->emb_sj_nest ||
               join->allowed_semijoin_with_cache) &&
              (!(tab->table->map & join->outer_join) ||
               join->allowed_outer_join_with_cache);

      if (cond && !tmp && tab->quick)
      {						// Outer join
        if (tab->type != JT_ALL && !is_hj)
        {
          /*
            Don't use the quick method
            We come here in the case where we have 'key=constant' and
            the test is removed by make_cond_for_table()
          */
          delete tab->quick;
          tab->quick= 0;
        }
        else
        {
          /*
            Hack to handle the case where we only refer to a table
            in the ON part of an OUTER JOIN. In this case we want the code
            below to check if we should use 'quick' instead.
          */
          DBUG_PRINT("info", ("Item_int"));
          tmp= new (thd->mem_root) Item_int(thd, (longlong) 1, 1); // Always true
        }

      }
      if (tmp || !cond || tab->type == JT_REF || tab->type == JT_REF_OR_NULL ||
          tab->type == JT_EQ_REF || first_inner_tab)
      {
        DBUG_EXECUTE("where",print_where(tmp,
                                         tab->table? tab->table->alias.c_ptr() :"sjm-nest",
                                         QT_ORDINARY););
	SQL_SELECT *sel= tab->select= ((SQL_SELECT*)
                                       thd->memdup((uchar*) select,
                                                   sizeof(*select)));
	if (!sel)
	  DBUG_RETURN(1);			// End of memory
        /*
          If tab is an inner table of an outer join operation,
          add a match guard to the pushed down predicate.
          The guard will turn the predicate on only after
          the first match for outer tables is encountered.
	*/
        if (cond && tmp)
        {
          /*
            Because of QUICK_GROUP_MIN_MAX_SELECT there may be a select without
            a cond, so neutralize the hack above.
          */
          COND *tmp_cond;
          if (!(tmp_cond= add_found_match_trig_cond(thd, first_inner_tab, tmp,
                                                    0)))
            DBUG_RETURN(1);
          sel->cond= tmp_cond;
          tab->set_select_cond(tmp_cond, __LINE__);
          /* Push condition to storage engine if this is enabled
             and the condition is not guarded */
          if (tab->table)
          {
            tab->table->file->pushed_cond= NULL;
            if ((tab->table->file->ha_table_flags() &
                  HA_CAN_TABLE_CONDITION_PUSHDOWN) &&
                !first_inner_tab)
            {
              COND *push_cond=
              make_cond_for_table(thd, tmp_cond, current_map, current_map,
                                  -1, FALSE, FALSE);
              if (push_cond)
              {
                /* Push condition to handler */
                if (!tab->table->file->cond_push(push_cond))
                  tab->table->file->pushed_cond= push_cond;
              }
            }
          }
        }
        else
        {
          sel->cond= NULL;
          tab->set_select_cond(NULL, __LINE__);
        }

	sel->head=tab->table;
        DBUG_EXECUTE("where",
                     print_where(tmp,
                                 tab->table ? tab->table->alias.c_ptr() :
                                   "(sjm-nest)",
                                 QT_ORDINARY););
	if (tab->quick)
	{
	  /* Use quick key read if it's a constant and it's not used
	     with key reading */
          if ((tab->needed_reg.is_clear_all() && tab->type != JT_EQ_REF &&
              tab->type != JT_FT &&
              ((tab->type != JT_CONST && tab->type != JT_REF) ||
               (uint) tab->ref.key == tab->quick->index)) || is_hj)
          {
            DBUG_ASSERT(tab->quick->is_valid());
	    sel->quick=tab->quick;		// Use value from get_quick_...
	    sel->quick_keys.clear_all();
	    sel->needed_reg.clear_all();
	  }
	  else
	  {
	    delete tab->quick;
	  }
	  tab->quick=0;
	}
	uint ref_key= sel->head? (uint) sel->head->reginfo.join_tab->ref.key+1 : 0;
	if (i == join->const_tables && ref_key)
	{
	  if (!tab->const_keys.is_clear_all() &&
              tab->table->reginfo.impossible_range)
	    DBUG_RETURN(1);
	}
	else if (tab->type == JT_ALL && ! use_quick_range)
	{
	  if (!tab->const_keys.is_clear_all() &&
	      tab->table->reginfo.impossible_range)
	    DBUG_RETURN(1);				// Impossible range
	  /*
	    We plan to scan all rows.
	    Check again if we should use an index.

            There are two cases:
            1) There could be an index usage the refers to a previous
               table that we didn't consider before, but could be consider
               now as a "last resort". For example
               SELECT * from t1,t2 where t1.a between t2.a and t2.b;
            2) If the current table is the first non const table
               and there is a limit it still possibly beneficial
               to use the index even if the index range is big as
               we can stop when we've found limit rows.

            (1) - Don't switch the used index if we are using semi-join
                  LooseScan on this table. Using different index will not
                  produce the desired ordering and de-duplication.
	  */

	  if (!tab->table->is_filled_at_execution() &&
              !tab->loosescan_match_tab &&              // (1)
              ((cond && (!tab->keys.is_subset(tab->const_keys) && i > 0)) ||
               (!tab->const_keys.is_clear_all() && i == join->const_tables &&
                join->unit->select_limit_cnt <
                join->best_positions[i].records_read &&
                !(join->select_options & OPTION_FOUND_ROWS))))
	  {
	    /* Join with outer join condition */
	    COND *orig_cond=sel->cond;

            if (build_tmp_join_prefix_cond(join, tab, &sel->cond))
              return true;

	    /*
              We can't call sel->cond->fix_fields,
              as it will break tab->on_expr if it's AND condition
              (fix_fields currently removes extra AND/OR levels).
              Yet attributes of the just built condition are not needed.
              Thus we call sel->cond->quick_fix_field for safety.
	    */
	    if (sel->cond && !sel->cond->fixed)
	      sel->cond->quick_fix_field();

	    if (sel->test_quick_select(thd, tab->keys,
				       ((used_tables & ~ current_map) |
                                        OUTER_REF_TABLE_BIT),
				       (join->select_options &
					OPTION_FOUND_ROWS ?
					HA_POS_ERROR :
					join->unit->select_limit_cnt), 0,
                                        FALSE, FALSE) < 0)
            {
	      /*
		Before reporting "Impossible WHERE" for the whole query
		we have to check isn't it only "impossible ON" instead
	      */
              sel->cond=orig_cond;
              if (!*tab->on_expr_ref ||
                  sel->test_quick_select(thd, tab->keys,
                                         used_tables & ~ current_map,
                                         (join->select_options &
                                          OPTION_FOUND_ROWS ?
                                          HA_POS_ERROR :
                                          join->unit->select_limit_cnt),0,
                                          FALSE, FALSE) < 0)
		DBUG_RETURN(1);			// Impossible WHERE
            }
            else
	      sel->cond=orig_cond;

	    /* Fix for EXPLAIN */
	    if (sel->quick)
	      join->best_positions[i].records_read= (double)sel->quick->records;
	  }
	  else
	  {
	    sel->needed_reg=tab->needed_reg;
	  }
	  sel->quick_keys= tab->table->quick_keys;
	  if (!sel->quick_keys.is_subset(tab->checked_keys) ||
              !sel->needed_reg.is_subset(tab->checked_keys))
	  {
            /*
              "Range checked for each record" is a "last resort" access method
              that should only be used when the other option is a cross-product
              join.

              We use the following condition (it's approximate):
              1. There are potential keys for (sel->needed_reg)
              2. There were no possible ways to construct a quick select, or
                 the quick select would be more expensive than the full table
                 scan.
            */
	    tab->use_quick= (!sel->needed_reg.is_clear_all() &&
			     (sel->quick_keys.is_clear_all() ||
                              (sel->quick &&
                               sel->quick->read_time >
                               tab->table->file->scan_time() +
                               tab->table->file->stats.records/TIME_FOR_COMPARE
                               ))) ?
	      2 : 1;
	    sel->read_tables= used_tables & ~current_map;
            sel->quick_keys.clear_all();
	  }
	  if (i != join->const_tables && tab->use_quick != 2 &&
              !tab->first_inner)
	  {					/* Read with cache */
            /*
              TODO: the execution also gets here when we will not be using
              join buffer. Review these cases and perhaps, remove this call.
              (The final decision whether to use join buffer is made in
              check_join_cache_usage, so we should only call make_scan_filter()
              there, too).
            */
            if (tab->make_scan_filter())
              DBUG_RETURN(1);
          }
	}
      }

      /*
        Push down conditions from all ON expressions.
        Each of these conditions are guarded by a variable
        that turns if off just before null complemented row for
        outer joins is formed. Thus, the condition from an
        'on expression' are guaranteed not to be checked for
        the null complemented row.
      */

      /*
        First push down constant conditions from ON expressions.
         - Each pushed-down condition is wrapped into trigger which is
           enabled only for non-NULL-complemented record
         - The condition is attached to the first_inner_table.

        With regards to join nests:
         - if we start at top level, don't walk into nests
         - if we start inside a nest, stay within that nest.
      */
      JOIN_TAB *start_from= tab->bush_root_tab?
                               tab->bush_root_tab->bush_children->start :
                               join->join_tab + join->const_tables;
      JOIN_TAB *end_with= tab->bush_root_tab?
                               tab->bush_root_tab->bush_children->end :
                               join->join_tab + join->top_join_tab_count;
      for (JOIN_TAB *join_tab= start_from;
           join_tab != end_with;
           join_tab++)
      {
        if (*join_tab->on_expr_ref)
        {
          JOIN_TAB *cond_tab= join_tab->first_inner;
          COND *tmp_cond= make_cond_for_table(thd, *join_tab->on_expr_ref,
                                              join->const_table_map,
                                              (table_map) 0, -1, FALSE, FALSE);
          if (!tmp_cond)
            continue;
          tmp_cond= new (thd->mem_root) Item_func_trig_cond(thd, tmp_cond,
                                            &cond_tab->not_null_compl);
          if (!tmp_cond)
            DBUG_RETURN(1);
          tmp_cond->quick_fix_field();
          cond_tab->select_cond= !cond_tab->select_cond ? tmp_cond :
                                 new (thd->mem_root) Item_cond_and(thd, cond_tab->select_cond,
                                                   tmp_cond);
          if (!cond_tab->select_cond)
	    DBUG_RETURN(1);
          cond_tab->select_cond->quick_fix_field();
          cond_tab->select_cond->update_used_tables();
          if (cond_tab->select)
            cond_tab->select->cond= cond_tab->select_cond;
        }
      }

      /* Push down non-constant conditions from ON expressions */
      JOIN_TAB *last_tab= tab;

      /*
        while we're inside of an outer join and last_tab is
        the last of its tables ...
      */
      while (first_inner_tab && first_inner_tab->last_inner == last_tab)
      {
        /*
          Table tab is the last inner table of an outer join.
          An on expression is always attached to it.
	*/
        COND *on_expr= *first_inner_tab->on_expr_ref;

        table_map used_tables2= (join->const_table_map |
                                 OUTER_REF_TABLE_BIT | RAND_TABLE_BIT);

        start_from= tab->bush_root_tab?
                      tab->bush_root_tab->bush_children->start :
                      join->join_tab + join->const_tables;
        for (JOIN_TAB *inner_tab= start_from;
             inner_tab <= last_tab;
             inner_tab++)
        {
          DBUG_ASSERT(inner_tab->table);
          current_map= inner_tab->table->map;
          used_tables2|= current_map;
          /*
            psergey: have put the -1 below. It's bad, will need to fix it.
          */
          COND *tmp_cond= make_cond_for_table(thd, on_expr, used_tables2,
                                              current_map,
                                              /*(inner_tab - first_tab)*/ -1,
					      FALSE, FALSE);
          if (tab == last_tab)
          {
            /*
              This pushes conjunctive conditions of ON expression of an outer
              join such that:
              - their used_tables() contain RAND_TABLE_BIT
              - the conditions does not refer to any fields
              (such like rand() > 0.5)
            */
            table_map rand_table_bit= (table_map) RAND_TABLE_BIT;
            COND *rand_cond= make_cond_for_table(thd, on_expr, used_tables2,
                                                 rand_table_bit, -1,
                                                 FALSE, FALSE);
            add_cond_and_fix(thd, &tmp_cond, rand_cond);
          }
          bool is_sjm_lookup_tab= FALSE;
          if (inner_tab->bush_children)
          {
            /*
              'inner_tab' is an SJ-Materialization tab, i.e. we have a join
              order like this:

                ot1 sjm_tab LEFT JOIN ot2 ot3
                         ^          ^
                   'tab'-+          +--- left join we're adding triggers for

              LEFT JOIN's ON expression may not have references to subquery
              columns.  The subquery was in the WHERE clause, so IN-equality
              is in the WHERE clause, also.
              However, equality propagation code may have propagated the
              IN-equality into ON expression, and we may get things like

                subquery_inner_table=const

              in the ON expression. We must not check such conditions during
              SJM-lookup, because 1) subquery_inner_table has no valid current
              row (materialization temp.table has it instead), and 2) they
              would be true anyway.
            */
            SJ_MATERIALIZATION_INFO *sjm=
              inner_tab->bush_children->start->emb_sj_nest->sj_mat_info;
            if (sjm->is_used && !sjm->is_sj_scan)
              is_sjm_lookup_tab= TRUE;
          }

          if (inner_tab == first_inner_tab && inner_tab->on_precond &&
              !is_sjm_lookup_tab)
            add_cond_and_fix(thd, &tmp_cond, inner_tab->on_precond);
          if (tmp_cond && !is_sjm_lookup_tab)
          {
            JOIN_TAB *cond_tab=  (inner_tab < first_inner_tab ?
                                  first_inner_tab : inner_tab);
            Item **sel_cond_ref= (inner_tab < first_inner_tab ?
                                  &first_inner_tab->on_precond :
                                  &inner_tab->select_cond);
            /*
              First add the guards for match variables of
              all embedding outer join operations.
	    */
            if (!(tmp_cond= add_found_match_trig_cond(thd,
                                                     cond_tab->first_inner,
                                                     tmp_cond,
                                                     first_inner_tab)))
              DBUG_RETURN(1);
            /*
              Now add the guard turning the predicate off for
              the null complemented row.
	    */
            DBUG_PRINT("info", ("Item_func_trig_cond"));
            tmp_cond= new (thd->mem_root) Item_func_trig_cond(thd, tmp_cond,
                                              &first_inner_tab->
                                              not_null_compl);
            DBUG_PRINT("info", ("Item_func_trig_cond %p",
                                tmp_cond));
            if (tmp_cond)
              tmp_cond->quick_fix_field();
	    /* Add the predicate to other pushed down predicates */
            DBUG_PRINT("info", ("Item_cond_and"));
            *sel_cond_ref= !(*sel_cond_ref) ?
                             tmp_cond :
                             new (thd->mem_root) Item_cond_and(thd, *sel_cond_ref, tmp_cond);
            DBUG_PRINT("info", ("Item_cond_and %p",
                                (*sel_cond_ref)));
            if (!(*sel_cond_ref))
              DBUG_RETURN(1);
            (*sel_cond_ref)->quick_fix_field();
            (*sel_cond_ref)->update_used_tables();
            if (cond_tab->select)
              cond_tab->select->cond= cond_tab->select_cond;
          }
        }
        first_inner_tab= first_inner_tab->first_upper;
      }
      if (!tab->bush_children)
        i++;
    }
  }
  DBUG_RETURN(0);
}


end_send_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
	       bool end_of_records)
{
  int idx= -1;
  enum_nested_loop_state ok_code= NESTED_LOOP_OK;
  List<Item> *fields= join_tab ? (join_tab-1)->fields : join->fields;
  DBUG_ENTER("end_send_group");

  if (!join->items3.is_null() && !join->set_group_rpa)
  {
    join->set_group_rpa= true;
    join->set_items_ref_array(join->items3);
  }

  if (!join->first_record || end_of_records ||
      (idx=test_if_group_changed(join->group_fields)) >= 0)
  {
    if (!join->group_sent &&
        (join->first_record ||
         (end_of_records && !join->group && !join->group_optimized_away)))
    {
      if (join->procedure)
	join->procedure->end_group();
      if (idx < (int) join->send_group_parts)
      {
	int error=0;
	if (join->procedure)
	{
	  if (join->having && join->having->val_int() == 0)
	    error= -1;				// Didn't satisfy having
 	  else
	  {
	    if (join->do_send_rows)
	      error=join->procedure->send_row(*fields) ? 1 : 0;
	    join->send_records++;
	  }
	  if (end_of_records && join->procedure->end_of_records())
	    error= 1;				// Fatal error
	}
	else
	{
	  if (!join->first_record)
	  {
            List_iterator_fast<Item> it(*join->fields);
            Item *item;
            /* No matching rows for group function */
            join->clear();

            while ((item= it++))
              item->no_rows_in_result();
	  }
	  if (join->having && join->having->val_int() == 0)
	    error= -1;				// Didn't satisfy having
	  else
	  {
	    if (join->do_send_rows)
            {
	      error=join->result->send_data(*fields);
              if (unlikely(error < 0))
              {
                /* Duplicate row, don't count */
                join->duplicate_rows++;
                error= 0;
              }
            }
	    join->send_records++;
            join->group_sent= true;
	  }
	  if (unlikely(join->rollup.state != ROLLUP::STATE_NONE && error <= 0))
	  {
	    if (join->rollup_send_data((uint) (idx+1)))
	      error= 1;
	  }
	}
	if (unlikely(error > 0))
          DBUG_RETURN(NESTED_LOOP_ERROR);        /* purecov: inspected */
	if (end_of_records)
	  DBUG_RETURN(NESTED_LOOP_OK);
	if (join->send_records >= join->unit->select_limit_cnt &&
	    join->do_send_rows)
	{
	  if (!(join->select_options & OPTION_FOUND_ROWS))
	    DBUG_RETURN(NESTED_LOOP_QUERY_LIMIT); // Abort nicely
	  join->do_send_rows=0;
	  join->unit->select_limit_cnt = HA_POS_ERROR;
        }
        else if (join->send_records >= join->fetch_limit)
        {
          /*
            There is a server side cursor and all rows
            for this fetch request are sent.
          */
          /*
            Preventing code duplication. When finished with the group reset
            the group functions and copy_fields. We fall through. bug #11904
          */
          ok_code= NESTED_LOOP_CURSOR_LIMIT;
        }
      }
    }
    else
    {
      if (end_of_records)
	DBUG_RETURN(NESTED_LOOP_OK);
      join->first_record=1;
      (void) test_if_group_changed(join->group_fields);
    }
    if (idx < (int) join->send_group_parts)
    {
      /*
        This branch is executed also for cursors which have finished their
        fetch limit - the reason for ok_code.
      */
      copy_fields(&join->tmp_table_param);
      if (init_sum_functions(join->sum_funcs, join->sum_funcs_end[idx+1]))
	DBUG_RETURN(NESTED_LOOP_ERROR);
      if (join->procedure)
	join->procedure->add();
      join->group_sent= false;
      DBUG_RETURN(ok_code);
    }
  }
  if (update_sum_func(join->sum_funcs))
    DBUG_RETURN(NESTED_LOOP_ERROR);
  if (join->procedure)
    join->procedure->add();
  DBUG_RETURN(NESTED_LOOP_OK);
}


join_read_next(READ_RECORD *info)
{
  int error;
  if (unlikely((error= info->table->file->ha_index_next(info->record()))))
    return report_error(info->table, error);

  return 0;
}


join_read_key(JOIN_TAB *tab)
{
  return join_read_key2(tab->join->thd, tab, tab->table, &tab->ref);
}


static bool is_eliminated_table(table_map eliminated_tables, TABLE_LIST *tbl)
{
  return eliminated_tables &&
    ((tbl->table && (tbl->table->map & eliminated_tables)) ||
     (tbl->nested_join && !(tbl->nested_join->used_tables &
                            ~eliminated_tables)));
}


bool JOIN_TAB::hash_join_is_possible()
{
  if (type != JT_REF && type != JT_EQ_REF)
    return FALSE;
  if (!is_ref_for_hash_join())
  {
    KEY *keyinfo= table->key_info + ref.key;
    return keyinfo->key_part[0].field->hash_join_is_possible();
  }
  return TRUE;
}


JOIN_TAB *first_top_level_tab(JOIN *join, enum enum_with_const_tables const_tbls)
{
  JOIN_TAB *tab= join->join_tab;
  if (const_tbls == WITHOUT_CONST_TABLES)
  {
    if (join->const_tables == join->table_count || !tab)
      return NULL;
    tab += join->const_tables;
  }
  return tab;
}


bool mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result)
{
  DBUG_ENTER("mysql_explain_union");
  bool res= 0;
  SELECT_LEX *first= unit->first_select();

  for (SELECT_LEX *sl= first; sl; sl= sl->next_select())
  {
    sl->set_explain_type(FALSE);
    sl->options|= SELECT_DESCRIBE;
  }

  if (unit->is_unit_op() || unit->fake_select_lex)
  {
    if (unit->union_needs_tmp_table() && unit->fake_select_lex)
    {
      unit->fake_select_lex->select_number= FAKE_SELECT_LEX_ID; // just for initialization
      unit->fake_select_lex->type= unit_operation_text[unit->common_op()];
      unit->fake_select_lex->options|= SELECT_DESCRIBE;
    }
    if (!(res= unit->prepare(unit->derived, result,
                             SELECT_NO_UNLOCK | SELECT_DESCRIBE)))
      res= unit->exec();
  }
  else
  {
    thd->lex->current_select= first;
    unit->set_limit(unit->global_parameters());
    res= mysql_select(thd,
                      first->table_list.first,
                      first->with_wild, first->item_list,
                      first->where,
                      first->order_list.elements + first->group_list.elements,
                      first->order_list.first,
                      first->group_list.first,
                      first->having,
                      thd->lex->proc_list.first,
                      first->options | thd->variables.option_bits | SELECT_DESCRIBE,
                      result, unit, first);
  }
  DBUG_RETURN(res || thd->is_error());
}


test_if_group_changed(List<Cached_item> &list)
{
  DBUG_ENTER("test_if_group_changed");
  List_iterator<Cached_item> li(list);
  int idx= -1,i;
  Cached_item *buff;

  for (i=(int) list.elements-1 ; (buff=li++) ; i--)
  {
    if (buff->cmp())
      idx=i;
  }
  DBUG_PRINT("info", ("idx: %d", idx));
  DBUG_RETURN(idx);
}


static int compare_embedding_subqueries(JOIN_TAB *jt1, JOIN_TAB *jt2)
{
  /* Determine if the first table is originally from a subquery */
  TABLE_LIST *tbl1= jt1->table->pos_in_table_list;
  uint tbl1_select_no;
  if (tbl1->jtbm_subselect)
  {
    tbl1_select_no=
      tbl1->jtbm_subselect->unit->first_select()->select_number;
  }
  else if (tbl1->embedding && tbl1->embedding->sj_subq_pred)
  {
    tbl1_select_no=
      tbl1->embedding->sj_subq_pred->unit->first_select()->select_number;
  }
  else
    tbl1_select_no= 1; /* Top-level */

  /* Same for the second table */
  TABLE_LIST *tbl2= jt2->table->pos_in_table_list;
  uint tbl2_select_no;
  if (tbl2->jtbm_subselect)
  {
    tbl2_select_no=
      tbl2->jtbm_subselect->unit->first_select()->select_number;
  }
  else if (tbl2->embedding && tbl2->embedding->sj_subq_pred)
  {
    tbl2_select_no=
      tbl2->embedding->sj_subq_pred->unit->first_select()->select_number;
  }
  else
    tbl2_select_no= 1; /* Top-level */

  /*
    Put top-level tables in front. Tables from within subqueries must follow,
    grouped by their owner subquery. We don't care about the order that
    subquery groups are in, because choose_initial_table_order() will re-order
    the groups.
  */
  if (tbl1_select_no != tbl2_select_no)
    return tbl1_select_no > tbl2_select_no ? 1 : -1;
  return 0;
}


join_read_last(JOIN_TAB *tab)
{
  TABLE *table=tab->table;
  int error= 0;
  DBUG_ENTER("join_read_last");

  DBUG_ASSERT(table->no_keyread ||
              !table->covering_keys.is_set(tab->index) ||
              table->file->keyread == tab->index);
  tab->table->status=0;
  tab->read_record.read_record_func= join_read_prev;
  tab->read_record.table=table;
  if (!table->file->inited)
    error= table->file->ha_index_init(tab->index, 1);
  if (likely(!error))
    error= table->file->prepare_index_scan();
  if (unlikely(error) ||
      unlikely(error= tab->table->file->ha_index_last(tab->table->record[0])))
    DBUG_RETURN(report_error(table, error));

  DBUG_RETURN(0);
}


JOIN::add_sorting_to_table(JOIN_TAB *tab, ORDER *order)
{
  tab->filesort=
    new (thd->mem_root) Filesort(order, HA_POS_ERROR, tab->keep_current_rowid,
                                 tab->select);
  if (!tab->filesort)
    return true;
  /*
    Select was moved to filesort->select to force join_init_read_record to use
    sorted result instead of reading table through select.
  */
  if (tab->select)
  {
    tab->select= NULL;
    tab->set_select_cond(NULL, __LINE__);
  }
  tab->read_first_record= join_init_read_record;
  return false;
}


int read_first_record_seq(JOIN_TAB *tab)
{
  if (unlikely(tab->read_record.table->file->ha_rnd_init_with_error(1)))
    return 1;
  return tab->read_record.read_record();
}


static int remove_dup_with_compare(THD *thd, TABLE *table, Field **first_field,
				   Item *having)
{
  handler *file=table->file;
  uchar *record=table->record[0];
  int error;
  DBUG_ENTER("remove_dup_with_compare");

  if (unlikely(file->ha_rnd_init_with_error(1)))
    DBUG_RETURN(1);

  error= file->ha_rnd_next(record);
  for (;;)
  {
    if (unlikely(thd->check_killed()))
    {
      error=0;
      goto err;
    }
    if (unlikely(error))
    {
      if (error == HA_ERR_END_OF_FILE)
	break;
      goto err;
    }
    if (having && !having->val_int())
    {
      if (unlikely((error= file->ha_delete_row(record))))
	goto err;
      error= file->ha_rnd_next(record);
      continue;
    }
    if (unlikely(copy_blobs(first_field)))
    {
      my_message(ER_OUTOFMEMORY, ER_THD(thd,ER_OUTOFMEMORY),
                 MYF(ME_FATALERROR));
      error=0;
      goto err;
    }
    store_record(table,record[1]);

    /* Read through rest of file and mark duplicated rows deleted */
    bool found=0;
    for (;;)
    {
      if (unlikely((error= file->ha_rnd_next(record))))
      {
	if (error == HA_ERR_END_OF_FILE)
	  break;
	goto err;
      }
      if (compare_record(table, first_field) == 0)
      {
	if (unlikely((error= file->ha_delete_row(record))))
	  goto err;
      }
      else if (!found)
      {
	found=1;
        if (unlikely((error= file->remember_rnd_pos())))
          goto err;
      }
    }
    if (!found)
      break;					// End of file
    /* Restart search on saved row */
    if (unlikely((error= file->restart_rnd_next(record))))
      goto err;
  }

  file->extra(HA_EXTRA_NO_CACHE);
  (void) file->ha_rnd_end();
  DBUG_RETURN(0);
err:
  file->extra(HA_EXTRA_NO_CACHE);
  (void) file->ha_rnd_end();
  if (error)
    file->print_error(error,MYF(0));
  DBUG_RETURN(1);
}


JOIN_TAB *first_depth_first_tab(JOIN* join)
{
  JOIN_TAB* tab;
  /* This means we're starting the enumeration */
  if (join->const_tables == join->top_join_tab_count || !join->join_tab)
    return NULL;

  tab= join->join_tab + join->const_tables;

  return (tab->bush_children) ? tab->bush_children->start : tab;
}


Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
                        Item ***copy_func, Field **from_field,
                        Field **default_field,
                        bool group, bool modify_item,
                        bool table_cant_handle_bit_fields,
                        bool make_copy_field)
{
  Field *result;
  Item::Type orig_type= type;
  Item *orig_item= 0;

  DBUG_ASSERT(thd == table->in_use);

  if (type != Item::FIELD_ITEM &&
      item->real_item()->type() == Item::FIELD_ITEM)
  {
    orig_item= item;
    item= item->real_item();
    type= Item::FIELD_ITEM;
  }

  switch (type) {
  case Item::TYPE_HOLDER:
  case Item::SUM_FUNC_ITEM:
  {
    result= item->create_tmp_field(group, table);
    if (!result)
      my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR));
    return result;
  }
  case Item::DEFAULT_VALUE_ITEM:
  {
    Field *field= ((Item_default_value*) item)->field;
    if (field->default_value && (field->flags & BLOB_FLAG))
    {
      /*
        We have to use a copy function when using a blob with default value
        as the we have to calcuate the default value before we can use it.
      */
      return create_tmp_field_from_item(thd, item, table,
                                        (make_copy_field ? 0 : copy_func),
                                        modify_item);
    }
  }
  /* Fall through */
  case Item::FIELD_ITEM:
  case Item::CONTEXTUALLY_TYPED_VALUE_ITEM:
  case Item::INSERT_VALUE_ITEM:
  case Item::TRIGGER_FIELD_ITEM:
  {
    Item_field *field= (Item_field*) item;
    bool orig_modify= modify_item;
    if (orig_type == Item::REF_ITEM)
      modify_item= 0;
    /*
      If item have to be able to store NULLs but underlaid field can't do it,
      create_tmp_field_from_field() can't be used for tmp field creation.
    */
    if (((field->maybe_null && field->in_rollup) ||
	(thd->create_tmp_table_for_derived  &&    /* for mat. view/dt */
	 orig_item && orig_item->maybe_null)) &&
        !field->field->maybe_null())
    {
      bool save_maybe_null= FALSE;
      /*
        The item the ref points to may have maybe_null flag set while
        the ref doesn't have it. This may happen for outer fields
        when the outer query decided at some point after name resolution phase
        that this field might be null. Take this into account here.
      */
      if (orig_item)
      {
        save_maybe_null= item->maybe_null;
        item->maybe_null= orig_item->maybe_null;
      }
      result= create_tmp_field_from_item(thd, item, table, NULL,
                                         modify_item);
      *from_field= field->field;
      if (result && modify_item)
        field->result_field= result;
      if (orig_item)
      {
        item->maybe_null= save_maybe_null;
        result->field_name= orig_item->name;
      }
    }
    else if (table_cant_handle_bit_fields && field->field->type() ==
             MYSQL_TYPE_BIT)
    {
      const Type_handler *handler= item->type_handler_long_or_longlong();
      *from_field= field->field;
      if ((result=
             handler->make_and_init_table_field(&item->name,
                                                Record_addr(item->maybe_null),
                                                *item, table)))
        create_tmp_field_from_item_finalize(thd, result, item,
                                            copy_func, modify_item);
      if (result && modify_item)
        field->result_field= result;
    }
    else
    {
      LEX_CSTRING *tmp= orig_item ? &orig_item->name : &item->name;
      result= create_tmp_field_from_field(thd, (*from_field= field->field),
                                          tmp, table,
                                          modify_item ? field :
                                          NULL);
    }

    if (orig_type == Item::REF_ITEM && orig_modify)
      ((Item_ref*)orig_item)->set_result_field(result);
    /*
      Fields that are used as arguments to the DEFAULT() function already have
      their data pointers set to the default value during name resolution. See
      Item_default_value::fix_fields.
    */
    if (orig_type != Item::DEFAULT_VALUE_ITEM && field->field->eq_def(result))
      *default_field= field->field;
    return result;
  }
  /* Fall through */
  case Item::FUNC_ITEM:
    if (((Item_func *) item)->functype() == Item_func::FUNC_SP)
    {
      Item_func_sp *item_func_sp= (Item_func_sp *) item;
      Field *sp_result_field= item_func_sp->get_sp_result_field();

      if (make_copy_field)
      {
        DBUG_ASSERT(item_func_sp->result_field);
        *from_field= item_func_sp->result_field;
      }
      else
      {
        *((*copy_func)++)= item;
      }
      Field *result_field=
        create_tmp_field_from_field(thd,
                                    sp_result_field,
                                    &item_func_sp->name,
                                    table,
                                    NULL);

      if (modify_item)
        item->set_result_field(result_field);

      return result_field;
    }

    /* Fall through */
  case Item::COND_ITEM:
  case Item::SUBSELECT_ITEM:
  case Item::REF_ITEM:
  case Item::EXPR_CACHE_ITEM:
    if (make_copy_field)
    {
      DBUG_ASSERT(((Item_result_field*)item)->result_field);
      *from_field= ((Item_result_field*)item)->result_field;
    }
    /* Fall through */
  case Item::FIELD_AVG_ITEM:
  case Item::FIELD_STD_ITEM:
  case Item::PROC_ITEM:
  case Item::INT_ITEM:
  case Item::REAL_ITEM:
  case Item::DECIMAL_ITEM:
  case Item::STRING_ITEM:
  case Item::DATE_ITEM:
  case Item::NULL_ITEM:
  case Item::VARBIN_ITEM:
  case Item::CACHE_ITEM:
  case Item::WINDOW_FUNC_ITEM: // psergey-winfunc:
  case Item::PARAM_ITEM:
    return create_tmp_field_from_item(thd, item, table,
                                      (make_copy_field ? 0 : copy_func),
                                       modify_item);
  default:					// Dosen't have to be stored
    return 0;
  }
}


list_contains_unique_index(TABLE *table,
                          bool (*find_func) (Field *, void *), void *data)
{
  for (uint keynr= 0; keynr < table->s->keys; keynr++)
  {
    if (keynr == table->s->primary_key ||
         (table->key_info[keynr].flags & HA_NOSAME))
    {
      KEY *keyinfo= table->key_info + keynr;
      KEY_PART_INFO *key_part, *key_part_end;

      for (key_part=keyinfo->key_part,
           key_part_end=key_part+ keyinfo->user_defined_key_parts;
           key_part < key_part_end;
           key_part++)
      {
        if (key_part->field->maybe_null() ||
            !find_func(key_part->field, data))
          break;
      }
      if (key_part == key_part_end)
        return 1;
    }
  }
  return 0;
}


end_unique_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
		  bool end_of_records)
{
  TABLE *table= join_tab->table;
  int	  error;
  DBUG_ENTER("end_unique_update");

  if (end_of_records)
    DBUG_RETURN(NESTED_LOOP_OK);

  init_tmptable_sum_functions(join->sum_funcs);
  copy_fields(join_tab->tmp_table_param);		// Groups are copied twice.
  if (copy_funcs(join_tab->tmp_table_param->items_to_copy, join->thd))
    DBUG_RETURN(NESTED_LOOP_ERROR);           /* purecov: inspected */

  if (likely(!(error= table->file->ha_write_tmp_row(table->record[0]))))
    join_tab->send_records++;			// New group
  else
  {
    if (unlikely((int) table->file->get_dup_key(error) < 0))
    {
      table->file->print_error(error,MYF(0));	/* purecov: inspected */
      DBUG_RETURN(NESTED_LOOP_ERROR);            /* purecov: inspected */
    }
    /* Prepare table for random positioning */
    bool rnd_inited= (table->file->inited == handler::RND);
    if (!rnd_inited &&
        ((error= table->file->ha_index_end()) ||
         (error= table->file->ha_rnd_init(0))))
    {
      table->file->print_error(error, MYF(0));
      DBUG_RETURN(NESTED_LOOP_ERROR);
    }
    if (unlikely(table->file->ha_rnd_pos(table->record[1],table->file->dup_ref)))
    {
      table->file->print_error(error,MYF(0));	/* purecov: inspected */
      DBUG_RETURN(NESTED_LOOP_ERROR);            /* purecov: inspected */
    }
    restore_record(table,record[1]);
    update_tmptable_sum_func(join->sum_funcs,table);
    if (unlikely((error= table->file->ha_update_tmp_row(table->record[1],
                                                        table->record[0]))))
    {
      table->file->print_error(error,MYF(0));	/* purecov: inspected */
      DBUG_RETURN(NESTED_LOOP_ERROR);            /* purecov: inspected */
    }
    if (!rnd_inited &&
        ((error= table->file->ha_rnd_end()) ||
         (error= table->file->ha_index_init(0, 0))))
    {
      table->file->print_error(error, MYF(0));
      DBUG_RETURN(NESTED_LOOP_ERROR);
    }
  }
  if (unlikely(join->thd->check_killed()))
  {
    DBUG_RETURN(NESTED_LOOP_KILLED);             /* purecov: inspected */
  }
  DBUG_RETURN(NESTED_LOOP_OK);
}


int JOIN::rollup_send_data(uint idx)
{
  uint i;
  for (i= send_group_parts ; i-- > idx ; )
  {
    int res= 0;
    /* Get reference pointers to sum functions in place */
    copy_ref_ptr_array(ref_ptrs, rollup.ref_pointer_arrays[i]);
    if ((!having || having->val_int()))
    {
      if (send_records < unit->select_limit_cnt && do_send_rows &&
	  (res= result->send_data(rollup.fields[i])) > 0)
	return 1;
      if (!res)
        send_records++;
    }
  }
  /* Restore ref_pointer_array */
  set_items_ref_array(current_ref_ptrs);
  return 0;
}


AGGR_OP::put_record(bool end_of_records)
{
  // Lasy tmp table creation/initialization
  if (!join_tab->table->file->inited)
    if (prepare_tmp_table())
      return NESTED_LOOP_ERROR;
  enum_nested_loop_state rc= (*write_func)(join_tab->join, join_tab,
                                           end_of_records);
  return rc;
}


void JOIN::get_partial_cost_and_fanout(int end_tab_idx,
                                       table_map filter_map,
                                       double *read_time_arg,
                                       double *record_count_arg)
{
  double record_count= 1;
  double read_time= 0.0;
  double sj_inner_fanout= 1.0;
  JOIN_TAB *end_tab= NULL;
  JOIN_TAB *tab;
  int i;
  int last_sj_table= MAX_TABLES;

  /*
    Handle a special case where the join is degenerate, and produces no
    records
  */
  if (table_count == const_tables)
  {
    *read_time_arg= 0.0;
    /*
      We return 1, because
       - it is the pessimistic estimate (there might be grouping)
       - it's safer, as we're less likely to hit the edge cases in
         calculations.
    */
    *record_count_arg=1.0;
    return;
  }

  for (tab= first_depth_first_tab(this), i= const_tables;
       tab;
       tab= next_depth_first_tab(this, tab), i++)
  {
    end_tab= tab;
    if (i == end_tab_idx)
      break;
  }

  for (tab= first_depth_first_tab(this), i= const_tables;
       ;
       tab= next_depth_first_tab(this, tab), i++)
  {
    if (end_tab->bush_root_tab && end_tab->bush_root_tab == tab)
    {
      /*
        We've entered the SJM nest that contains the end_tab. The caller is
        - interested in fanout inside the nest (because that's how many times
          we'll invoke the attached WHERE conditions)
        - not interested in cost
      */
      record_count= 1.0;
      read_time= 0.0;
    }

    /*
      Ignore fanout (but not cost) from sj-inner tables, as long as
      the range that processes them finishes before the end_tab
    */
    if (tab->sj_strategy != SJ_OPT_NONE)
    {
      sj_inner_fanout= 1.0;
      last_sj_table= i + tab->n_sj_tables;
    }

    table_map cur_table_map;
    if (tab->table)
      cur_table_map= tab->table->map;
    else
    {
      /* This is a SJ-Materialization nest. Check all of its tables */
      TABLE *first_child= tab->bush_children->start->table;
      TABLE_LIST *sjm_nest= first_child->pos_in_table_list->embedding;
      cur_table_map= sjm_nest->nested_join->used_tables;
    }
    if (tab->records_read && (cur_table_map & filter_map))
    {
      record_count= COST_MULT(record_count, tab->records_read);
      read_time= COST_ADD(read_time,
                          COST_ADD(tab->read_time,
                                   record_count / (double) TIME_FOR_COMPARE));
      if (tab->emb_sj_nest)
        sj_inner_fanout= COST_MULT(sj_inner_fanout, tab->records_read);
				     }

    if (i == last_sj_table)
    {
      record_count /= sj_inner_fanout;
      sj_inner_fanout= 1.0;
      last_sj_table= MAX_TABLES;
    }

    if (tab == end_tab)
      break;
  }
  *read_time_arg= read_time;// + record_count / TIME_FOR_COMPARE;
  *record_count_arg= record_count;
}


count_field_types(SELECT_LEX *select_lex, TMP_TABLE_PARAM *param,
                  List<Item> &fields, bool reset_with_sum_func)
{
  List_iterator<Item> li(fields);
  Item *field;

  param->field_count=param->sum_func_count=param->func_count=
    param->hidden_field_count=0;
  param->quick_group=1;
  while ((field=li++))
  {
    Item::Type real_type= field->real_item()->type();
    if (real_type == Item::FIELD_ITEM)
      param->field_count++;
    else if (real_type == Item::SUM_FUNC_ITEM)
    {
      if (! field->const_item())
      {
	Item_sum *sum_item=(Item_sum*) field->real_item();
        if (!sum_item->depended_from() ||
            sum_item->depended_from() == select_lex)
        {
          if (!sum_item->quick_group)
            param->quick_group=0;			// UDF SUM function
          param->sum_func_count++;

          for (uint i=0 ; i < sum_item->get_arg_count() ; i++)
          {
            if (sum_item->get_arg(i)->real_item()->type() == Item::FIELD_ITEM)
              param->field_count++;
            else
              param->func_count++;
          }
        }
        param->func_count++;
      }
    }
    else
    {
      param->func_count++;
      if (reset_with_sum_func)
	field->with_sum_func=0;
    }
  }
}


setup_tmp_table_column_bitmaps(TABLE *table, uchar *bitmaps, uint field_count)
{
  uint bitmap_size= bitmap_buffer_size(field_count);

  DBUG_ASSERT(table->s->virtual_fields == 0 && table->def_vcol_set == 0);

  my_bitmap_init(&table->def_read_set, (my_bitmap_map*) bitmaps, field_count,
              FALSE);
  bitmaps+= bitmap_size;
  my_bitmap_init(&table->tmp_set,
                 (my_bitmap_map*) bitmaps, field_count, FALSE);
  bitmaps+= bitmap_size;
  my_bitmap_init(&table->eq_join_set,
                 (my_bitmap_map*) bitmaps, field_count, FALSE);
  bitmaps+= bitmap_size;
  my_bitmap_init(&table->cond_set,
                 (my_bitmap_map*) bitmaps, field_count, FALSE);
  bitmaps+= bitmap_size;
  my_bitmap_init(&table->has_value_set,
                 (my_bitmap_map*) bitmaps, field_count, FALSE);
  /* write_set and all_set are copies of read_set */
  table->def_write_set= table->def_read_set;
  table->s->all_set= table->def_read_set;
  bitmap_set_all(&table->s->all_set);
  table->default_column_bitmaps();
}


JOIN_TAB::sort_table()
{
  int rc;
  DBUG_PRINT("info",("Sorting for index"));
  THD_STAGE_INFO(join->thd, stage_creating_sort_index);
  DBUG_ASSERT(join->ordered_index_usage != (filesort->order == join->order ?
                                            JOIN::ordered_index_order_by :
                                            JOIN::ordered_index_group_by));
  rc= create_sort_index(join->thd, join, this, NULL);
  return (rc != 0);
}


static void unclear_tables(JOIN *join, table_map *cleared_tables)
{
  for (uint i= 0 ; i < join->table_count ; i++)
  {
    if ((*cleared_tables) & (((table_map) 1) << i))
    {
      TABLE *table= join->table[i];
      if (table->s->null_bytes)
        memcpy(table->null_flags, table->record[1], table->s->null_bytes);
      unmark_as_null_row(table);
    }
  }
}


join_tab_cmp_embedded_first(const void *emb,  const void* ptr1, const void* ptr2)
{
  const TABLE_LIST *emb_nest= (TABLE_LIST*) emb;
  JOIN_TAB *jt1= *(JOIN_TAB**) ptr1;
  JOIN_TAB *jt2= *(JOIN_TAB**) ptr2;

  if (jt1->emb_sj_nest == emb_nest && jt2->emb_sj_nest != emb_nest)
    return -1;
  if (jt1->emb_sj_nest != emb_nest && jt2->emb_sj_nest == emb_nest)
    return 1;

  if (jt1->dependent & jt2->table->map)
    return 1;
  if (jt2->dependent & jt1->table->map)
    return -1;

  if (jt1->found_records > jt2->found_records)
    return 1;
  if (jt1->found_records < jt2->found_records)
    return -1;

  return jt1 > jt2 ? 1 : (jt1 < jt2 ? -1 : 0);
}


void JOIN::join_free()
{
  SELECT_LEX_UNIT *tmp_unit;
  SELECT_LEX *sl;
  /*
    Optimization: if not EXPLAIN and we are done with the JOIN,
    free all tables.
  */
  bool full= !(select_lex->uncacheable) &&  !(thd->lex->describe);
  bool can_unlock= full;
  DBUG_ENTER("JOIN::join_free");

  cleanup(full);

  for (tmp_unit= select_lex->first_inner_unit();
       tmp_unit;
       tmp_unit= tmp_unit->next_unit())
  {
    if (tmp_unit->with_element && tmp_unit->with_element->is_recursive)
      continue;
    for (sl= tmp_unit->first_select(); sl; sl= sl->next_select())
    {
      Item_subselect *subselect= sl->master_unit()->item;
      bool full_local= full && (!subselect || subselect->is_evaluated());
      /*
        If this join is evaluated, we can fully clean it up and clean up all
        its underlying joins even if they are correlated -- they will not be
        used any more anyway.
        If this join is not yet evaluated, we still must clean it up to
        close its table cursors -- it may never get evaluated, as in case of
        ... HAVING FALSE OR a IN (SELECT ...))
        but all table cursors must be closed before the unlock.
      */
      sl->cleanup_all_joins(full_local);
      /* Can't unlock if at least one JOIN is still needed */
      can_unlock= can_unlock && full_local;
    }
  }
  /*
    We are not using tables anymore
    Unlock all tables. We may be in an INSERT .... SELECT statement.
  */
  if (can_unlock && lock && thd->lock && ! thd->locked_tables_mode &&
      !(select_options & SELECT_NO_UNLOCK) &&
      !select_lex->subquery_in_having &&
      (select_lex == (thd->lex->unit.fake_select_lex ?
                      thd->lex->unit.fake_select_lex : &thd->lex->select_lex)))
  {
    /*
      TODO: unlock tables even if the join isn't top level select in the
      tree.
    */
    mysql_unlock_read_tables(thd, lock);           // Don't free join->lock
    lock= 0;
  }

  DBUG_VOID_RETURN;
}


int JOIN_TAB::make_scan_filter()
{
  COND *tmp;
  DBUG_ENTER("make_scan_filter");

  Item *cond= is_inner_table_of_outer_join() ?
                *get_first_inner_table()->on_expr_ref : join->conds;

  if (cond &&
      (tmp= make_cond_for_table(join->thd, cond,
                               join->const_table_map | table->map,
			       table->map, -1, FALSE, TRUE)))
  {
     DBUG_EXECUTE("where",print_where(tmp,"cache", QT_ORDINARY););
     if (!(cache_select=
          (SQL_SELECT*) join->thd->memdup((uchar*) select, sizeof(SQL_SELECT))))
	DBUG_RETURN(1);
     cache_select->cond= tmp;
     cache_select->read_tables=join->const_table_map;
  }
  DBUG_RETURN(0);
}


void JOIN::set_allowed_join_cache_types()
{
  allowed_join_cache_types= 0;
  if (optimizer_flag(thd, OPTIMIZER_SWITCH_JOIN_CACHE_INCREMENTAL))
    allowed_join_cache_types|= JOIN_CACHE_INCREMENTAL_BIT;
  if (optimizer_flag(thd, OPTIMIZER_SWITCH_JOIN_CACHE_HASHED))
    allowed_join_cache_types|= JOIN_CACHE_HASHED_BIT;
  if (optimizer_flag(thd, OPTIMIZER_SWITCH_JOIN_CACHE_BKA))
    allowed_join_cache_types|= JOIN_CACHE_BKA_BIT;
  allowed_semijoin_with_cache=
    optimizer_flag(thd, OPTIMIZER_SWITCH_SEMIJOIN_WITH_CACHE);
  allowed_outer_join_with_cache=
    optimizer_flag(thd, OPTIMIZER_SWITCH_OUTER_JOIN_WITH_CACHE);
  max_allowed_join_cache_level= thd->variables.join_cache_level;
}


end_write_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
		bool end_of_records)
{
  TABLE *table= join_tab->table;
  int	  idx= -1;
  DBUG_ENTER("end_write_group");

  if (!join->first_record || end_of_records ||
      (idx=test_if_group_changed(join->group_fields)) >= 0)
  {
    if (join->first_record || (end_of_records && !join->group))
    {
      if (join->procedure)
	join->procedure->end_group();
      int send_group_parts= join->send_group_parts;
      if (idx < send_group_parts)
      {
        if (!join->first_record)
        {
          /* No matching rows for group function */
          join->clear();
        }
        copy_sum_funcs(join->sum_funcs,
                       join->sum_funcs_end[send_group_parts]);
	if (!join_tab->having || join_tab->having->val_int())
	{
          int error= table->file->ha_write_tmp_row(table->record[0]);
          if (unlikely(error) &&
              create_internal_tmp_table_from_heap(join->thd, table,
                                          join_tab->tmp_table_param->start_recinfo,
                                          &join_tab->tmp_table_param->recinfo,
                                                   error, 0, NULL))
	    DBUG_RETURN(NESTED_LOOP_ERROR);
        }
        if (unlikely(join->rollup.state != ROLLUP::STATE_NONE))
	{
          if (unlikely(join->rollup_write_data((uint) (idx+1),
                                               join_tab->tmp_table_param,
                                               table)))
          {
	    DBUG_RETURN(NESTED_LOOP_ERROR);
          }
	}
	if (end_of_records)
	  goto end;
      }
    }
    else
    {
      if (end_of_records)
        goto end;
      join->first_record=1;
      (void) test_if_group_changed(join->group_fields);
    }
    if (idx < (int) join->send_group_parts)
    {
      copy_fields(join_tab->tmp_table_param);
      if (unlikely(copy_funcs(join_tab->tmp_table_param->items_to_copy,
                              join->thd)))
	DBUG_RETURN(NESTED_LOOP_ERROR);
      if (unlikely(init_sum_functions(join->sum_funcs,
                                      join->sum_funcs_end[idx+1])))
	DBUG_RETURN(NESTED_LOOP_ERROR);
      if (unlikely(join->procedure))
	join->procedure->add();
      goto end;
    }
  }
  if (unlikely(update_sum_func(join->sum_funcs)))
    DBUG_RETURN(NESTED_LOOP_ERROR);
  if (unlikely(join->procedure))
    join->procedure->add();
end:
  if (unlikely(join->thd->check_killed()))
  {
    DBUG_RETURN(NESTED_LOOP_KILLED);             /* purecov: inspected */
  }
  DBUG_RETURN(NESTED_LOOP_OK);
}


optimize_cond(JOIN *join, COND *conds,
              List<TABLE_LIST> *join_list, bool ignore_on_conds,
              Item::cond_result *cond_value, COND_EQUAL **cond_equal,
              int flags)
{
  THD *thd= join->thd;
  DBUG_ENTER("optimize_cond");

  if (!conds)
  {
    *cond_value= Item::COND_TRUE;
    if (!ignore_on_conds)
      build_equal_items(join, NULL, NULL, join_list, ignore_on_conds,
                        cond_equal);
  }
  else
  {
    /*
      Build all multiple equality predicates and eliminate equality
      predicates that can be inferred from these multiple equalities.
      For each reference of a field included into a multiple equality
      that occurs in a function set a pointer to the multiple equality
      predicate. Substitute a constant instead of this field if the
      multiple equality contains a constant.
    */
    DBUG_EXECUTE("where", print_where(conds, "original", QT_ORDINARY););
    conds= build_equal_items(join, conds, NULL, join_list,
                             ignore_on_conds, cond_equal,
                             MY_TEST(flags & OPT_LINK_EQUAL_FIELDS));
    DBUG_EXECUTE("where",print_where(conds,"after equal_items", QT_ORDINARY););

    /* change field = field to field = const for each found field = const */
    propagate_cond_constants(thd, (I_List<COND_CMP> *) 0, conds, conds);
    /*
      Remove all instances of item == item
      Remove all and-levels where CONST item != CONST item
    */
    DBUG_EXECUTE("where",print_where(conds,"after const change", QT_ORDINARY););
    conds= conds->remove_eq_conds(thd, cond_value, true);
    if (conds && conds->type() == Item::COND_ITEM &&
        ((Item_cond*) conds)->functype() == Item_func::COND_AND_FUNC)
      *cond_equal= &((Item_cond_and*) conds)->m_cond_equal;
    DBUG_EXECUTE("info",print_where(conds,"after remove", QT_ORDINARY););
  }
  DBUG_RETURN(conds);
}


void JOIN_TAB::partial_cleanup()
{
  if (!table)
    return;

  if (table->is_created())
  {
    table->file->ha_index_or_rnd_end();
    DBUG_PRINT("info", ("close index: %s.%s  alias: %s",
               table->s->db.str,
               table->s->table_name.str,
               table->alias.c_ptr()));
    if (aggr)
    {
      int tmp= 0;
      if ((tmp= table->file->extra(HA_EXTRA_NO_CACHE)))
        table->file->print_error(tmp, MYF(0));
    }
  }
  delete filesort_result;
  filesort_result= NULL;
  free_cache(&read_record);
}


static bool change_group_ref(THD *thd, Item_func *expr, ORDER *group_list,
                             bool *changed)
{
  if (expr->argument_count())
  {
    Name_resolution_context *context= &thd->lex->current_select->context;
    Item **arg,**arg_end;
    bool arg_changed= FALSE;
    for (arg= expr->arguments(),
         arg_end= expr->arguments() + expr->argument_count();
         arg != arg_end; arg++)
    {
      Item *item= *arg;
      if (item->type() == Item::FIELD_ITEM || item->type() == Item::REF_ITEM)
      {
        ORDER *group_tmp;
        for (group_tmp= group_list; group_tmp; group_tmp= group_tmp->next)
        {
          if (item->eq(*group_tmp->item,0))
          {
            Item *new_item;
            if (!(new_item= new (thd->mem_root) Item_ref(thd, context,
                                                         group_tmp->item, 0,
                                                         &item->name)))
              return 1;                                 // fatal_error is set
            thd->change_item_tree(arg, new_item);
            arg_changed= TRUE;
          }
        }
      }
      else if (item->type() == Item::FUNC_ITEM)
      {
        if (change_group_ref(thd, (Item_func *) item, group_list, &arg_changed))
          return 1;
      }
    }
    if (arg_changed)
    {
      expr->maybe_null= 1;
      expr->in_rollup= 1;
      *changed= TRUE;
    }
  }
  return 0;
}


join_read_always_key_or_null(JOIN_TAB *tab)
{
  int res;

  /* First read according to key which is NOT NULL */
  *tab->ref.null_ref_key= 0;			// Clear null byte
  if ((res= join_read_always_key(tab)) >= 0)
    return res;

  /* Then read key with null value */
  *tab->ref.null_ref_key= 1;			// Set null byte
  return safe_index_read(tab);
}


get_sort_by_table(ORDER *a,ORDER *b, List<TABLE_LIST> &tables,
                  table_map const_tables)
{
  TABLE_LIST *table;
  List_iterator<TABLE_LIST> ti(tables);
  table_map map= (table_map) 0;
  DBUG_ENTER("get_sort_by_table");

  if (!a)
    a=b;					// Only one need to be given
  else if (!b)
    b=a;

  for (; a && b; a=a->next,b=b->next)
  {
    /* Skip elements of a that are constant */
    while (!((*a->item)->used_tables() & ~const_tables))
    {
      if (!(a= a->next))
        break;
    }

    /* Skip elements of b that are constant */
    while (!((*b->item)->used_tables() & ~const_tables))
    {
      if (!(b= b->next))
        break;
    }

    if (!a || !b)
      break;

    if (!(*a->item)->eq(*b->item,1))
      DBUG_RETURN(0);
    map|=a->item[0]->used_tables();
  }
  if (!map || (map & (RAND_TABLE_BIT | OUTER_REF_TABLE_BIT)))
    DBUG_RETURN(0);

  map&= ~const_tables;
  while ((table= ti++) && !(map & table->table->map)) ;
  if (map != table->table->map)
    DBUG_RETURN(0);				// More than one table
  DBUG_PRINT("exit",("sort by table: %d",table->table->tablenr));
  DBUG_RETURN(table->table);
}


Field *create_tmp_field_from_field(THD *thd, Field *org_field,
                                   LEX_CSTRING *name, TABLE *table,
                                   Item_field *item)
{
  Field *new_field;

  new_field= org_field->make_new_field(thd->mem_root, table,
                                       table == org_field->table);
  if (new_field)
  {
    new_field->init(table);
    new_field->orig_table= org_field->orig_table;
    if (item)
      item->result_field= new_field;
    else
      new_field->field_name= *name;
    new_field->flags|= org_field->flags & NO_DEFAULT_VALUE_FLAG;
    if (org_field->maybe_null() || (item && item->maybe_null))
      new_field->flags&= ~NOT_NULL_FLAG;	// Because of outer join
    if (org_field->type() == MYSQL_TYPE_VAR_STRING ||
        org_field->type() == MYSQL_TYPE_VARCHAR)
      table->s->db_create_options|= HA_OPTION_PACK_RECORD;
    else if (org_field->type() == FIELD_TYPE_DOUBLE)
      ((Field_double *) new_field)->not_fixed= TRUE;
    new_field->vcol_info= 0;
    new_field->cond_selectivity= 1.0;
    new_field->next_equal_field= NULL;
    new_field->option_list= NULL;
    new_field->option_struct= NULL;
  }
  return new_field;
}


Field *Item::create_field_for_schema(THD *thd, TABLE *table)
{
  if (field_type() == MYSQL_TYPE_VARCHAR)
  {
    Field *field;
    if (max_length > MAX_FIELD_VARCHARLENGTH)
      field= new Field_blob(max_length, maybe_null, &name,
                            collation.collation);
    else
      field= new Field_varstring(max_length, maybe_null, &name,
                                 table->s, collation.collation);
    if (field)
      field->init(table);
    return field;
  }
  return tmp_table_field_from_field_type(table);
}


int SELECT_LEX::vers_setup_conds(THD *thd, TABLE_LIST *tables)
{
  DBUG_ENTER("SELECT_LEX::vers_setup_cond");
#define newx new (thd->mem_root)

  const bool update_conds= !skip_setup_conds(thd);
  TABLE_LIST *table;

  if (!versioned_tables)
  {
    for (table= tables; table; table= table->next_local)
    {
      if (table->table && table->table->versioned())
        versioned_tables++;
      else if (table->vers_conditions.is_set() &&
              (table->is_non_derived() || !table->vers_conditions.used))
      {
        my_error(ER_VERS_NOT_VERSIONED, MYF(0), table->alias.str);
        DBUG_RETURN(-1);
      }
    }
  }

  if (versioned_tables == 0)
    DBUG_RETURN(0);

  /* For prepared statements we create items on statement arena,
     because they must outlive execution phase for multiple executions. */
  Query_arena_stmt on_stmt_arena(thd);

  // find outer system_time
  SELECT_LEX *outer_slex= outer_select();
  TABLE_LIST* outer_table= NULL;

  if (outer_slex)
  {
    TABLE_LIST* derived= master_unit()->derived;
    // inner SELECT may not be a derived table (derived == NULL)
    while (derived && outer_slex && !derived->vers_conditions.is_set())
    {
      derived= outer_slex->master_unit()->derived;
      outer_slex= outer_slex->outer_select();
    }
    if (derived && outer_slex)
    {
      DBUG_ASSERT(derived->vers_conditions.is_set());
      outer_table= derived;
    }
  }

  bool is_select= false;
  bool use_sysvar= false;
  switch (thd->lex->sql_command)
  {
  case SQLCOM_SELECT:
    use_sysvar= true;
    /* fall through */
  case SQLCOM_CREATE_TABLE:
  case SQLCOM_INSERT_SELECT:
  case SQLCOM_REPLACE_SELECT:
  case SQLCOM_DELETE_MULTI:
  case SQLCOM_UPDATE_MULTI:
    is_select= true;
  default:
    break;
  }

  for (table= tables; table; table= table->next_local)
  {
    if (!table->table || table->is_view() || !table->table->versioned())
      continue;

    vers_select_conds_t &vers_conditions= table->vers_conditions;

#ifdef WITH_PARTITION_STORAGE_ENGINE
      /*
        if the history is stored in partitions, then partitions
        themselves are not versioned
      */
      if (table->partition_names && table->table->part_info->vers_info)
      {
        /* If the history is stored in partitions, then partitions
            themselves are not versioned. */
        if (vers_conditions.was_set())
        {
          my_error(ER_VERS_QUERY_IN_PARTITION, MYF(0), table->alias.str);
          DBUG_RETURN(-1);
        }
        else if (!vers_conditions.is_set())
          vers_conditions.type= SYSTEM_TIME_ALL;
      }
#endif

    if (outer_table && !vers_conditions.is_set())
    {
      // propagate system_time from nearest outer SELECT_LEX
      vers_conditions= outer_table->vers_conditions;
      outer_table->vers_conditions.used= true;
    }

    // propagate system_time from sysvar
    if (!vers_conditions.is_set() && use_sysvar)
    {
      if (vers_conditions.init_from_sysvar(thd))
        DBUG_RETURN(-1);
    }

    if (vers_conditions.is_set())
    {
      if (vers_conditions.was_set() &&
          table->lock_type > TL_READ_NO_INSERT &&
          !vers_conditions.delete_history)
      {
        my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE, MYF(0), table->alias.str);
        DBUG_RETURN(-1);
      }

      if (vers_conditions.type == SYSTEM_TIME_ALL)
        continue;
    }

    const LEX_CSTRING *fstart=
        thd->make_clex_string(table->table->vers_start_field()->field_name);
    const LEX_CSTRING *fend=
        thd->make_clex_string(table->table->vers_end_field()->field_name);

    Item *row_start=
        newx Item_field(thd, &this->context, table->db.str, table->alias.str, fstart);
    Item *row_end=
        newx Item_field(thd, &this->context, table->db.str, table->alias.str, fend);

    bool timestamps_only= table->table->versioned(VERS_TIMESTAMP);

    if (vers_conditions.is_set() && vers_conditions.type != SYSTEM_TIME_HISTORY)
    {
      thd->where= "FOR SYSTEM_TIME";
      /* TODO: do resolve fix_length_and_dec(), fix_fields(). This requires
        storing vers_conditions as Item and make some magic related to
        vers_system_time_t/VERS_TRX_ID at stage of fix_fields()
        (this is large refactoring). */
      if (vers_conditions.resolve_units(thd))
        DBUG_RETURN(-1);
      if (timestamps_only && (vers_conditions.start.unit == VERS_TRX_ID ||
        vers_conditions.end.unit == VERS_TRX_ID))
      {
        my_error(ER_VERS_ENGINE_UNSUPPORTED, MYF(0), table->table_name.str);
        DBUG_RETURN(-1);
      }
    }

    if (!update_conds)
      continue;

    Item *cond1= NULL, *cond2= NULL, *cond3= NULL, *curr= NULL;
    Item *point_in_time1= vers_conditions.start.item;
    Item *point_in_time2= vers_conditions.end.item;
    TABLE *t= table->table;
    if (t->versioned(VERS_TIMESTAMP))
    {
      MYSQL_TIME max_time;
      switch (vers_conditions.type)
      {
      case SYSTEM_TIME_UNSPECIFIED:
      case SYSTEM_TIME_HISTORY:
        thd->variables.time_zone->gmt_sec_to_TIME(&max_time, TIMESTAMP_MAX_VALUE);
        max_time.second_part= TIME_MAX_SECOND_PART;
        curr= newx Item_datetime_literal(thd, &max_time, TIME_SECOND_PART_DIGITS);
        if (vers_conditions.type == SYSTEM_TIME_UNSPECIFIED)
          cond1= newx Item_func_eq(thd, row_end, curr);
        else
          cond1= newx Item_func_lt(thd, row_end, curr);
        break;
      case SYSTEM_TIME_AS_OF:
        cond1= newx Item_func_le(thd, row_start, point_in_time1);
        cond2= newx Item_func_gt(thd, row_end, point_in_time1);
        break;
      case SYSTEM_TIME_FROM_TO:
        cond1= newx Item_func_lt(thd, row_start, point_in_time2);
        cond2= newx Item_func_gt(thd, row_end, point_in_time1);
        cond3= newx Item_func_lt(thd, point_in_time1, point_in_time2);
        break;
      case SYSTEM_TIME_BETWEEN:
        cond1= newx Item_func_le(thd, row_start, point_in_time2);
        cond2= newx Item_func_gt(thd, row_end, point_in_time1);
        cond3= newx Item_func_le(thd, point_in_time1, point_in_time2);
        break;
      case SYSTEM_TIME_BEFORE:
        cond1= newx Item_func_history(thd, row_end);
        cond2= newx Item_func_lt(thd, row_end, point_in_time1);
        break;
      default:
        DBUG_ASSERT(0);
      }
    }
    else
    {
      DBUG_ASSERT(table->table->s && table->table->s->db_plugin);

      Item *trx_id0, *trx_id1;

      switch (vers_conditions.type)
      {
      case SYSTEM_TIME_UNSPECIFIED:
      case SYSTEM_TIME_HISTORY:
        curr= newx Item_int(thd, ULONGLONG_MAX);
        if (vers_conditions.type == SYSTEM_TIME_UNSPECIFIED)
          cond1= newx Item_func_eq(thd, row_end, curr);
        else
          cond1= newx Item_func_lt(thd, row_end, curr);
        break;
      case SYSTEM_TIME_AS_OF:
        trx_id0= vers_conditions.start.unit == VERS_TIMESTAMP
          ? newx Item_func_trt_id(thd, point_in_time1, TR_table::FLD_TRX_ID)
          : point_in_time1;
        cond1= newx Item_func_trt_trx_sees_eq(thd, trx_id0, row_start);
        cond2= newx Item_func_trt_trx_sees(thd, row_end, trx_id0);
        break;
      case SYSTEM_TIME_FROM_TO:
	cond3= newx Item_func_lt(thd, point_in_time1, point_in_time2);
        /* fall through */
      case SYSTEM_TIME_BETWEEN:
        trx_id0= vers_conditions.start.unit == VERS_TIMESTAMP
          ? newx Item_func_trt_id(thd, point_in_time1, TR_table::FLD_TRX_ID, true)
          : point_in_time1;
        trx_id1= vers_conditions.end.unit == VERS_TIMESTAMP
          ? newx Item_func_trt_id(thd, point_in_time2, TR_table::FLD_TRX_ID, false)
          : point_in_time2;
        cond1= vers_conditions.type == SYSTEM_TIME_FROM_TO
          ? newx Item_func_trt_trx_sees(thd, trx_id1, row_start)
          : newx Item_func_trt_trx_sees_eq(thd, trx_id1, row_start);
        cond2= newx Item_func_trt_trx_sees_eq(thd, row_end, trx_id0);
	if (!cond3)
	  cond3= newx Item_func_le(thd, point_in_time1, point_in_time2);
        break;
      case SYSTEM_TIME_BEFORE:
        trx_id0= vers_conditions.start.unit == VERS_TIMESTAMP
          ? newx Item_func_trt_id(thd, point_in_time1, TR_table::FLD_TRX_ID, true)
          : point_in_time1;
        cond1= newx Item_func_history(thd, row_end);
        cond2= newx Item_func_trt_trx_sees(thd, trx_id0, row_end);
        break;
      default:
        DBUG_ASSERT(0);
      }
    }

    if (cond1)
    {
      cond1= and_items(thd, cond2, cond1);
      cond1= and_items(thd, cond3, cond1);
      if (is_select)
        table->on_expr= and_items(thd, table->on_expr, cond1);
      else
      {
        if (join)
        {
          where= and_items(thd, join->conds, cond1);
          join->conds= where;
        }
        else
          where= and_items(thd, where, cond1);
        table->where= and_items(thd, table->where, cond1);
      }
    }

    table->vers_conditions.type= SYSTEM_TIME_ALL;
  } // for (table= tables; ...)

  DBUG_RETURN(0);
#undef newx
}


join_read_const_table(THD *thd, JOIN_TAB *tab, POSITION *pos)
{
  int error;
  TABLE_LIST *tbl;
  DBUG_ENTER("join_read_const_table");
  TABLE *table=tab->table;
  table->const_table=1;
  table->null_row=0;
  table->status=STATUS_NO_RECORD;

  if (tab->table->pos_in_table_list->is_materialized_derived() &&
      !tab->table->pos_in_table_list->fill_me)
  {
    //TODO: don't get here at all
    /* Skip materialized derived tables/views. */
    DBUG_RETURN(0);
  }
  else if (tab->table->pos_in_table_list->jtbm_subselect &&
          tab->table->pos_in_table_list->jtbm_subselect->is_jtbm_const_tab)
  {
    /* Row will not be found */
    int res;
    if (tab->table->pos_in_table_list->jtbm_subselect->jtbm_const_row_found)
      res= 0;
    else
      res= -1;
    DBUG_RETURN(res);
  }
  else if (tab->type == JT_SYSTEM)
  {
    if (unlikely((error=join_read_system(tab))))
    {						// Info for DESCRIBE
      tab->info= ET_CONST_ROW_NOT_FOUND;
      /* Mark for EXPLAIN that the row was not found */
      pos->records_read=0.0;
      pos->ref_depend_map= 0;
      if (!table->pos_in_table_list->outer_join || error > 0)
	DBUG_RETURN(error);
    }
    /*
      The optimizer trust the engine that when stats.records is 0, there
      was no found rows
    */
    DBUG_ASSERT(table->file->stats.records > 0 || error);
  }
  else
  {
    if (/*!table->file->key_read && */
        table->covering_keys.is_set(tab->ref.key) && !table->no_keyread &&
        (int) table->reginfo.lock_type <= (int) TL_READ_HIGH_PRIORITY)
    {
      table->file->ha_start_keyread(tab->ref.key);
      tab->index= tab->ref.key;
    }
    error=join_read_const(tab);
    table->file->ha_end_keyread();
    if (unlikely(error))
    {
      tab->info= ET_UNIQUE_ROW_NOT_FOUND;
      /* Mark for EXPLAIN that the row was not found */
      pos->records_read=0.0;
      pos->ref_depend_map= 0;
      if (!table->pos_in_table_list->outer_join || error > 0)
	DBUG_RETURN(error);
    }
  }
  /*
     Evaluate an on-expression only if it is not considered expensive.
     This mainly prevents executing subqueries in optimization phase.
     This is necessary since proper setup for such execution has not been
     done at this stage.
  */
  if (*tab->on_expr_ref && !table->null_row &&
      !(*tab->on_expr_ref)->is_expensive())
  {
#if !defined(DBUG_OFF) && defined(NOT_USING_ITEM_EQUAL)
    /*
      This test could be very useful to find bugs in the optimizer
      where we would call this function with an expression that can't be
      evaluated yet. We can't have this enabled by default as long as
      have items like Item_equal, that doesn't report they are const but
      they can still be called even if they contain not const items.
    */
    (*tab->on_expr_ref)->update_used_tables();
    DBUG_ASSERT((*tab->on_expr_ref)->const_item());
#endif
    if ((table->null_row= MY_TEST((*tab->on_expr_ref)->val_int() == 0)))
      mark_as_null_row(table);
  }
  if (!table->null_row && ! tab->join->mixed_implicit_grouping)
    table->maybe_null= 0;

  {
    JOIN *join= tab->join;
    List_iterator<TABLE_LIST> ti(join->select_lex->leaf_tables);
    /* Check appearance of new constant items in Item_equal objects */
    if (join->conds)
      update_const_equal_items(thd, join->conds, tab, TRUE);
    while ((tbl= ti++))
    {
      TABLE_LIST *embedded;
      TABLE_LIST *embedding= tbl;
      do
      {
        embedded= embedding;
        if (embedded->on_expr)
           update_const_equal_items(thd, embedded->on_expr, tab, TRUE);
        embedding= embedded->embedding;
      }
      while (embedding &&
             embedding->nested_join->join_list.head() == embedded);
    }
  }
  DBUG_RETURN(0);
}


join_no_more_records(READ_RECORD *info __attribute__((unused)))
{
  return -1;
}


static bool equal(Item *i1, Item *i2, Field *f2)
{
  DBUG_ASSERT((i2 == NULL) ^ (f2 == NULL));

  if (i2 != NULL)
    return i1->eq(i2, 1);
  else if (i1->type() == Item::FIELD_ITEM)
    return f2->eq(((Item_field *) i1)->field);
  else
    return FALSE;
}


static void operator delete(void *, MEM_ROOT*) {}


bool Virtual_tmp_table::init(uint field_count)
{
  uint *blob_field;
  uchar *bitmaps;
  DBUG_ENTER("Virtual_tmp_table::init");
  if (!multi_alloc_root(in_use->mem_root,
                        &s, sizeof(*s),
                        &field, (field_count + 1) * sizeof(Field*),
                        &blob_field, (field_count + 1) * sizeof(uint),
                        &bitmaps, bitmap_buffer_size(field_count) * 6,
                        NullS))
    DBUG_RETURN(true);
  s->reset();
  s->blob_field= blob_field;
  setup_tmp_table_column_bitmaps(this, bitmaps, field_count);
  m_alloced_field_count= field_count;
  DBUG_RETURN(false);
};


join_tab_cmp(const void *dummy, const void* ptr1, const void* ptr2)
{
  JOIN_TAB *jt1= *(JOIN_TAB**) ptr1;
  JOIN_TAB *jt2= *(JOIN_TAB**) ptr2;
  int cmp;

  if ((cmp= compare_embedding_subqueries(jt1, jt2)) != 0)
    return cmp;
  /*
    After that,
    take care about ordering imposed by LEFT JOIN constraints,
    possible [eq]ref accesses, and numbers of matching records in the table.
  */
  if (jt1->dependent & jt2->table->map)
    return 1;
  if (jt2->dependent & jt1->table->map)
    return -1;
  if (jt1->found_records > jt2->found_records)
    return 1;
  if (jt1->found_records < jt2->found_records)
    return -1;
  return jt1 > jt2 ? 1 : (jt1 < jt2 ? -1 : 0);
}


return_zero_rows(JOIN *join, select_result *result, List<TABLE_LIST> &tables,
		 List<Item> &fields, bool send_row, ulonglong select_options,
		 const char *info, Item *having, List<Item> &all_fields)
{
  DBUG_ENTER("return_zero_rows");

  if (select_options & SELECT_DESCRIBE)
  {
    select_describe(join, FALSE, FALSE, FALSE, info);
    DBUG_RETURN(0);
  }

  join->join_free();

  if (send_row)
  {
    /*
      Set all tables to have NULL row. This is needed as we will be evaluating
      HAVING condition.
    */
    List_iterator<TABLE_LIST> ti(tables);
    TABLE_LIST *table;
    while ((table= ti++))
    {
      /*
        Don't touch semi-join materialization tables, as the above join_free()
        call has freed them (and HAVING clause can't have references to them
        anyway).
      */
      if (!table->is_jtbm())
        mark_as_null_row(table->table);		// All fields are NULL
    }
    List_iterator_fast<Item> it(all_fields);
    Item *item;
    /*
      Inform all items (especially aggregating) to calculate HAVING correctly,
      also we will need it for sending results.
    */
    while ((item= it++))
      item->no_rows_in_result();
    if (having && having->val_int() == 0)
      send_row=0;
  }

  /* Update results for FOUND_ROWS */
  if (!join->send_row_on_empty_set())
  {
    join->thd->set_examined_row_count(0);
    join->thd->limit_found_rows= 0;
  }

  if (!(result->send_result_set_metadata(fields,
                              Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)))
  {
    bool send_error= FALSE;
    if (send_row)
      send_error= result->send_data(fields) > 0;
    if (likely(!send_error))
      result->send_eof();				// Should be safe
  }
  DBUG_RETURN(0);
}


void JOIN::save_query_plan(Join_plan_state *save_to)
{
  DYNAMIC_ARRAY tmp_keyuse;
  /* Swap the current and the backup keyuse internal arrays. */
  tmp_keyuse= keyuse;
  keyuse= save_to->keyuse; /* keyuse is reset to an empty array. */
  save_to->keyuse= tmp_keyuse;

  for (uint i= 0; i < table_count; i++)
  {
    save_to->join_tab_keyuse[i]= join_tab[i].keyuse;
    join_tab[i].keyuse= NULL;
    save_to->join_tab_checked_keys[i]= join_tab[i].checked_keys;
    join_tab[i].checked_keys.clear_all();
  }
  memcpy((uchar*) save_to->best_positions, (uchar*) best_positions,
         sizeof(POSITION) * (table_count + 1));
  memset((uchar*) best_positions, 0, sizeof(POSITION) * (table_count + 1));

  /* Save SJM nests */
  List_iterator<TABLE_LIST> it(select_lex->sj_nests);
  TABLE_LIST *tlist;
  SJ_MATERIALIZATION_INFO **p_info= save_to->sj_mat_info;
  while ((tlist= it++))
  {
    *(p_info++)= tlist->sj_mat_info;
  }
}


bool generate_derived_keys_for_table(KEYUSE *keyuse, uint count, uint keys)
{
  TABLE *table= keyuse->table;
  if (table->alloc_keys(keys))
    return TRUE;
  uint key_count= 0;
  KEYUSE *first_keyuse= keyuse;
  uint prev_part= keyuse->keypart;
  uint parts= 0;
  uint i= 0;

  for ( ; i < count && key_count < keys; )
  {
    do
    {
      keyuse->key= table->s->keys;
      keyuse->keypart_map= (key_part_map) (1 << parts);
      keyuse++;
      i++;
    }
    while (i < count && keyuse->used_tables == first_keyuse->used_tables &&
           keyuse->keypart == prev_part);
    parts++;
    if (i < count && keyuse->used_tables == first_keyuse->used_tables)
    {
      prev_part= keyuse->keypart;
    }
    else
    {
      KEYUSE *save_first_keyuse= first_keyuse;
      if (table->check_tmp_key(table->s->keys, parts,
                               get_next_field_for_derived_key_simple,
                               (uchar *) &first_keyuse))

      {
        first_keyuse= save_first_keyuse;
        if (table->add_tmp_key(table->s->keys, parts,
                               get_next_field_for_derived_key,
                               (uchar *) &first_keyuse,
                               FALSE))
          return TRUE;
        table->reginfo.join_tab->keys.set_bit(table->s->keys);
      }
      else
      {
        /* Mark keyuses for this key to be excluded */
        for (KEYUSE *curr=save_first_keyuse; curr < keyuse; curr++)
	{
          curr->key= MAX_KEY;
        }
      }
      first_keyuse= keyuse;
      key_count++;
      parts= 0;
      prev_part= keyuse->keypart;
    }
  }

  return FALSE;
}


setup_new_fields(THD *thd, List<Item> &fields,
		 List<Item> &all_fields, ORDER *new_field)
{
  Item	  **item;
  uint counter;
  enum_resolution_type not_used;
  DBUG_ENTER("setup_new_fields");

  thd->column_usage= MARK_COLUMNS_READ;       // Not really needed, but...
  for (; new_field ; new_field= new_field->next)
  {
    if ((item= find_item_in_list(*new_field->item, fields, &counter,
				 IGNORE_ERRORS, &not_used)))
      new_field->item=item;			/* Change to shared Item */
    else
    {
      thd->where="procedure list";
      if ((*new_field->item)->fix_fields(thd, new_field->item))
	DBUG_RETURN(1); /* purecov: inspected */
      all_fields.push_front(*new_field->item, thd->mem_root);
      new_field->item=all_fields.head_ref();
    }
  }
  DBUG_RETURN(0);
}


static TABLE_LIST* embedding_sjm(Item *item)
{
  Item_field *item_field= (Item_field *) (item->real_item());
  TABLE_LIST *nest= item_field->field->table->pos_in_table_list->embedding;
  if (nest && nest->sj_mat_info && nest->sj_mat_info->is_used)
    return nest;
  else
    return NULL;
}


JOIN_TAB *next_explain_order_tab(JOIN* join, JOIN_TAB* tab)
{
  /* If we're inside SJM nest and have reached its end, get out */
  if (tab->last_leaf_in_bush)
    return tab->bush_root_tab;

  /* Move to next tab in the array we're traversing */
  tab++;

  if (tab == join->join_tab + join->top_join_tab_count)
    return NULL; /* Outside SJM nest and reached EOF */

  if (tab->bush_children)
    return tab->bush_children->start;

  return tab;
}


find_field_in_order_list (Field *field, void *data)
{
  ORDER *group= (ORDER *) data;
  bool part_found= 0;
  for (ORDER *tmp_group= group; tmp_group; tmp_group=tmp_group->next)
  {
    Item *item= (*tmp_group->item)->real_item();
    if (item->type() == Item::FIELD_ITEM &&
        ((Item_field*) item)->field->eq(field))
    {
      part_found= 1;
      break;
    }
  }
  return part_found;
}


JOIN_TAB *first_linear_tab(JOIN *join,
                           enum enum_with_bush_roots include_bush_roots,
                           enum enum_with_const_tables const_tbls)
{
  JOIN_TAB *first= join->join_tab;

  if (!first)
    return NULL;

  if (const_tbls == WITHOUT_CONST_TABLES)
    first+= join->const_tables;

  if (first >= join->join_tab + join->top_join_tab_count)
    return NULL; /* All are const tables */

  if (first->bush_children && include_bush_roots == WITHOUT_BUSH_ROOTS)
  {
    /* This JOIN_TAB is a SJM nest; Start from first table in nest */
    return first->bush_children->start;
  }

  return first;
}


COND *Item_func_eq::build_equal_items(THD *thd,
                                      COND_EQUAL *inherited,
                                      bool link_item_fields,
                                      COND_EQUAL **cond_equal_ref)
{
  COND_EQUAL cond_equal;
  cond_equal.upper_levels= inherited;
  List<Item> eq_list;

  DBUG_ASSERT(!cond_equal_ref || !cond_equal_ref[0]);
  /*
    If an equality predicate forms the whole and level,
    we call it standalone equality and it's processed here.
    E.g. in the following where condition
    WHERE a=5 AND (b=5 or a=c)
    (b=5) and (a=c) are standalone equalities.
    In general we can't leave alone standalone eqalities:
    for WHERE a=b AND c=d AND (b=c OR d=5)
    b=c is replaced by =(a,b,c,d).
   */
  if (Item_func_eq::check_equality(thd, &cond_equal, &eq_list))
  {
    Item_equal *item_equal;
    int n= cond_equal.current_level.elements + eq_list.elements;
    if (n == 0)
      return new (thd->mem_root) Item_int(thd, (longlong) 1, 1);
    else if (n == 1)
    {
      if ((item_equal= cond_equal.current_level.pop()))
      {
        item_equal->fix_fields(thd, NULL);
        item_equal->update_used_tables();
        set_if_bigger(thd->lex->current_select->max_equal_elems,
                      item_equal->n_field_items());
        item_equal->upper_levels= inherited;
        if (cond_equal_ref)
          *cond_equal_ref= new (thd->mem_root) COND_EQUAL(item_equal,
                                                          thd->mem_root);
        return item_equal;
      }
      Item *res= eq_list.pop();
      res->update_used_tables();
      DBUG_ASSERT(res->type() == FUNC_ITEM);
      return res;
    }
    else
    {
      /*
        Here a new AND level must be created. It can happen only
        when a row equality is processed as a standalone predicate.
      */
      Item_cond_and *and_cond= new (thd->mem_root) Item_cond_and(thd, eq_list);
      and_cond->quick_fix_field();
      List<Item> *cond_args= and_cond->argument_list();
      List_iterator_fast<Item_equal> it(cond_equal.current_level);
      while ((item_equal= it++))
      {
        if (item_equal->fix_length_and_dec())
          return NULL;
        item_equal->update_used_tables();
        set_if_bigger(thd->lex->current_select->max_equal_elems,
                      item_equal->n_field_items());
      }
      and_cond->m_cond_equal.copy(cond_equal);
      cond_equal.current_level= and_cond->m_cond_equal.current_level;
      cond_args->append((List<Item> *)&cond_equal.current_level);
      and_cond->update_used_tables();
      if (cond_equal_ref)
        *cond_equal_ref= &and_cond->m_cond_equal;
      return and_cond;
    }
  }
  return Item_func::build_equal_items(thd, inherited, link_item_fields,
                                      cond_equal_ref);
}


copy_fields(TMP_TABLE_PARAM *param)
{
  Copy_field *ptr=param->copy_field;
  Copy_field *end=param->copy_field_end;

  DBUG_ASSERT((ptr != NULL && end >= ptr) || (ptr == NULL && end == NULL));

  for (; ptr != end; ptr++)
    (*ptr->do_copy)(ptr);

  List_iterator_fast<Item> it(param->copy_funcs);
  Item_copy_string *item;
  while ((item = (Item_copy_string*) it++))
    item->copy();
}