My Project
sql_join_buffer.h
00001 #ifndef SQL_JOIN_CACHE_INCLUDED
00002 #define SQL_JOIN_CACHE_INCLUDED
00003 
00004 #include "sql_executor.h"
00005 
00006 /* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
00007 
00008    This program is free software; you can redistribute it and/or modify
00009    it under the terms of the GNU General Public License as published by
00010    the Free Software Foundation; version 2 of the License.
00011 
00012    This program is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License
00018    along with this program; if not, write to the Free Software
00019    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
00020 
00023 /* 
00024   Categories of data fields of variable length written into join cache buffers.
00025   The value of any of these fields is written into cache together with the
00026   prepended length of the value.     
00027 */
00028 #define CACHE_BLOB      1        /* blob field  */
00029 #define CACHE_STRIPPED  2        /* field stripped of trailing spaces */
00030 #define CACHE_VARSTR1   3        /* short string value (length takes 1 byte) */ 
00031 #define CACHE_VARSTR2   4        /* long string value (length takes 2 bytes) */
00032 
00033 /*
00034   The CACHE_FIELD structure used to describe fields of records that
00035   are written into a join cache buffer from record buffers and backward.
00036 */
00037 typedef struct st_cache_field {
00038   uchar *str;   
00039   uint length;  
00040   /* 
00041     Field object for the moved field
00042     (0 - for a flag field, see JOIN_CACHE::create_flag_fields).
00043   */
00044   Field *field;
00045   uint type;    
00046   /* 
00047     The number of the record offset value for the field in the sequence
00048     of offsets placed after the last field of the record. These
00049     offset values are used to access fields referred to from other caches.
00050     If the value is 0 then no offset for the field is saved in the
00051     trailing sequence of offsets.
00052   */ 
00053   uint referenced_field_no; 
00055   st_cache_field *next_copy_rowid;
00056   /* The remaining structure fields are used as containers for temp values */
00057   uint blob_length; 
00058   uint offset;      
00060   void bind_buffer(uchar *buffer)
00061   {
00062     if (next_copy_rowid != NULL)
00063       next_copy_rowid->bind_buffer(buffer);
00064     str= buffer;
00065   }
00066   bool buffer_is_bound() const { return str != NULL; }
00067 } CACHE_FIELD;
00068 
00069 
00070 /*
00071   JOIN_CACHE is the base class to support the implementations of both
00072   Blocked-Based Nested Loops (BNL) Join Algorithm and Batched Key Access (BKA)
00073   Join Algorithm. The first algorithm is supported by the derived class
00074   JOIN_CACHE_BNL, while the second algorithm is supported by the derived
00075   class JOIN_CACHE_BKA.
00076   These two algorithms have a lot in common. Both algorithms first
00077   accumulate the records of the left join operand in a join buffer and
00078   then search for matching rows of the second operand for all accumulated
00079   records.
00080   For the first algorithm this strategy saves on logical I/O operations:
00081   the entire set of records from the join buffer requires only one look-through
00082   the records provided by the second operand. 
00083   For the second algorithm the accumulation of records allows to optimize
00084   fetching rows of the second operand from disk for some engines (MyISAM, 
00085   InnoDB), or to minimize the number of round-trips between the Server and
00086   the engine nodes (NDB Cluster).        
00087 */ 
00088 
00089 class JOIN_CACHE :public QEP_operation
00090 {
00091 
00092 private:
00093 
00094   /* Size of the offset of a record from the cache */   
00095   uint size_of_rec_ofs;    
00096   /* Size of the length of a record in the cache */
00097   uint size_of_rec_len;
00098   /* Size of the offset of a field within a record in the cache */   
00099   uint size_of_fld_ofs;
00100 
00101 protected:
00102        
00103   /* 3 functions below actually do not use the hidden parameter 'this' */ 
00104 
00105   /* Calculate the number of bytes used to store an offset value */
00106   uint offset_size(ulong len)
00107   {
00108     if (len <= 0xFFUL)
00109       return 1;
00110     if (len <= 0xFFFFUL)
00111       return 2;
00112     if (len <= 0xFFFFFFFFUL)
00113       return 4;
00114     return 8;
00115   }
00116 
00117   /* Get the offset value that takes ofs_sz bytes at the position ptr */
00118   ulong get_offset(uint ofs_sz, uchar *ptr)
00119   {
00120     switch (ofs_sz) {
00121     case 1: return uint(*ptr);
00122     case 2: return uint2korr(ptr);
00123     case 4: return uint4korr(ptr);
00124     case 8: return uint8korr(ptr);
00125     }
00126     return 0;
00127   }
00128 
00129   /* Set the offset value ofs that takes ofs_sz bytes at the position ptr */ 
00130   void store_offset(uint ofs_sz, uchar *ptr, ulong ofs)
00131   {
00132     switch (ofs_sz) {
00133     case 1: *ptr= (uchar) ofs; return;
00134     case 2: int2store(ptr, (uint16) ofs); return;
00135     case 4: int4store(ptr, (uint32) ofs); return;
00136     case 8: int8store(ptr, (uint64) ofs); return;
00137     }
00138   }
00139 
00140   /* 
00141     The total maximal length of the fields stored for a record in the cache.
00142     For blob fields only the sizes of the blob lengths are taken into account. 
00143   */
00144   uint length;
00145 
00146   /* 
00147     Representation of the executed multi-way join through which all needed
00148     context can be accessed.  
00149   */   
00150   JOIN *join;  
00151 
00152   /* 
00153     Cardinality of the range of join tables whose fields can be put into the
00154     cache. (A table from the range not necessarily contributes to the cache.)
00155   */
00156   uint tables;
00157 
00158   /* 
00159     The total number of flag and data fields that can appear in a record
00160     written into the cache. Fields with null values are always skipped 
00161     to save space. 
00162   */
00163   uint fields;
00164 
00165   /* 
00166     The total number of flag fields in a record put into the cache. They are
00167     used for table null bitmaps, table null row flags, and an optional match
00168     flag. Flag fields go before other fields in a cache record with the match
00169     flag field placed always at the very beginning of the record.
00170   */
00171   uint flag_fields;
00172 
00173   /* The total number of blob fields that are written into the cache */ 
00174   uint blobs;
00175 
00176   /* 
00177     The total number of fields referenced from field descriptors for other join
00178     caches. These fields are used to construct key values to access matching
00179     rows with index lookups. Currently the fields can be referenced only from
00180     descriptors for bka caches. However they may belong to a cache of any type.
00181   */   
00182   uint referenced_fields;
00183    
00184   /* 
00185     The current number of already created data field descriptors.
00186     This number can be useful for implementations of the init methods.  
00187   */
00188   uint data_field_count; 
00189 
00190   /* 
00191     The current number of already created pointers to the data field
00192     descriptors. This number can be useful for implementations of
00193     the init methods.  
00194   */
00195   uint data_field_ptr_count; 
00196   /* 
00197     Array of the descriptors of fields containing 'fields' elements.
00198     These are all fields that are stored for a record in the cache. 
00199   */
00200   CACHE_FIELD *field_descr;
00201 
00202   /* 
00203     Array of pointers to the blob descriptors that contains 'blobs' elements.
00204   */
00205   CACHE_FIELD **blob_ptr;
00206 
00207   /* 
00208     This flag indicates that records written into the join buffer contain
00209     a match flag field. The flag must be set by the init method. 
00210   */
00211   bool with_match_flag; 
00212   /*
00213     This flag indicates that any record is prepended with the length of the
00214     record which allows us to skip the record or part of it without reading.
00215   */
00216   bool with_length;
00217 
00218   /* 
00219     The maximal number of bytes used for a record representation in
00220     the cache excluding the space for blob data. 
00221     For future derived classes this representation may contains some
00222     redundant info such as a key value associated with the record.     
00223   */
00224   uint pack_length;
00225   /* 
00226     The value of pack_length incremented by the total size of all 
00227     pointers of a record in the cache to the blob data. 
00228   */
00229   uint pack_length_with_blob_ptrs;
00230 
00231   /* Pointer to the beginning of the join buffer */
00232   uchar *buff;         
00233   /* 
00234     Size of the entire memory allocated for the join buffer.
00235     Part of this memory may be reserved for the auxiliary buffer.
00236   */ 
00237   ulong buff_size;
00238   /* Size of the auxiliary buffer. */ 
00239   ulong aux_buff_size;
00240 
00241   /* The number of records put into the join buffer */ 
00242   uint records;
00243 
00244   /* 
00245     Pointer to the current position in the join buffer.
00246     This member is used both when writing to buffer and
00247     when reading from it.
00248   */
00249   uchar *pos;
00250   /* 
00251     Pointer to the first free position in the join buffer,
00252     right after the last record into it.
00253   */
00254   uchar *end_pos; 
00255 
00256   /* 
00257     Pointer to the beginning of first field of the current read/write record
00258     from the join buffer. The value is adjusted by the get_record/put_record
00259     functions.
00260   */
00261   uchar *curr_rec_pos;
00262   /* 
00263     Pointer to the beginning of first field of the last record
00264     from the join buffer.
00265   */
00266   uchar *last_rec_pos;
00267 
00268   /* 
00269     Flag is set if the blob data for the last record in the join buffer
00270     is in record buffers rather than in the join cache.
00271   */
00272   bool last_rec_blob_data_is_in_rec_buff;
00273 
00274   /* 
00275     Pointer to the position to the current record link. 
00276     Record links are used only with linked caches. Record links allow to set
00277     connections between parts of one join record that are stored in different
00278     join buffers.
00279     In the simplest case a record link is just a pointer to the beginning of
00280     the record stored in the buffer.
00281     In a more general case a link could be a reference to an array of pointers
00282     to records in the buffer.   */
00283   uchar *curr_rec_link;
00284 
00286   bool check_only_first_match;
00287 
00288   void calc_record_fields();     
00289   int alloc_fields(uint external_fields);
00290   void create_flag_fields();
00291   void create_remaining_fields(bool all_read_fields);
00292   void set_constants();
00293   bool alloc_buffer();
00294 
00295   uint get_size_of_rec_offset() { return size_of_rec_ofs; }
00296   uint get_size_of_rec_length() { return size_of_rec_len; }
00297   uint get_size_of_fld_offset() { return size_of_fld_ofs; }
00298 
00299   uchar *get_rec_ref(uchar *ptr)
00300   {
00301     return buff+get_offset(size_of_rec_ofs, ptr-size_of_rec_ofs);
00302   }
00303   ulong get_rec_length(uchar *ptr)
00304   { 
00305     return get_offset(size_of_rec_len, ptr);
00306   }
00307   ulong get_fld_offset(uchar *ptr)
00308   { 
00309     return get_offset(size_of_fld_ofs, ptr);
00310   }
00311 
00312   void store_rec_ref(uchar *ptr, uchar* ref)
00313   {
00314     store_offset(size_of_rec_ofs, ptr-size_of_rec_ofs, (ulong) (ref-buff));
00315   }
00316 
00317   void store_rec_length(uchar *ptr, ulong len)
00318   {
00319     store_offset(size_of_rec_len, ptr, len);
00320   }
00321   void store_fld_offset(uchar *ptr, ulong ofs)
00322   {
00323     store_offset(size_of_fld_ofs, ptr, ofs);
00324   }
00325 
00326   /* Write record fields and their required offsets into the join buffer */ 
00327   uint write_record_data(uchar *link, bool *is_full);
00328 
00329   /* 
00330     This method must determine for how much the auxiliary buffer should be
00331     incremented when a new record is added to the join buffer.
00332     If no auxiliary buffer is needed the function should return 0.
00333   */
00334   virtual uint aux_buffer_incr() { return 0; }
00335 
00340   virtual uint aux_buffer_min_size() const { return 0; }
00341 
00342   /* Shall calculate how much space is remaining in the join buffer */ 
00343   virtual ulong rem_space() 
00344   { 
00345     return std::max<ulong>(buff_size-(end_pos-buff)-aux_buff_size, 0UL);
00346   }
00347 
00348   /* Shall skip record from the join buffer if its match flag is on */
00349   virtual bool skip_record_if_match();
00350 
00351   /* Read some flag and data fields of a record from the join buffer */
00352   int read_some_record_fields();
00353 
00354   /* Read some flag fields of a record from the join buffer */
00355   void read_some_flag_fields();
00356 
00357   /* Read all flag fields of the record which is at position rec_ptr */
00358   void read_all_flag_fields_by_pos(uchar *rec_ptr);
00359 
00360   /* Read a data record field from the join buffer */
00361   uint read_record_field(CACHE_FIELD *copy, bool last_record);
00362 
00363   /* Read a referenced field from the join buffer */
00364   bool read_referenced_field(CACHE_FIELD *copy, uchar *rec_ptr, uint *len);
00365 
00366   /* 
00367     True if rec_ptr points to the record whose blob data stay in
00368     record buffers
00369   */
00370   bool blob_data_is_in_rec_buff(uchar *rec_ptr)
00371   {
00372     return rec_ptr == last_rec_pos && last_rec_blob_data_is_in_rec_buff;
00373   }
00374 
00375   /* Find matches from the next table for records from the join buffer */   
00376   virtual enum_nested_loop_state join_matching_records(bool skip_last)=0;
00377 
00378   /* Add null complements for unmatched outer records from buffer */
00379   virtual enum_nested_loop_state join_null_complements(bool skip_last);
00380 
00381   /* Restore the fields of the last record from the join buffer */
00382   virtual void restore_last_record();
00383 
00384   /*Set match flag for a record in join buffer if it has not been set yet */
00385   bool set_match_flag_if_none(JOIN_TAB *first_inner, uchar *rec_ptr);
00386 
00387   enum_nested_loop_state generate_full_extensions(uchar *rec_ptr);
00388 
00389   /* Check matching to a partial join record from the join buffer */
00390   virtual bool check_match(uchar *rec_ptr);
00391 
00393   bool calc_check_only_first_match(const JOIN_TAB *t) const
00394   {
00395     return (t->last_sj_inner_tab == t &&
00396             t->get_sj_strategy() == SJ_OPT_FIRST_MATCH) ||
00397       (t->first_inner && t->first_inner->last_inner == t &&
00398        t->table->reginfo.not_exists_optimize);
00399   }
00400 
00401   /* 
00402     This function shall add a record into the join buffer and return TRUE
00403     if it has been decided that it should be the last record in the buffer.
00404   */ 
00405   virtual bool put_record_in_cache();
00406 
00407 public:
00408   /* Pointer to the previous join cache if there is any */
00409   JOIN_CACHE *prev_cache;
00410   /* Pointer to the next join cache if there is any */
00411   JOIN_CACHE *next_cache;
00412 
00413   /* Shall initialize the join cache structure */ 
00414   virtual int init()=0;  
00415 
00416   /* The function shall return TRUE only for BKA caches */
00417   virtual bool is_key_access() { return FALSE; }
00418 
00419   /* Shall reset the join buffer for reading/writing */
00420   virtual void reset_cache(bool for_writing);
00421 
00422   /* Add a record into join buffer and call join_records() if it's full */
00423   virtual enum_nested_loop_state put_record()
00424   {
00425     if (put_record_in_cache())
00426       return join_records(false);
00427     return NESTED_LOOP_OK;
00428   }
00429   /* 
00430     This function shall read the next record into the join buffer and return
00431     TRUE if there is no more next records.
00432   */ 
00433   virtual bool get_record();
00434 
00435   /* 
00436     This function shall read the record at the position rec_ptr
00437     in the join buffer
00438   */ 
00439   virtual void get_record_by_pos(uchar *rec_ptr);
00440 
00441   /* Shall return the value of the match flag for the positioned record */
00442   virtual bool get_match_flag_by_pos(uchar *rec_ptr);
00443 
00444   /* Shall return the position of the current record */
00445   virtual uchar *get_curr_rec() { return curr_rec_pos; }
00446 
00447   /* Shall set the current record link */
00448   virtual void set_curr_rec_link(uchar *link) { curr_rec_link= link; }
00449 
00450   /* Shall return the current record link */
00451   virtual uchar *get_curr_rec_link()
00452   { 
00453     return (curr_rec_link ? curr_rec_link : get_curr_rec());
00454   }
00455      
00456   /* Join records from the join buffer with records from the next join table */
00457   enum_nested_loop_state end_send() { return join_records(false); };
00458   enum_nested_loop_state join_records(bool skip_last);
00459 
00460   enum_op_type type() { return OT_CACHE; }
00461 
00469   JOIN_CACHE(JOIN *j, JOIN_TAB *tab, JOIN_CACHE *prev)
00470     : QEP_operation(tab), join(j), buff(NULL), prev_cache(prev),
00471     next_cache(NULL)
00472     {
00473       if (prev_cache)
00474         prev_cache->next_cache= this;
00475     }
00476   virtual ~JOIN_CACHE() {}
00477   void free()
00478   {
00479     /*
00480       JOIN_CACHE doesn't support unlinking cache chain. This code is needed
00481       only by set_join_cache_denial().
00482     */
00483     /*
00484       If there is a previous/next cache linked to this cache through the
00485       (next|prev)_cache pointer: remove the link. 
00486     */
00487     if (prev_cache)
00488       prev_cache->next_cache= NULL;
00489     if (next_cache)
00490       next_cache->prev_cache= NULL;
00491 
00492     my_free(buff);
00493     buff= NULL;
00494   }
00495 
00497   enum {ALG_NONE= 0, ALG_BNL= 1, ALG_BKA= 2, ALG_BKA_UNIQUE= 4};
00498 
00499   friend class JOIN_CACHE_BNL;
00500   friend class JOIN_CACHE_BKA;
00501   friend class JOIN_CACHE_BKA_UNIQUE;
00502 };
00503 
00504 class JOIN_CACHE_BNL :public JOIN_CACHE
00505 {
00506 
00507 protected:
00508 
00509   /* Using BNL find matches from the next table for records from join buffer */
00510   enum_nested_loop_state join_matching_records(bool skip_last);
00511 
00512 public:
00513   JOIN_CACHE_BNL(JOIN *j, JOIN_TAB *tab, JOIN_CACHE *prev)
00514     : JOIN_CACHE(j, tab, prev)
00515   {}
00516 
00517   /* Initialize the BNL cache */       
00518   int init();
00519 
00520 };
00521 
00522 class JOIN_CACHE_BKA :public JOIN_CACHE
00523 {
00524 protected:
00525 
00526   /* Flag to to be passed to the MRR interface */ 
00527   uint mrr_mode;
00528 
00529   /* MRR buffer assotiated with this join cache */
00530   HANDLER_BUFFER mrr_buff;
00531 
00532   /* Shall initialize the MRR buffer */
00533   virtual void init_mrr_buff()
00534   {
00535     mrr_buff.buffer= end_pos;
00536     mrr_buff.buffer_end= buff+buff_size;
00537   }
00538 
00539   /*
00540     The number of the cache fields that are used in building keys to access
00541     the table join_tab
00542   */
00543   uint local_key_arg_fields;
00544   /* 
00545     The total number of the fields in the previous caches that are used
00546     in building keys t access the table join_tab
00547   */
00548   uint external_key_arg_fields;
00549 
00550   /* 
00551     This flag indicates that the key values will be read directly from the join
00552     buffer. It will save us building key values in the key buffer.
00553   */
00554   bool use_emb_key;
00555   /* The length of an embedded key value */ 
00556   uint emb_key_length;
00557 
00558   /* Check the possibility to read the access keys directly from join buffer */  
00559   bool check_emb_key_usage();
00560 
00562   uint aux_buffer_incr();
00563 
00565   uint aux_buffer_min_size() const;
00566 
00567   /* Using BKA find matches from the next table for records from join buffer */
00568   enum_nested_loop_state join_matching_records(bool skip_last);
00569 
00570   /* Prepare to search for records that match records from the join buffer */
00571   bool init_join_matching_records(RANGE_SEQ_IF *seq_funcs, uint ranges);
00572 
00573 public:
00574   
00576   JOIN_CACHE_BKA(JOIN *j, JOIN_TAB *tab, uint flags, JOIN_CACHE* prev)
00577     : JOIN_CACHE(j, tab, prev), mrr_mode(flags)
00578   {}
00579 
00580   /* Initialize the BKA cache */       
00581   int init();
00582 
00583   bool is_key_access() { return TRUE; }
00584 
00585   /* Shall get the key built over the next record from the join buffer */
00586   virtual uint get_next_key(uchar **key);
00587 
00588   /* Check if the record combination matches the index condition */
00589   bool skip_index_tuple(range_seq_t rseq, char *range_info);
00590 };
00591 
00592 /*
00593   The class JOIN_CACHE_BKA_UNIQUE supports the variant of the BKA join algorithm
00594   that submits only distinct keys to the MRR interface. The records in the join
00595   buffer of a cache of this class that have the same access key are linked into
00596   a chain attached to a key entry structure that either itself contains the key
00597   value, or, in the case when the keys are embedded, refers to its occurance in
00598   one of the records from the chain.
00599   To build the chains with the same keys a hash table is employed. It is placed
00600   at the very end of the join buffer. The array of hash entries is allocated
00601   first at the very bottom of the join buffer, then go key entries. A hash entry
00602   contains a header of the list of the key entries with the same hash value. 
00603   Each key entry is a structure of the following type:
00604     struct st_join_cache_key_entry {
00605       union { 
00606         uchar[] value;
00607         cache_ref *value_ref; // offset from the beginning of the buffer
00608       } hash_table_key;
00609       key_ref next_key; // offset backward from the beginning of hash table
00610       cache_ref *last_rec // offset from the beginning of the buffer
00611     }
00612   The references linking the records in a chain are always placed at the very
00613   beginning of the record info stored in the join buffer. The records are 
00614   linked in a circular list. A new record is always added to the end of this 
00615   list. When a key is passed to the MRR interface it can be passed either with
00616   an association link containing a reference to the header of the record chain
00617   attached to the corresponding key entry in the hash table, or without any
00618   association link. When the next record is returned by a call to the MRR 
00619   function multi_range_read_next without any association (because if was not
00620   passed  together with the key) then the key value is extracted from the
00621   returned record and searched for it in the hash table. If there is any records
00622   with such key the chain of them will be yielded as the result of this search.
00623 
00624   The following picture represents a typical layout for the info stored in the
00625   join buffer of a join cache object of the JOIN_CACHE_BKA_UNIQUE class.
00626     
00627   buff
00628   V
00629   +----------------------------------------------------------------------------+
00630   |     |[*]record_1_1|                                                        |
00631   |     ^ |                                                                    |
00632   |     | +--------------------------------------------------+                 |
00633   |     |                           |[*]record_2_1|          |                 |
00634   |     |                           ^ |                      V                 |
00635   |     |                           | +------------------+   |[*]record_1_2|   |
00636   |     |                           +--------------------+-+   |               |
00637   |+--+ +---------------------+                          | |   +-------------+ |
00638   ||  |                       |                          V |                 | |
00639   |||[*]record_3_1|         |[*]record_1_3|              |[*]record_2_2|     | |
00640   ||^                       ^                            ^                   | |
00641   ||+----------+            |                            |                   | |
00642   ||^          |            |<---------------------------+-------------------+ |
00643   |++          | | ... mrr  |   buffer ...           ... |     |               |
00644   |            |            |                            |                     |
00645   |      +-----+--------+   |                      +-----|-------+             |
00646   |      V     |        |   |                      V     |       |             |
00647   ||key_3|[/]|[*]|      |   |                |key_2|[/]|[*]|     |             |
00648   |                   +-+---|-----------------------+            |             |
00649   |                   V |   |                       |            |             |
00650   |             |key_1|[*]|[*]|         |   | ... |[*]|   ...  |[*]|  ...  |   |
00651   +----------------------------------------------------------------------------+
00652                                         ^           ^            ^
00653                                         |           i-th entry   j-th entry
00654                                         hash table
00655 
00656   i-th hash entry:
00657     circular record chain for key_1:
00658       record_1_1
00659       record_1_2
00660       record_1_3 (points to record_1_1)
00661     circular record chain for key_3:
00662       record_3_1 (points to itself)
00663 
00664   j-th hash entry:
00665     circular record chain for key_2:
00666       record_2_1
00667       record_2_2 (points to record_2_1)
00668 
00669 */
00670 
00671 class JOIN_CACHE_BKA_UNIQUE :public JOIN_CACHE_BKA
00672 {
00673 
00674 private:
00675 
00676   /* Size of the offset of a key entry in the hash table */
00677   uint size_of_key_ofs;
00678 
00679   /* 
00680     Length of a key value.
00681     It is assumed that all key values have the same length.
00682   */
00683   uint key_length;
00684   /* 
00685     Length of the key entry in the hash table.
00686     A key entry either contains the key value, or it contains a reference
00687     to the key value if use_emb_key flag is set for the cache.
00688   */ 
00689   uint key_entry_length;
00690  
00691   /* The beginning of the hash table in the join buffer */
00692   uchar *hash_table;
00693   /* Number of hash entries in the hash table */
00694   uint hash_entries;
00695 
00696   /* Number of key entries in the hash table (number of distinct keys) */
00697   uint key_entries;
00698 
00699   /* The position of the last key entry in the hash table */
00700   uchar *last_key_entry;
00701 
00702   /* The position of the currently retrieved key entry in the hash table */
00703   uchar *curr_key_entry;
00704 
00705   /* 
00706     The offset of the record fields from the beginning of the record
00707     representation. The record representation starts with a reference to
00708     the next record in the key record chain followed by the length of
00709     the trailing record data followed by a reference to the record segment
00710      in the previous cache, if any, followed by the record fields.
00711   */ 
00712   uint rec_fields_offset;
00713   /* The offset of the data fields from the beginning of the record fields */
00714   uint data_fields_offset;
00715   
00716   uint get_hash_idx(uchar* key, uint key_len);
00717 
00718   void cleanup_hash_table();
00719   
00720 protected:
00721 
00722   uint get_size_of_key_offset() { return size_of_key_ofs; }
00723 
00724   /* 
00725     Get the position of the next_key_ptr field pointed to by 
00726     a linking reference stored at the position key_ref_ptr. 
00727     This reference is actually the offset backward from the
00728     beginning of hash table.
00729   */  
00730   uchar *get_next_key_ref(uchar *key_ref_ptr)
00731   {
00732     return hash_table-get_offset(size_of_key_ofs, key_ref_ptr);
00733   }
00734 
00735   /* 
00736     Store the linking reference to the next_key_ptr field at 
00737     the position key_ref_ptr. The position of the next_key_ptr
00738     field is pointed to by ref. The stored reference is actually
00739     the offset backward from the beginning of the hash table.
00740   */  
00741   void store_next_key_ref(uchar *key_ref_ptr, uchar *ref)
00742   {
00743     store_offset(size_of_key_ofs, key_ref_ptr, (ulong) (hash_table-ref));
00744   }     
00745   
00746   /* 
00747     Check whether the reference to the next_key_ptr field at the position
00748     key_ref_ptr contains  a nil value.
00749   */
00750   bool is_null_key_ref(uchar *key_ref_ptr)
00751   {
00752     ulong nil= 0;
00753     return memcmp(key_ref_ptr, &nil, size_of_key_ofs ) == 0;
00754   } 
00755 
00756   /* 
00757     Set the reference to the next_key_ptr field at the position
00758     key_ref_ptr equal to nil.
00759   */
00760   void store_null_key_ref(uchar *key_ref_ptr)
00761   {
00762     ulong nil= 0;
00763     store_offset(size_of_key_ofs, key_ref_ptr, nil);
00764   } 
00765 
00766   uchar *get_next_rec_ref(uchar *ref_ptr)
00767   {
00768     return buff+get_offset(get_size_of_rec_offset(), ref_ptr);
00769   }
00770 
00771   void store_next_rec_ref(uchar *ref_ptr, uchar *ref)
00772   {
00773     store_offset(get_size_of_rec_offset(), ref_ptr, (ulong) (ref-buff));
00774   }     
00775  
00776   /*
00777     Get the position of the embedded key value for the current
00778     record pointed to by get_curr_rec().
00779   */ 
00780   uchar *get_curr_emb_key()
00781   {
00782     return get_curr_rec()+data_fields_offset;
00783   }
00784 
00785   /*
00786     Get the position of the embedded key value pointed to by a reference
00787     stored at ref_ptr. The stored reference is actually the offset from
00788     the beginning of the join buffer.
00789   */  
00790   uchar *get_emb_key(uchar *ref_ptr)
00791   {
00792     return buff+get_offset(get_size_of_rec_offset(), ref_ptr);
00793   }
00794 
00795   /* 
00796     Store the reference to an embedded key at the position key_ref_ptr.
00797     The position of the embedded key is pointed to by ref. The stored
00798     reference is actually the offset from the beginning of the join buffer.
00799   */  
00800   void store_emb_key_ref(uchar *ref_ptr, uchar *ref)
00801   {
00802     store_offset(get_size_of_rec_offset(), ref_ptr, (ulong) (ref-buff));
00803   }
00804   
00805   /* 
00806     Calculate how much space in the buffer would not be occupied by
00807     records, key entries and additional memory for the MMR buffer.
00808   */ 
00809   ulong rem_space() 
00810   { 
00811     return std::max<ulong>(last_key_entry-end_pos-aux_buff_size, 0UL);
00812   }
00813 
00814   /* 
00815     Initialize the MRR buffer allocating some space within the join buffer.
00816     The entire space between the last record put into the join buffer and the
00817     last key entry added to the hash table is used for the MRR buffer.
00818   */
00819   void init_mrr_buff()
00820   {
00821     mrr_buff.buffer= end_pos;
00822     mrr_buff.buffer_end= last_key_entry;
00823   }
00824 
00825   /* Skip record from JOIN_CACHE_BKA_UNIQUE buffer if its match flag is on */
00826   bool skip_record_if_match();
00827 
00828   /* Using BKA_UNIQUE find matches for records from join buffer */
00829   enum_nested_loop_state join_matching_records(bool skip_last);
00830 
00831   /* Search for a key in the hash table of the join buffer */
00832   bool key_search(uchar *key, uint key_len, uchar **key_ref_ptr);
00833 
00834   virtual bool check_match(uchar *rec_ptr);
00835 
00836   /* Add a record into the JOIN_CACHE_BKA_UNIQUE buffer */
00837   bool put_record_in_cache();
00838 
00839 public:
00840 
00841   JOIN_CACHE_BKA_UNIQUE(JOIN *j, JOIN_TAB *tab, uint flags, JOIN_CACHE* prev)
00842     : JOIN_CACHE_BKA(j, tab, flags, prev)
00843   {}
00844 
00845   /* Initialize the BKA_UNIQUE cache */       
00846   int init();
00847 
00848   /* Reset the JOIN_CACHE_BKA_UNIQUE  buffer for reading/writing */
00849   void reset_cache(bool for_writing);
00850 
00851   /* Read the next record from the JOIN_CACHE_BKA_UNIQUE buffer */
00852   bool get_record();
00853 
00854   /*
00855     Shall check whether all records in a key chain have 
00856     their match flags set on
00857   */   
00858   virtual bool check_all_match_flags_for_key(uchar *key_chain_ptr);
00859 
00860   uint get_next_key(uchar **key); 
00861   
00862   /* Get the head of the record chain attached to the current key entry */ 
00863   uchar *get_curr_key_chain()
00864   {
00865     return get_next_rec_ref(curr_key_entry+key_entry_length-
00866                             get_size_of_rec_offset());
00867   }
00868   
00869   /* Check if the record combination matches the index condition */
00870   bool skip_index_tuple(range_seq_t rseq, char *range_info);
00871 };
00872 
00873 
00874 #endif /* SQL_JOIN_CACHE_INCLUDED */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines