My Project
|
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 */