~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/join.cc

  • Committer: Padraig O'Sullivan
  • Date: 2010-04-17 01:06:54 UTC
  • mto: (1497.1.1 build)
  • mto: This revision was merged to the branch mainline in revision 1499.
  • Revision ID: osullivan.padraig@gmail.com-20100417010654-t48hu57m4gl6egwm
Integrated the AccessMethodFactory class into the code base. We have now abstracted out the concept of an access method.

Show diffs side-by-side

added added

removed removed

Lines of Context:
51
51
#include "drizzled/optimizer/range.h"
52
52
#include "drizzled/optimizer/sum.h"
53
53
#include "drizzled/optimizer/explain_plan.h"
 
54
#include "drizzled/optimizer/access_method_factory.h"
 
55
#include "drizzled/optimizer/access_method.h"
54
56
#include "drizzled/records.h"
55
57
#include "drizzled/probes.h"
56
58
#include "drizzled/internal/my_bit.h"
98
100
static bool make_simple_join(JOIN *join,Table *tmp_table);
99
101
static void make_outerjoin_info(JOIN *join);
100
102
static bool make_join_select(JOIN *join, optimizer::SqlSelect *select,COND *item);
101
 
static bool make_join_readinfo(JOIN *join, uint64_t options, uint32_t no_jbuf_after);
 
103
static bool make_join_readinfo(JOIN *join);
102
104
static void update_depend_map(JOIN *join);
103
105
static void update_depend_map(JOIN *join, order_st *order);
104
106
static order_st *remove_constants(JOIN *join,order_st *first_order,COND *cond, bool change_list, bool *simple_order);
128
130
static void reset_nj_counters(List<TableList> *join_list);
129
131
static bool test_if_subpart(order_st *a,order_st *b);
130
132
static void restore_prev_nj_state(JoinTable *last);
131
 
static uint32_t make_join_orderinfo(JOIN *join);
132
133
static bool add_ref_to_table_cond(Session *session, JoinTable *join_tab);
133
134
static void free_blobs(Field **ptr); /* Rename this method...conflicts with another in global namespace... */
134
135
 
835
836
        (group_list && order) ||
836
837
        test(select_options & OPTION_BUFFER_RESULT)));
837
838
 
838
 
  uint32_t no_jbuf_after= make_join_orderinfo(this);
839
 
  uint64_t select_opts_for_readinfo=
840
 
    (select_options & (SELECT_DESCRIBE | SELECT_NO_JOIN_CACHE)) | (0);
841
 
 
842
839
  // No cache for MATCH == 'Don't use join buffering when we use MATCH'.
843
 
  if (make_join_readinfo(this, select_opts_for_readinfo, no_jbuf_after))
 
840
  if (make_join_readinfo(this))
844
841
    return 1;
845
842
 
846
843
  /* Create all structures needed for materialized subquery execution. */
4872
4869
    false - OK
4873
4870
    true  - Out of memory
4874
4871
*/
4875
 
static bool make_join_readinfo(JOIN *join, uint64_t options, uint32_t no_jbuf_after)
 
4872
static bool make_join_readinfo(JOIN *join)
4876
4873
{
4877
 
  uint32_t i;
4878
 
  bool statistics= test(!(join->select_options & SELECT_DESCRIBE));
4879
 
  bool sorted= 1;
 
4874
  bool sorted= true;
4880
4875
 
4881
 
  for (i=join->const_tables ; i < join->tables ; i++)
 
4876
  for (uint32_t i= join->const_tables ; i < join->tables ; i++)
4882
4877
  {
4883
4878
    JoinTable *tab=join->join_tab+i;
4884
4879
    Table *table=tab->table;
4885
 
    bool using_join_cache;
4886
4880
    tab->read_record.table= table;
4887
4881
    tab->read_record.cursor= table->cursor;
4888
4882
    tab->next_select=sub_select;                /* normal select */
4891
4885
      produce sorted output.
4892
4886
    */
4893
4887
    tab->sorted= sorted;
4894
 
    sorted= 0;                                  // only first must be sorted
 
4888
    sorted= false; // only first must be sorted
 
4889
 
4895
4890
    if (tab->insideout_match_tab)
4896
4891
    {
4897
 
      if (!(tab->insideout_buf= (unsigned char*)join->session->alloc(tab->table->key_info
4898
 
                                                         [tab->index].
4899
 
                                                         key_length)))
 
4892
      if (! (tab->insideout_buf= (unsigned char*) join->session->alloc(tab->table->key_info
 
4893
                                                                       [tab->index].
 
4894
                                                                       key_length)))
4900
4895
        return true;
4901
4896
    }
4902
 
    switch (tab->type) {
4903
 
    case AM_SYSTEM:                             // Only happens with left join
4904
 
      table->status=STATUS_NO_RECORD;
4905
 
      tab->read_first_record= join_read_system;
4906
 
      tab->read_record.read_record= join_no_more_records;
4907
 
      break;
4908
 
    case AM_CONST:                              // Only happens with left join
4909
 
      table->status=STATUS_NO_RECORD;
4910
 
      tab->read_first_record= join_read_const;
4911
 
      tab->read_record.read_record= join_no_more_records;
4912
 
      if (table->covering_keys.test(tab->ref.key) &&
4913
 
          !table->no_keyread)
4914
 
      {
4915
 
        table->key_read=1;
4916
 
        table->cursor->extra(HA_EXTRA_KEYREAD);
4917
 
      }
4918
 
      break;
4919
 
    case AM_EQ_REF:
4920
 
      table->status=STATUS_NO_RECORD;
4921
 
      if (tab->select)
4922
 
      {
4923
 
        delete tab->select->quick;
4924
 
        tab->select->quick=0;
4925
 
      }
4926
 
      delete tab->quick;
4927
 
      tab->quick=0;
4928
 
      tab->read_first_record= join_read_key;
4929
 
      tab->read_record.read_record= join_no_more_records;
4930
 
      if (table->covering_keys.test(tab->ref.key) && !table->no_keyread)
4931
 
      {
4932
 
        table->key_read=1;
4933
 
        table->cursor->extra(HA_EXTRA_KEYREAD);
4934
 
      }
4935
 
      break;
4936
 
    case AM_REF_OR_NULL:
4937
 
    case AM_REF:
4938
 
      table->status=STATUS_NO_RECORD;
4939
 
      if (tab->select)
4940
 
      {
4941
 
        delete tab->select->quick;
4942
 
        tab->select->quick=0;
4943
 
      }
4944
 
      delete tab->quick;
4945
 
      tab->quick=0;
4946
 
      if (table->covering_keys.test(tab->ref.key) && !table->no_keyread)
4947
 
      {
4948
 
        table->key_read=1;
4949
 
        table->cursor->extra(HA_EXTRA_KEYREAD);
4950
 
      }
4951
 
      if (tab->type == AM_REF)
4952
 
      {
4953
 
        tab->read_first_record= join_read_always_key;
4954
 
        tab->read_record.read_record= tab->insideout_match_tab?
4955
 
           join_read_next_same_diff : join_read_next_same;
4956
 
      }
4957
 
      else
4958
 
      {
4959
 
        tab->read_first_record= join_read_always_key_or_null;
4960
 
        tab->read_record.read_record= join_read_next_same_or_null;
4961
 
      }
4962
 
      break;
4963
 
    case AM_ALL:
4964
 
      /*
4965
 
        If previous table use cache
4966
 
        If the incoming data set is already sorted don't use cache.
4967
 
      */
4968
 
      table->status=STATUS_NO_RECORD;
4969
 
      using_join_cache= false;
4970
 
      if (i != join->const_tables && !(options & SELECT_NO_JOIN_CACHE) &&
4971
 
          tab->use_quick != 2 && !tab->first_inner && i <= no_jbuf_after &&
4972
 
          !tab->insideout_match_tab)
4973
 
      {
4974
 
        if ((options & SELECT_DESCRIBE) ||
4975
 
            !join_init_cache(join->session,join->join_tab+join->const_tables,
4976
 
                i-join->const_tables))
4977
 
        {
4978
 
                using_join_cache= true;
4979
 
          tab[-1].next_select=sub_select_cache; /* Patch previous */
4980
 
        }
4981
 
      }
4982
 
      /* These init changes read_record */
4983
 
      if (tab->use_quick == 2)
4984
 
      {
4985
 
        join->session->server_status|=SERVER_QUERY_NO_GOOD_INDEX_USED;
4986
 
        tab->read_first_record= join_init_quick_read_record;
4987
 
        if (statistics)
4988
 
          status_var_increment(join->session->status_var.select_range_check_count);
4989
 
      }
4990
 
      else
4991
 
      {
4992
 
        tab->read_first_record= join_init_read_record;
4993
 
        if (i == join->const_tables)
4994
 
        {
4995
 
          if (tab->select && tab->select->quick)
4996
 
          {
4997
 
            if (statistics)
4998
 
              status_var_increment(join->session->status_var.select_range_count);
4999
 
          }
5000
 
          else
5001
 
          {
5002
 
            join->session->server_status|=SERVER_QUERY_NO_INDEX_USED;
5003
 
            if (statistics)
5004
 
              status_var_increment(join->session->status_var.select_scan_count);
5005
 
          }
5006
 
        }
5007
 
        else
5008
 
        {
5009
 
          if (tab->select && tab->select->quick)
5010
 
          {
5011
 
            if (statistics)
5012
 
              status_var_increment(join->session->status_var.select_full_range_join_count);
5013
 
          }
5014
 
          else
5015
 
          {
5016
 
            join->session->server_status|=SERVER_QUERY_NO_INDEX_USED;
5017
 
            if (statistics)
5018
 
              status_var_increment(join->session->status_var.select_full_join_count);
5019
 
          }
5020
 
        }
5021
 
        if (!table->no_keyread)
5022
 
        {
5023
 
          if (tab->select && tab->select->quick &&
5024
 
                    tab->select->quick->index != MAX_KEY && //not index_merge
5025
 
              table->covering_keys.test(tab->select->quick->index))
5026
 
          {
5027
 
            table->key_read=1;
5028
 
            table->cursor->extra(HA_EXTRA_KEYREAD);
5029
 
          }
5030
 
          else if (!table->covering_keys.none() &&
5031
 
            !(tab->select && tab->select->quick))
5032
 
          {                                     // Only read index tree
5033
 
                  if (!tab->insideout_match_tab)
5034
 
                  {
5035
 
                    /*
5036
 
                      See bug #26447: "Using the clustered index for a table scan
5037
 
                      is always faster than using a secondary index".
5038
 
                    */
5039
 
                    if (table->s->primary_key != MAX_KEY &&
5040
 
                        table->cursor->primary_key_is_clustered())
5041
 
                      tab->index= table->s->primary_key;
5042
 
                    else
5043
 
                      tab->index= table->find_shortest_key(&table->covering_keys);
5044
 
                  }
5045
 
            tab->read_first_record= join_read_first;
5046
 
            tab->type= AM_NEXT;         // Read with index_first / index_next
5047
 
          }
5048
 
        }
5049
 
      }
5050
 
      break;
5051
 
    default:
5052
 
      break;
5053
 
    case AM_UNKNOWN:
5054
 
    case AM_MAYBE_REF:
 
4897
 
 
4898
    optimizer::AccessMethodFactory &factory= optimizer::AccessMethodFactory::singleton();
 
4899
    optimizer::AccessMethod *access_method= factory.createAccessMethod(tab->type);
 
4900
 
 
4901
    if (! access_method)
 
4902
    {
 
4903
      /**
 
4904
       * @todo
 
4905
       * Is abort() the correct thing to call here? I call this here because it was what was called in
 
4906
       * the default case for the switch statement that used to be here.
 
4907
       */
5055
4908
      abort();
5056
4909
    }
 
4910
 
 
4911
    access_method->getStats(table, tab);
 
4912
 
 
4913
    delete access_method;
5057
4914
  }
5058
 
  join->join_tab[join->tables-1].next_select=0; /* Set by do_select */
5059
 
  return(false);
 
4915
 
 
4916
  join->join_tab[join->tables-1].next_select= NULL; /* Set by do_select */
 
4917
 
 
4918
  return false;
5060
4919
}
5061
4920
 
5062
4921
/** Update the dependency map for the tables. */
6171
6030
  }
6172
6031
}
6173
6032
 
6174
 
/**
6175
 
  Determine if the set is already ordered for order_st BY, so it can
6176
 
  disable join cache because it will change the ordering of the results.
6177
 
  Code handles sort table that is at any location (not only first after
6178
 
  the const tables) despite the fact that it's currently prohibited.
6179
 
  We must disable join cache if the first non-const table alone is
6180
 
  ordered. If there is a temp table the ordering is done as a last
6181
 
  operation and doesn't prevent join cache usage.
6182
 
*/
6183
 
static uint32_t make_join_orderinfo(JOIN *join)
6184
 
{
6185
 
  uint32_t i;
6186
 
  if (join->need_tmp)
6187
 
    return join->tables;
6188
 
 
6189
 
  for (i=join->const_tables ; i < join->tables ; i++)
6190
 
  {
6191
 
    JoinTable *tab= join->join_tab+i;
6192
 
    Table *table= tab->table;
6193
 
    if ((table == join->sort_by_table &&
6194
 
        (!join->order || join->skip_sort_order)) ||
6195
 
        (join->sort_by_table == (Table *) 1 &&  i != join->const_tables))
6196
 
    {
6197
 
      break;
6198
 
    }
6199
 
  }
6200
 
  return i;
6201
 
}
6202
6033
 
6203
6034
/**
6204
6035
  Create a condition for a const reference and add this to the