List:Commits« Previous MessageNext Message »
From:Sergey Petrunia Date:October 20 2007 6:05pm
Subject:bk commit into 5.2 tree (sergefp:1.2588)
View as plain text  
Below is the list of changes that have just been committed into a local
5.2 repository of psergey. When psergey does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet@stripped, 2007-10-20 20:05:00+04:00, sergefp@stripped +4 -0
  WL#2771 Batched Key Access:
  - Quick hack implementation of BKA + semi-join FirstMatch strategy

  sql/handler.cc@stripped, 2007-10-20 20:04:55+04:00, sergefp@stripped +40 -32
    WL#2771 Batched Key Access:
    - Quick hack implementation of BKA + semi-join FirstMatch strategy

  sql/handler.h@stripped, 2007-10-20 20:04:55+04:00, sergefp@stripped +16 -0
    WL#2771 Batched Key Access:
    - Quick hack implementation of BKA + semi-join FirstMatch strategy

  sql/sql_select.cc@stripped, 2007-10-20 20:04:55+04:00, sergefp@stripped +20 -6
    WL#2771 Batched Key Access:
    - Quick hack implementation of BKA + semi-join FirstMatch strategy

  sql/sql_select.h@stripped, 2007-10-20 20:04:55+04:00, sergefp@stripped +18 -7
    WL#2771 Batched Key Access:
    - Quick hack implementation of BKA + semi-join FirstMatch strategy

diff -Nrup a/sql/handler.cc b/sql/handler.cc
--- a/sql/handler.cc	2007-08-27 02:38:28 +04:00
+++ b/sql/handler.cc	2007-10-20 20:04:55 +04:00
@@ -3457,6 +3457,8 @@ int DsMrr_impl::dsmrr_init(handler *h, K
   rowids_buf += key->key_length + h->ref_length;
 
   is_mrr_assoc= !test(mode & HA_MRR_NO_ASSOCIATION);
+  semi_join= test(mode & HA_MRR_SEMI_JOIN);
+  DBUG_ASSERT(!semi_join || is_mrr_assoc);
   rowids_buf_end= buf->buffer_end;
   
   elem_size= h->ref_length + (int)is_mrr_assoc * sizeof(void*);
@@ -3572,15 +3574,18 @@ int DsMrr_impl::dsmrr_fill_buffer(handle
   while ((rowids_buf_cur < rowids_buf_end) && 
          !(res= h->handler::multi_range_read_next(&range_info)))
   {
-    /* Put rowid, or {rowid, range_id} pair into the buffer */
-    h->position(h->table->record[0]);
-    memcpy(rowids_buf_cur, h->ref, h->ref_length);
-    rowids_buf_cur += h->ref_length;
-
-    if (is_mrr_assoc)
+    if (!semi_join || *range_info==0)
     {
-      memcpy(rowids_buf_cur, &range_info, sizeof(void*));
-      rowids_buf_cur += sizeof(void*);
+      /* Put rowid, or {rowid, range_id} pair into the buffer */
+      h->position(h->table->record[0]);
+      memcpy(rowids_buf_cur, h->ref, h->ref_length);
+      rowids_buf_cur += h->ref_length;
+
+      if (is_mrr_assoc)
+      {
+        memcpy(rowids_buf_cur, &range_info, sizeof(void*));
+        rowids_buf_cur += sizeof(void*);
+      }
     }
   }
 
@@ -3607,40 +3612,43 @@ int DsMrr_impl::dsmrr_fill_buffer(handle
 int DsMrr_impl::dsmrr_next(handler *h, char **range_info)
 {
   int res;
+  uchar *cur_rowid;
   
   if (use_default_impl)
     return h->handler::multi_range_read_next(range_info);
     
-  if (rowids_buf_cur == rowids_buf_last)
+  do
   {
-    h->table->column_bitmaps_set_no_signal(save_read_set, save_write_set);
-    if (dsmrr_eof)
+    if (rowids_buf_cur == rowids_buf_last)
+    {
+      h->table->column_bitmaps_set_no_signal(save_read_set, save_write_set);
+      if (dsmrr_eof)
+      {
+        res= HA_ERR_END_OF_FILE;
+        goto end;
+      }
+
+      res= dsmrr_fill_buffer(h);
+      h->table->column_bitmaps_set_no_signal(&row_access_bitmap,
+                                             &row_access_bitmap);
+      if (res)
+        goto end;
+    }
+    
+    /* Return EOF if there are no rowids in the buffer after re-fill attempt */
+    if (rowids_buf_cur == rowids_buf_last)
     {
       res= HA_ERR_END_OF_FILE;
       goto end;
     }
-
-    res= dsmrr_fill_buffer(h);
-    h->table->column_bitmaps_set_no_signal(&row_access_bitmap,
-                                           &row_access_bitmap);
-    if (res)
-      goto end;
-  }
-  
-  /* Return EOF if there are no rowids in the buffer after re-fill attempt */
-  if (rowids_buf_cur == rowids_buf_last)
-  {
-    res= HA_ERR_END_OF_FILE;
-    goto end;
-  }
-
-  res= h2->rnd_pos(h->table->record[0], rowids_buf_cur);
-  rowids_buf_cur += h->ref_length;
+    cur_rowid= rowids_buf_cur;
+    rowids_buf_cur += h->ref_length + sizeof(void*) * test(is_mrr_assoc);
+     
+  } while (semi_join && *(cur_rowid + h->ref_length)==0);
+ 
+  res= h2->rnd_pos(h->table->record[0], cur_rowid);
   if (is_mrr_assoc)
-  {
-    memcpy(range_info, rowids_buf_cur, sizeof(void*));
-    rowids_buf_cur += sizeof(void*);
-  }
+    memcpy(range_info, cur_rowid + h->ref_length, sizeof(void*));
 
 end:
   if (res)
diff -Nrup a/sql/handler.h b/sql/handler.h
--- a/sql/handler.h	2007-10-03 15:09:44 +04:00
+++ b/sql/handler.h	2007-10-20 20:04:55 +04:00
@@ -1091,6 +1091,16 @@ void get_sweep_read_cost(TABLE *table, h
 */
 #define HA_MRR_NO_NULL_ENDPOINTS 128
 
+/*
+  Flag set <=> We're running a first-match semi-join, and the accessed table
+  is the inner table.
+  MRR implementation may (but doesn't have to) interpret KEY_MULTI_RANGE::ptr
+  as char* need_no_more_matches, if "*need_no_more_matches=1" then the SQL
+  layer does not need any more records from this range.
+
+  HA_MRR_SEMI_JOIN cannot be used together with HA_MRR_NO_ASSOCIATION.
+*/
+#define HA_MRR_SEMI_JOIN 256
 
 class ha_statistics
 {
@@ -2064,6 +2074,12 @@ public:
 
   /* TRUE <=> need range association, buffer holds {rowid, range_id} pairs */
   bool is_mrr_assoc; 
+
+  /*
+    TRUE <=> doing a first-match semi-join, check if we need any more records in
+    the scanned range
+  */
+  bool semi_join;
 
   handler *h; /* Owner table handler */
   handler *h2; /* Slave handler for doing rnd_pos(). */
diff -Nrup a/sql/sql_select.cc b/sql/sql_select.cc
--- a/sql/sql_select.cc	2007-10-19 02:46:41 +04:00
+++ b/sql/sql_select.cc	2007-10-20 20:04:55 +04:00
@@ -1073,7 +1073,10 @@ int setup_semijoin_dups_elimination(JOIN
     {
       if (i != join->const_tables && !(options & SELECT_NO_JOIN_CACHE)
&&
           tab->type == JT_ALL && tab->use_quick != 2 &&
!tab->first_inner &&
-          i <= no_jbuf_after && !dealing_with_jbuf)
+          i <= no_jbuf_after && !dealing_with_jbuf && 
+          emb_sj_map != tab->table->map)
+          // ^ psergey-add: and there is more than one inner table in the
+          // SJ-nest
       {
         /*
           This table uses join buffering, which makes use of FirstMatch or 
@@ -13356,6 +13359,7 @@ evaluate_join_record(JOIN *join, JOIN_TA
         enumerated all the suffixes for current prefix row combination
       */
       return_tab= join_tab->do_firstmatch;
+      join_tab->found= 1; //psergey-add:
     }
 
     /*
@@ -13520,9 +13524,12 @@ JOIN_CACHE_BNL::join_records(bool skip_l
       for (i= records - (skip_last ? 1 : 0) ; i-- > 0 ;)
       {
 	get_record();
-        if (!join_tab->select || !join_tab->select->skip_record())	
+        if ((!join_tab->select || !join_tab->select->skip_record()) &&
+            (!(join_tab->emb_sj_nest->sj_inner_tables == join_tab->table->map
&&
+               join_tab->do_firstmatch == join_tab - 1) || !get_match_flag()))
         {
           int res= 0;
+          set_match_flag(1);
           if (!join_tab->check_weed_out_table || 
               !(res= do_sj_dups_weedout(join->thd,
                                         join_tab->check_weed_out_table)))
@@ -16596,7 +16603,7 @@ static uint bka_range_seq_next(range_seq
     start_key->flag= HA_READ_KEY_EXACT;
     range->end_key= *start_key;
     range->end_key.flag= HA_READ_AFTER_KEY;
-    range->ptr= (char *) cache->get_record_label();
+    range->ptr= (char *) cache->get_record_pos();
     range->range_flag= EQ_RANGE;
     DBUG_RETURN(0);
   } 
@@ -16676,8 +16683,12 @@ JOIN_CACHE_BKA::join_records(bool skip_l
   init_mrr_buff();
   if (!file->inited)
     file->ha_index_init(join_tab->ref.key, 1);
+  uint mrr_mode= 0;
+  if (join_tab->emb_sj_nest->sj_inner_tables == join_tab->table->map
&&
+      join_tab->do_firstmatch == join_tab - 1)
+    mrr_mode= HA_MRR_SEMI_JOIN;
   error= file->multi_range_read_init(&seq_funcs, (void*)this, records,
-                                     0, &mrr_buff);
+                                     mrr_mode, &mrr_buff);
 
   for (JOIN_TAB *tmp=join->join_tab; tmp != join_tab ; tmp++)
   {
@@ -16694,10 +16705,13 @@ JOIN_CACHE_BKA::join_records(bool skip_l
     }
     if (rc == NESTED_LOOP_OK)
     {
-      get_record(rec_ptr);
-      if (!join_tab->select || !join_tab->select->skip_record())	
+      get_record_by_pos(rec_ptr);
+      if ((!join_tab->select || !join_tab->select->skip_record()) &&
+          (!(join_tab->emb_sj_nest->sj_inner_tables == join_tab->table->map
&&
+               join_tab->do_firstmatch == join_tab - 1) || !get_match_flag()))
       {
         int res= 0;
+        set_match_flag(1);
         if (!join_tab->check_weed_out_table || 
             !(res= do_sj_dups_weedout(join->thd,
                                       join_tab->check_weed_out_table)))
diff -Nrup a/sql/sql_select.h b/sql/sql_select.h
--- a/sql/sql_select.h	2007-10-19 02:27:45 +04:00
+++ b/sql/sql_select.h	2007-10-20 20:04:55 +04:00
@@ -315,6 +315,7 @@ protected:
   { return length; }
   virtual uint addon_length()
   { return 0; }
+  uchar *rec_pos;
 public:
   JOIN_TAB *join_tab;
   virtual ~JOIN_CACHE() {}
@@ -335,6 +336,17 @@ public:
   virtual bool put_record()= 0;
   virtual bool get_record()= 0;
   virtual enum_nested_loop_state join_records(bool skip_last)= 0;
+  virtual uchar *get_record_pos()
+  {
+    return rec_pos;
+  }
+  
+  /*
+    Getter/setter for "there were matches" flag.
+    The said flag is the 1st byte of the cached record
+  */
+  bool get_match_flag() { return test(*get_record_pos()); }
+  void set_match_flag(bool set) { (*get_record_pos())= (uchar)set; }
 };
 
 class JOIN_CACHE_BNL :public JOIN_CACHE
@@ -352,14 +364,16 @@ public:
     return is_full;
   }
   bool get_record()
-  { return read_record_data() == 0; }
+  { 
+    rec_pos= pos;
+    return read_record_data() == 0; 
+  }
   enum_nested_loop_state join_records(bool skip_last);
 };
 
 class JOIN_CACHE_BKA :public JOIN_CACHE
 {
 protected:
-  uchar *rec_pos;
   uint key_arg_fields;
   HANDLER_BUFFER mrr_buff;
 public:
@@ -404,10 +418,6 @@ public:
     rec_pos= pos;
     return read_record_data() == 0;
   }
-  virtual uchar *get_record_label()
-  {
-    return rec_pos;
-  }
   bool is_key_access() { return TRUE; }
   int init()
   {
@@ -426,11 +436,12 @@ public:
       end_pos= end;
   }
   virtual uint get_next_key(uchar **key);    
-  virtual void get_record(uchar *rec_ptr)
+  virtual void get_record_by_pos(uchar *rec_ptr)
   {
     uchar *save_pos= pos;
     uint save_record_nr= record_nr;
     pos= rec_ptr;
+    rec_pos= pos;
     record_nr= 0;
     read_record_data();
     pos= save_pos;
Thread
bk commit into 5.2 tree (sergefp:1.2588)Sergey Petrunia22 Oct