static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables)
{
  LEX	*lex= thd->lex;
  select_result *result=lex->result;
  bool res;
  /* assign global limit variable if limit is not given */
  {
    SELECT_LEX *param= lex->unit.global_parameters();
    if (!param->explicit_limit)
      param->select_limit=
        new (thd->mem_root) Item_int(thd,
                                     (ulonglong) thd->variables.select_limit);
  }

  if (!(res= open_and_lock_tables(thd, all_tables, TRUE, 0)))
  {
    if (lex->describe)
    {
      /*
        We always use select_send for EXPLAIN, even if it's an EXPLAIN
        for SELECT ... INTO OUTFILE: a user application should be able
        to prepend EXPLAIN to any query and receive output for it,
        even if the query itself redirects the output.
      */
      if (unlikely(!(result= new (thd->mem_root) select_send(thd))))
        return 1;                               /* purecov: inspected */
      thd->send_explain_fields(result, lex->describe, lex->analyze_stmt);
        
      /*
        This will call optimize() for all parts of query. The query plan is
        printed out below.
      */
      res= mysql_explain_union(thd, &lex->unit, result);
      
      /* Print EXPLAIN only if we don't have an error */
      if (likely(!res))
      {
        /* 
          Do like the original select_describe did: remove OFFSET from the
          top-level LIMIT
        */        
        result->reset_offset_limit(); 
        if (lex->explain_json)
        {
          lex->explain->print_explain_json(result, lex->analyze_stmt);
        }
        else
        {
          lex->explain->print_explain(result, thd->lex->describe,
                                      thd->lex->analyze_stmt);
          if (lex->describe & DESCRIBE_EXTENDED)
          {
            char buff[1024];
            String str(buff,(uint32) sizeof(buff), system_charset_info);
            str.length(0);
            /*
              The warnings system requires input in utf8, @see
              mysqld_show_warnings().
            */
            lex->unit.print(&str, QT_EXPLAIN_EXTENDED);
            push_warning(thd, Sql_condition::WARN_LEVEL_NOTE,
                         ER_YES, str.c_ptr_safe());
          }
        }
      }

      if (res)
        result->abort_result_set();
      else
        result->send_eof();
      delete result;
    }
    else
    {
      Protocol *save_protocol= NULL;
      if (lex->analyze_stmt)
      {
        if (result && result->result_interceptor())
          result->result_interceptor()->disable_my_ok_calls();
        else 
        {
          DBUG_ASSERT(thd->protocol);
          result= new (thd->mem_root) select_send_analyze(thd);
          save_protocol= thd->protocol;
          thd->protocol= new Protocol_discard(thd);
        }
      }
      else
      {
        if (!result && !(result= new (thd->mem_root) select_send(thd)))
          return 1;                               /* purecov: inspected */
      }
      query_cache_store_query(thd, all_tables);
      res= handle_select(thd, lex, result, 0);
      if (result != lex->result)
        delete result;

      if (lex->analyze_stmt)
      {
        if (save_protocol)
        {
          delete thd->protocol;
          thd->protocol= save_protocol;
        }
        if (!res)
          res= thd->lex->explain->send_explain(thd);
      }
    }
  }
  /* Count number of empty select queries */
  if (!thd->get_sent_row_count() && !res)
    status_var_increment(thd->status_var.empty_queries);
  else
    status_var_add(thd->status_var.rows_sent, thd->get_sent_row_count());

  return res;
}