~stewart/drizzle/embedded-innodb-create-select-transaction-arrgh

« back to all changes in this revision

Viewing changes to drizzled/join.cc

merge trunk

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. */
2348
2345
  {
2349
2346
    /* Get reference pointers to sum functions in place */
2350
2347
    memcpy(ref_pointer_array, rollup.ref_pointer_arrays[i],
2351
 
     ref_pointer_array_size);
 
2348
           ref_pointer_array_size);
2352
2349
    if ((!having || having->val_int()))
2353
2350
    {
2354
2351
      int write_error;
2360
2357
          item->save_in_result_field(1);
2361
2358
      }
2362
2359
      copy_sum_funcs(sum_funcs_end[i+1], sum_funcs_end[i]);
2363
 
      if ((write_error= table_arg->cursor->ha_write_row(table_arg->record[0])))
 
2360
      if ((write_error= table_arg->cursor->insertRecord(table_arg->record[0])))
2364
2361
      {
2365
 
  if (create_myisam_from_heap(session, table_arg,
2366
 
                                    tmp_table_param.start_recinfo,
2367
 
                                    &tmp_table_param.recinfo,
2368
 
                                    write_error, 0))
2369
 
    return 1;
 
2362
        my_error(ER_USE_SQL_BIG_RESULT, MYF(0));
 
2363
        return 1;
2370
2364
      }
2371
2365
    }
2372
2366
  }
2817
2811
    {
2818
2812
      int error;
2819
2813
      join->found_records++;
2820
 
      if ((error=table->cursor->ha_write_row(table->record[0])))
 
2814
      if ((error=table->cursor->insertRecord(table->record[0])))
2821
2815
      {
2822
2816
        if (!table->cursor->is_fatal_error(error, HA_CHECK_DUP))
2823
2817
          goto end;
2824
 
        if (create_myisam_from_heap(join->session, table,
2825
 
                                          join->tmp_table_param.start_recinfo,
2826
 
                                          &join->tmp_table_param.recinfo,
2827
 
                  error, 1))
2828
 
          return NESTED_LOOP_ERROR;        // Not a table_is_full error
2829
 
        table->s->uniques= 0;                   // To ensure rows are the same
 
2818
 
 
2819
        my_error(ER_USE_SQL_BIG_RESULT, MYF(0));
 
2820
        return NESTED_LOOP_ERROR;        // Table is_full error
2830
2821
      }
2831
2822
      if (++join->send_records >= join->tmp_table_param.end_write_records && join->do_send_rows)
2832
2823
      {
2875
2866
  {                                             /* Update old record */
2876
2867
    table->restoreRecord();
2877
2868
    update_tmptable_sum_func(join->sum_funcs,table);
2878
 
    if ((error= table->cursor->ha_update_row(table->record[1],
 
2869
    if ((error= table->cursor->updateRecord(table->record[1],
2879
2870
                                          table->record[0])))
2880
2871
    {
2881
2872
      table->print_error(error,MYF(0));
2899
2890
  }
2900
2891
  init_tmptable_sum_functions(join->sum_funcs);
2901
2892
  copy_funcs(join->tmp_table_param.items_to_copy);
2902
 
  if ((error=table->cursor->ha_write_row(table->record[0])))
 
2893
  if ((error=table->cursor->insertRecord(table->record[0])))
2903
2894
  {
2904
 
    if (create_myisam_from_heap(join->session, table,
2905
 
                                join->tmp_table_param.start_recinfo,
2906
 
                                &join->tmp_table_param.recinfo,
2907
 
                                error, 0))
2908
 
      return NESTED_LOOP_ERROR;            // Not a table_is_full error
2909
 
    /* Change method to update rows */
2910
 
    table->cursor->ha_index_init(0, 0);
2911
 
    join->join_tab[join->tables-1].next_select= end_unique_update;
 
2895
    my_error(ER_USE_SQL_BIG_RESULT, MYF(0));
 
2896
    return NESTED_LOOP_ERROR;        // Table is_full error
2912
2897
  }
2913
2898
  join->send_records++;
2914
2899
  return NESTED_LOOP_OK;
2932
2917
  copy_fields(&join->tmp_table_param);          // Groups are copied twice.
2933
2918
  copy_funcs(join->tmp_table_param.items_to_copy);
2934
2919
 
2935
 
  if (!(error= table->cursor->ha_write_row(table->record[0])))
 
2920
  if (!(error= table->cursor->insertRecord(table->record[0])))
2936
2921
    join->send_records++;                       // New group
2937
2922
  else
2938
2923
  {
2948
2933
    }
2949
2934
    table->restoreRecord();
2950
2935
    update_tmptable_sum_func(join->sum_funcs,table);
2951
 
    if ((error= table->cursor->ha_update_row(table->record[1],
 
2936
    if ((error= table->cursor->updateRecord(table->record[1],
2952
2937
                                          table->record[0])))
2953
2938
    {
2954
2939
      table->print_error(error,MYF(0));
4872
4857
    false - OK
4873
4858
    true  - Out of memory
4874
4859
*/
4875
 
static bool make_join_readinfo(JOIN *join, uint64_t options, uint32_t no_jbuf_after)
 
4860
static bool make_join_readinfo(JOIN *join)
4876
4861
{
4877
 
  uint32_t i;
4878
 
  bool statistics= test(!(join->select_options & SELECT_DESCRIBE));
4879
 
  bool sorted= 1;
 
4862
  bool sorted= true;
4880
4863
 
4881
 
  for (i=join->const_tables ; i < join->tables ; i++)
 
4864
  for (uint32_t i= join->const_tables ; i < join->tables ; i++)
4882
4865
  {
4883
4866
    JoinTable *tab=join->join_tab+i;
4884
4867
    Table *table=tab->table;
4885
 
    bool using_join_cache;
4886
4868
    tab->read_record.table= table;
4887
4869
    tab->read_record.cursor= table->cursor;
4888
4870
    tab->next_select=sub_select;                /* normal select */
4891
4873
      produce sorted output.
4892
4874
    */
4893
4875
    tab->sorted= sorted;
4894
 
    sorted= 0;                                  // only first must be sorted
 
4876
    sorted= false; // only first must be sorted
 
4877
 
4895
4878
    if (tab->insideout_match_tab)
4896
4879
    {
4897
 
      if (!(tab->insideout_buf= (unsigned char*)join->session->alloc(tab->table->key_info
4898
 
                                                         [tab->index].
4899
 
                                                         key_length)))
 
4880
      if (! (tab->insideout_buf= (unsigned char*) join->session->alloc(tab->table->key_info
 
4881
                                                                       [tab->index].
 
4882
                                                                       key_length)))
4900
4883
        return true;
4901
4884
    }
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:
 
4885
 
 
4886
    optimizer::AccessMethodFactory &factory= optimizer::AccessMethodFactory::singleton();
 
4887
    boost::shared_ptr<optimizer::AccessMethod> access_method(factory.createAccessMethod(tab->type));
 
4888
 
 
4889
    if (! access_method)
 
4890
    {
 
4891
      /**
 
4892
       * @todo
 
4893
       * Is abort() the correct thing to call here? I call this here because it was what was called in
 
4894
       * the default case for the switch statement that used to be here.
 
4895
       */
5055
4896
      abort();
5056
4897
    }
 
4898
 
 
4899
    access_method->getStats(table, tab);
5057
4900
  }
5058
 
  join->join_tab[join->tables-1].next_select=0; /* Set by do_select */
5059
 
  return(false);
 
4901
 
 
4902
  join->join_tab[join->tables-1].next_select= NULL; /* Set by do_select */
 
4903
 
 
4904
  return false;
5060
4905
}
5061
4906
 
5062
4907
/** Update the dependency map for the tables. */
6171
6016
  }
6172
6017
}
6173
6018
 
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
6019
 
6203
6020
/**
6204
6021
  Create a condition for a const reference and add this to the