summaryrefslogtreecommitdiff
path: root/sql/sql_join_cache.cc
diff options
context:
space:
mode:
authorunknown <sanja@askmonty.org>2012-12-23 23:37:11 +0200
committerunknown <sanja@askmonty.org>2012-12-23 23:37:11 +0200
commit61412c0c31138ca2e08636c10823bc55e6a7a84c (patch)
treeaf7b89ebb5f2334b21ab1f658d764829bfcbf7e1 /sql/sql_join_cache.cc
parent88b59efef6ae869bac9d14cefe2982a1061d3c93 (diff)
parent082ff5931770ed70df0ec1e85f81fa880a4d9e62 (diff)
downloadmariadb-git-61412c0c31138ca2e08636c10823bc55e6a7a84c.tar.gz
pre-merge
Diffstat (limited to 'sql/sql_join_cache.cc')
-rw-r--r--sql/sql_join_cache.cc988
1 files changed, 495 insertions, 493 deletions
diff --git a/sql/sql_join_cache.cc b/sql/sql_join_cache.cc
index 07266cc9cbe..4626f30df28 100644
--- a/sql/sql_join_cache.cc
+++ b/sql/sql_join_cache.cc
@@ -3894,13 +3894,15 @@ int JOIN_TAB_SCAN_MRR::next()
int rc= join_tab->table->file->multi_range_read_next((range_id_t*)ptr) ? -1 : 0;
if (!rc)
{
- /*
+ /*
If a record in in an incremental cache contains no fields then the
association for the last record in cache will be equal to cache->end_pos
- */
- DBUG_ASSERT((!(mrr_mode & HA_MRR_NO_ASSOCIATION))?
- (cache->buff <= (uchar *) (*ptr) &&
- (uchar *) (*ptr) <= cache->end_pos): TRUE);
+ */
+ /*
+ psergey: this makes no sense where HA_MRR_NO_ASSOC is used.
+ DBUG_ASSERT(cache->buff <= (uchar *) (*ptr) &&
+ (uchar *) (*ptr) <= cache->end_pos);
+ */
if (join_tab->table->vfield)
update_virtual_fields(join->thd, join_tab->table);
}
@@ -3910,663 +3912,663 @@ int JOIN_TAB_SCAN_MRR::next()
static
void bka_range_seq_key_info(void *init_params, uint *length,
- key_part_map *map)
+ key_part_map *map)
{
- TABLE_REF *ref= &(((JOIN_CACHE*)init_params)->join_tab->ref);
- *length= ref->key_length;
- *map= (key_part_map(1) << ref->key_parts) - 1;
+TABLE_REF *ref= &(((JOIN_CACHE*)init_params)->join_tab->ref);
+*length= ref->key_length;
+*map= (key_part_map(1) << ref->key_parts) - 1;
}
/*
- Initialize retrieval of range sequence for BKA join algorithm
-
- SYNOPSIS
- bka_range_seq_init()
- init_params pointer to the BKA join cache object
- n_ranges the number of ranges obtained
- flags combination of MRR flags
-
- DESCRIPTION
- The function interprets init_param as a pointer to a JOIN_CACHE_BKA
- object. The function prepares for an iteration over the join keys
- built for all records from the cache join buffer.
-
- NOTE
- This function are used only as a callback function.
-
- RETURN VALUE
- init_param value that is to be used as a parameter of bka_range_seq_next()
+Initialize retrieval of range sequence for BKA join algorithm
+
+SYNOPSIS
+ bka_range_seq_init()
+ init_params pointer to the BKA join cache object
+ n_ranges the number of ranges obtained
+ flags combination of MRR flags
+
+DESCRIPTION
+ The function interprets init_param as a pointer to a JOIN_CACHE_BKA
+ object. The function prepares for an iteration over the join keys
+ built for all records from the cache join buffer.
+
+NOTE
+ This function are used only as a callback function.
+
+RETURN VALUE
+ init_param value that is to be used as a parameter of bka_range_seq_next()
*/
static
range_seq_t bka_range_seq_init(void *init_param, uint n_ranges, uint flags)
{
- DBUG_ENTER("bka_range_seq_init");
- JOIN_CACHE_BKA *cache= (JOIN_CACHE_BKA *) init_param;
- cache->reset(0);
- DBUG_RETURN((range_seq_t) init_param);
+DBUG_ENTER("bka_range_seq_init");
+JOIN_CACHE_BKA *cache= (JOIN_CACHE_BKA *) init_param;
+cache->reset(0);
+DBUG_RETURN((range_seq_t) init_param);
}
/*
- Get the next range/key over records from the join buffer used by a BKA cache
-
- SYNOPSIS
- bka_range_seq_next()
- seq the value returned by bka_range_seq_init
- range OUT reference to the next range
+Get the next range/key over records from the join buffer used by a BKA cache
- DESCRIPTION
- The function interprets seq as a pointer to a JOIN_CACHE_BKA
- object. The function returns a pointer to the range descriptor
- for the key built over the next record from the join buffer.
-
- NOTE
- This function are used only as a callback function.
-
- RETURN VALUE
- FALSE ok, the range structure filled with info about the next range/key
- TRUE no more ranges
+SYNOPSIS
+ bka_range_seq_next()
+ seq the value returned by bka_range_seq_init
+ range OUT reference to the next range
+
+DESCRIPTION
+ The function interprets seq as a pointer to a JOIN_CACHE_BKA
+ object. The function returns a pointer to the range descriptor
+ for the key built over the next record from the join buffer.
+
+NOTE
+ This function are used only as a callback function.
+
+RETURN VALUE
+ FALSE ok, the range structure filled with info about the next range/key
+ TRUE no more ranges
*/
static
bool bka_range_seq_next(range_seq_t rseq, KEY_MULTI_RANGE *range)
{
- DBUG_ENTER("bka_range_seq_next");
- JOIN_CACHE_BKA *cache= (JOIN_CACHE_BKA *) rseq;
- TABLE_REF *ref= &cache->join_tab->ref;
- key_range *start_key= &range->start_key;
- if ((start_key->length= cache->get_next_key((uchar **) &start_key->key)))
- {
- start_key->keypart_map= (1 << ref->key_parts) - 1;
- 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_curr_rec();
- range->range_flag= EQ_RANGE;
- DBUG_RETURN(0);
- }
- DBUG_RETURN(1);
+DBUG_ENTER("bka_range_seq_next");
+JOIN_CACHE_BKA *cache= (JOIN_CACHE_BKA *) rseq;
+TABLE_REF *ref= &cache->join_tab->ref;
+key_range *start_key= &range->start_key;
+if ((start_key->length= cache->get_next_key((uchar **) &start_key->key)))
+{
+ start_key->keypart_map= (1 << ref->key_parts) - 1;
+ 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_curr_rec();
+ range->range_flag= EQ_RANGE;
+ DBUG_RETURN(0);
+}
+DBUG_RETURN(1);
}
/*
- Check whether range_info orders to skip the next record from BKA buffer
-
- SYNOPSIS
- bka_range_seq_skip_record()
- seq value returned by bka_range_seq_init()
- range_info information about the next range
- rowid [NOT USED] rowid of the record to be checked
+Check whether range_info orders to skip the next record from BKA buffer
-
- DESCRIPTION
- The function interprets seq as a pointer to a JOIN_CACHE_BKA object.
- The function returns TRUE if the record with this range_info
- is to be filtered out from the stream of records returned by
- multi_range_read_next().
-
- NOTE
- This function are used only as a callback function.
+SYNOPSIS
+ bka_range_seq_skip_record()
+ seq value returned by bka_range_seq_init()
+ range_info information about the next range
+ rowid [NOT USED] rowid of the record to be checked
- RETURN VALUE
- 1 record with this range_info is to be filtered out from the stream
- of records returned by multi_range_read_next()
- 0 the record is to be left in the stream
+
+DESCRIPTION
+ The function interprets seq as a pointer to a JOIN_CACHE_BKA object.
+ The function returns TRUE if the record with this range_info
+ is to be filtered out from the stream of records returned by
+ multi_range_read_next().
+
+NOTE
+ This function are used only as a callback function.
+
+RETURN VALUE
+ 1 record with this range_info is to be filtered out from the stream
+ of records returned by multi_range_read_next()
+ 0 the record is to be left in the stream
*/
static
bool bka_range_seq_skip_record(range_seq_t rseq, range_id_t range_info, uchar *rowid)
{
- DBUG_ENTER("bka_range_seq_skip_record");
- JOIN_CACHE_BKA *cache= (JOIN_CACHE_BKA *) rseq;
- bool res= cache->get_match_flag_by_pos((uchar *) range_info) ==
- JOIN_CACHE::MATCH_FOUND;
- DBUG_RETURN(res);
+DBUG_ENTER("bka_range_seq_skip_record");
+JOIN_CACHE_BKA *cache= (JOIN_CACHE_BKA *) rseq;
+bool res= cache->get_match_flag_by_pos((uchar *) range_info) ==
+ JOIN_CACHE::MATCH_FOUND;
+DBUG_RETURN(res);
}
/*
- Check if the record combination from BKA cache matches the index condition
+Check if the record combination from BKA cache matches the index condition
- SYNOPSIS
- bka_skip_index_tuple()
- rseq value returned by bka_range_seq_init()
- range_info record chain for the next range/key returned by MRR
-
- DESCRIPTION
- This is wrapper for JOIN_CACHE_BKA::skip_index_tuple method,
- see comments there.
+SYNOPSIS
+ bka_skip_index_tuple()
+ rseq value returned by bka_range_seq_init()
+ range_info record chain for the next range/key returned by MRR
+
+DESCRIPTION
+ This is wrapper for JOIN_CACHE_BKA::skip_index_tuple method,
+ see comments there.
- NOTE
- This function is used as a RANGE_SEQ_IF::skip_index_tuple callback.
-
- RETURN VALUE
- 0 The record combination satisfies the index condition
- 1 Otherwise
+NOTE
+ This function is used as a RANGE_SEQ_IF::skip_index_tuple callback.
+
+RETURN VALUE
+ 0 The record combination satisfies the index condition
+ 1 Otherwise
*/
static
bool bka_skip_index_tuple(range_seq_t rseq, range_id_t range_info)
{
- DBUG_ENTER("bka_skip_index_tuple");
- JOIN_CACHE_BKA *cache= (JOIN_CACHE_BKA *) rseq;
- THD *thd= cache->thd();
- bool res;
- status_var_increment(thd->status_var.ha_icp_attempts);
- if (!(res= cache->skip_index_tuple(range_info)))
- status_var_increment(thd->status_var.ha_icp_match);
- DBUG_RETURN(res);
+DBUG_ENTER("bka_skip_index_tuple");
+JOIN_CACHE_BKA *cache= (JOIN_CACHE_BKA *) rseq;
+THD *thd= cache->thd();
+bool res;
+status_var_increment(thd->status_var.ha_icp_attempts);
+if (!(res= cache->skip_index_tuple(range_info)))
+ status_var_increment(thd->status_var.ha_icp_match);
+DBUG_RETURN(res);
}
/*
- Prepare to read the record from BKA cache matching the current joined record
-
- SYNOPSIS
- prepare_look_for_matches()
- skip_last <-> ignore the last record in the buffer (always unused here)
-
- DESCRIPTION
- The function prepares to iterate over records in the join cache buffer
- matching the record loaded into the record buffer for join_tab when
- performing join operation by BKA join algorithm. With BKA algorithms the
- record loaded into the record buffer for join_tab always has a direct
- reference to the matching records from the join buffer. When the regular
- BKA join algorithm is employed the record from join_tab can refer to
- only one such record.
- The function sets the counter of the remaining records from the cache
- buffer that would match the current join_tab record to 1.
-
- RETURN VALUE
- TRUE there are no records in the buffer to iterate over
- FALSE otherwise
+Prepare to read the record from BKA cache matching the current joined record
+
+SYNOPSIS
+ prepare_look_for_matches()
+ skip_last <-> ignore the last record in the buffer (always unused here)
+
+DESCRIPTION
+ The function prepares to iterate over records in the join cache buffer
+ matching the record loaded into the record buffer for join_tab when
+ performing join operation by BKA join algorithm. With BKA algorithms the
+ record loaded into the record buffer for join_tab always has a direct
+ reference to the matching records from the join buffer. When the regular
+ BKA join algorithm is employed the record from join_tab can refer to
+ only one such record.
+ The function sets the counter of the remaining records from the cache
+ buffer that would match the current join_tab record to 1.
+
+RETURN VALUE
+ TRUE there are no records in the buffer to iterate over
+ FALSE otherwise
*/
-
+
bool JOIN_CACHE_BKA::prepare_look_for_matches(bool skip_last)
{
- if (!records)
- return TRUE;
- rem_records= 1;
- return FALSE;
+if (!records)
+ return TRUE;
+rem_records= 1;
+return FALSE;
}
/*
- Get the record from the BKA cache matching the current joined record
-
- SYNOPSIS
- get_next_candidate_for_match
-
- DESCRIPTION
- This method is used for iterations over the records from the join
- cache buffer when looking for matches for records from join_tab.
- The method performs the necessary preparations to read the next record
- from the join buffer into the record buffer by the method
- read_next_candidate_for_match, or, to skip the next record from the join
- buffer by the method skip_if_not_needed_match.
- This implementation of the virtual method get_next_candidate_for_match
- just decrements the counter of the records that are to be iterated over
- and returns the value of curr_association as a reference to the position
- of the beginning of the record fields in the buffer.
-
- RETURN VALUE
- pointer to the start of the record fields in the join buffer
- if the there is another record to iterate over, 0 - otherwise.
+Get the record from the BKA cache matching the current joined record
+
+SYNOPSIS
+ get_next_candidate_for_match
+
+DESCRIPTION
+ This method is used for iterations over the records from the join
+ cache buffer when looking for matches for records from join_tab.
+ The method performs the necessary preparations to read the next record
+ from the join buffer into the record buffer by the method
+ read_next_candidate_for_match, or, to skip the next record from the join
+ buffer by the method skip_if_not_needed_match.
+ This implementation of the virtual method get_next_candidate_for_match
+ just decrements the counter of the records that are to be iterated over
+ and returns the value of curr_association as a reference to the position
+ of the beginning of the record fields in the buffer.
+
+RETURN VALUE
+ pointer to the start of the record fields in the join buffer
+ if the there is another record to iterate over, 0 - otherwise.
*/
uchar *JOIN_CACHE_BKA::get_next_candidate_for_match()
{
- if (!rem_records)
- return 0;
- rem_records--;
- return curr_association;
+if (!rem_records)
+ return 0;
+rem_records--;
+return curr_association;
}
/*
- Check whether the matching record from the BKA cache is to be skipped
-
- SYNOPSIS
- skip_next_candidate_for_match
- rec_ptr pointer to the position in the join buffer right after
- the previous record
-
- DESCRIPTION
- This implementation of the virtual function just calls the
- method get_match_flag_by_pos to check whether the record referenced
- by ref_ptr has its match flag set to MATCH_FOUND.
-
- RETURN VALUE
- TRUE the record referenced by rec_ptr has its match flag set to
- MATCH_FOUND
- FALSE otherwise
+Check whether the matching record from the BKA cache is to be skipped
+
+SYNOPSIS
+ skip_next_candidate_for_match
+ rec_ptr pointer to the position in the join buffer right after
+ the previous record
+
+DESCRIPTION
+ This implementation of the virtual function just calls the
+ method get_match_flag_by_pos to check whether the record referenced
+ by ref_ptr has its match flag set to MATCH_FOUND.
+
+RETURN VALUE
+ TRUE the record referenced by rec_ptr has its match flag set to
+ MATCH_FOUND
+ FALSE otherwise
*/
bool JOIN_CACHE_BKA::skip_next_candidate_for_match(uchar *rec_ptr)
{
- return join_tab->check_only_first_match() &&
- (get_match_flag_by_pos(rec_ptr) == MATCH_FOUND);
+return join_tab->check_only_first_match() &&
+ (get_match_flag_by_pos(rec_ptr) == MATCH_FOUND);
}
/*
- Read the next record from the BKA join cache buffer when looking for matches
-
- SYNOPSIS
- read_next_candidate_for_match
- rec_ptr pointer to the position in the join buffer right after
- the previous record
-
- DESCRIPTION
- This implementation of the virtual method read_next_candidate_for_match
- calls the method get_record_by_pos to read the record referenced by rec_ptr
- from the join buffer into the record buffer. If this record refers to
- fields in the other join buffers the call of get_record_by_po ensures that
- these fields are read into the corresponding record buffers as well.
- This function is supposed to be called after a successful call of
- the method get_next_candidate_for_match.
-
- RETURN VALUE
- none
+Read the next record from the BKA join cache buffer when looking for matches
+
+SYNOPSIS
+ read_next_candidate_for_match
+ rec_ptr pointer to the position in the join buffer right after
+ the previous record
+
+DESCRIPTION
+ This implementation of the virtual method read_next_candidate_for_match
+ calls the method get_record_by_pos to read the record referenced by rec_ptr
+ from the join buffer into the record buffer. If this record refers to
+ fields in the other join buffers the call of get_record_by_po ensures that
+ these fields are read into the corresponding record buffers as well.
+ This function is supposed to be called after a successful call of
+ the method get_next_candidate_for_match.
+
+RETURN VALUE
+ none
*/
void JOIN_CACHE_BKA::read_next_candidate_for_match(uchar *rec_ptr)
{
- get_record_by_pos(rec_ptr);
+get_record_by_pos(rec_ptr);
}
/*
- Initialize the BKA join cache
+Initialize the BKA join cache
- SYNOPSIS
- init
+SYNOPSIS
+ init
- DESCRIPTION
- The function initializes the cache structure. It is supposed to be called
- right after a constructor for the JOIN_CACHE_BKA.
+DESCRIPTION
+ The function initializes the cache structure. It is supposed to be called
+ right after a constructor for the JOIN_CACHE_BKA.
- NOTES
- The function first constructs a companion object of the type
- JOIN_TAB_SCAN_MRR, then it calls the init method of the parent class.
-
- RETURN VALUE
- 0 initialization with buffer allocations has been succeeded
- 1 otherwise
+NOTES
+ The function first constructs a companion object of the type
+ JOIN_TAB_SCAN_MRR, then it calls the init method of the parent class.
+
+RETURN VALUE
+ 0 initialization with buffer allocations has been succeeded
+ 1 otherwise
*/
int JOIN_CACHE_BKA::init()
{
- int res;
- bool check_only_first_match= join_tab->check_only_first_match();
+int res;
+bool check_only_first_match= join_tab->check_only_first_match();
- RANGE_SEQ_IF rs_funcs= { bka_range_seq_key_info,
- bka_range_seq_init,
- bka_range_seq_next,
- check_only_first_match ?
- bka_range_seq_skip_record : 0,
- bka_skip_index_tuple };
+RANGE_SEQ_IF rs_funcs= { bka_range_seq_key_info,
+ bka_range_seq_init,
+ bka_range_seq_next,
+ check_only_first_match ?
+ bka_range_seq_skip_record : 0,
+ bka_skip_index_tuple };
- DBUG_ENTER("JOIN_CACHE_BKA::init");
+DBUG_ENTER("JOIN_CACHE_BKA::init");
- JOIN_TAB_SCAN_MRR *jsm;
- if (!(join_tab_scan= jsm= new JOIN_TAB_SCAN_MRR(join, join_tab,
- mrr_mode, rs_funcs)))
- DBUG_RETURN(1);
+JOIN_TAB_SCAN_MRR *jsm;
+if (!(join_tab_scan= jsm= new JOIN_TAB_SCAN_MRR(join, join_tab,
+ mrr_mode, rs_funcs)))
+ DBUG_RETURN(1);
- if ((res= JOIN_CACHE::init()))
- DBUG_RETURN(res);
+if ((res= JOIN_CACHE::init()))
+ DBUG_RETURN(res);
- if (use_emb_key)
- jsm->mrr_mode |= HA_MRR_MATERIALIZED_KEYS;
+if (use_emb_key)
+ jsm->mrr_mode |= HA_MRR_MATERIALIZED_KEYS;
- DBUG_RETURN(0);
+DBUG_RETURN(0);
}
/*
- Get the key built over the next record from BKA join buffer
-
- SYNOPSIS
- get_next_key()
- key pointer to the buffer where the key value is to be placed
-
- DESCRIPTION
- The function reads key fields from the current record in the join buffer.
- and builds the key value out of these fields that will be used to access
- the 'join_tab' table. Some of key fields may belong to previous caches.
- They are accessed via record references to the record parts stored in the
- previous join buffers. The other key fields always are placed right after
- the flag fields of the record.
- If the key is embedded, which means that its value can be read directly
- from the join buffer, then *key is set to the beginning of the key in
- this buffer. Otherwise the key is built in the join_tab->ref->key_buff.
- The function returns the length of the key if it succeeds ro read it.
- If is assumed that the functions starts reading at the position of
- the record length which is provided for each records in a BKA cache.
- After the key is built the 'pos' value points to the first position after
- the current record.
- The function just skips the records with MATCH_IMPOSSIBLE in the
- match flag field if there is any.
- The function returns 0 if the initial position is after the beginning
- of the record fields for last record from the join buffer.
-
- RETURN VALUE
- length of the key value - if the starting value of 'pos' points to
- the position before the fields for the last record,
- 0 - otherwise.
+Get the key built over the next record from BKA join buffer
+
+SYNOPSIS
+ get_next_key()
+ key pointer to the buffer where the key value is to be placed
+
+DESCRIPTION
+ The function reads key fields from the current record in the join buffer.
+ and builds the key value out of these fields that will be used to access
+ the 'join_tab' table. Some of key fields may belong to previous caches.
+ They are accessed via record references to the record parts stored in the
+ previous join buffers. The other key fields always are placed right after
+ the flag fields of the record.
+ If the key is embedded, which means that its value can be read directly
+ from the join buffer, then *key is set to the beginning of the key in
+ this buffer. Otherwise the key is built in the join_tab->ref->key_buff.
+ The function returns the length of the key if it succeeds ro read it.
+ If is assumed that the functions starts reading at the position of
+ the record length which is provided for each records in a BKA cache.
+ After the key is built the 'pos' value points to the first position after
+ the current record.
+ The function just skips the records with MATCH_IMPOSSIBLE in the
+ match flag field if there is any.
+ The function returns 0 if the initial position is after the beginning
+ of the record fields for last record from the join buffer.
+
+RETURN VALUE
+ length of the key value - if the starting value of 'pos' points to
+ the position before the fields for the last record,
+ 0 - otherwise.
*/
uint JOIN_CACHE_BKA::get_next_key(uchar ** key)
{
- uint len;
- uint32 rec_len;
- uchar *init_pos;
- JOIN_CACHE *cache;
-
+uint len;
+uint32 rec_len;
+uchar *init_pos;
+JOIN_CACHE *cache;
+
start:
- /* Any record in a BKA cache is prepended with its length */
- DBUG_ASSERT(with_length);
-
- if ((pos+size_of_rec_len) > last_rec_pos || !records)
- return 0;
+/* Any record in a BKA cache is prepended with its length */
+DBUG_ASSERT(with_length);
+
+if ((pos+size_of_rec_len) > last_rec_pos || !records)
+ return 0;
- /* Read the length of the record */
- rec_len= get_rec_length(pos);
- pos+= size_of_rec_len;
- init_pos= pos;
+/* Read the length of the record */
+rec_len= get_rec_length(pos);
+pos+= size_of_rec_len;
+init_pos= pos;
- /* Read a reference to the previous cache if any */
- if (prev_cache)
- pos+= prev_cache->get_size_of_rec_offset();
+/* Read a reference to the previous cache if any */
+if (prev_cache)
+ pos+= prev_cache->get_size_of_rec_offset();
- curr_rec_pos= pos;
+curr_rec_pos= pos;
- /* Read all flag fields of the record */
- read_flag_fields();
+/* Read all flag fields of the record */
+read_flag_fields();
- if (with_match_flag &&
- (Match_flag) curr_rec_pos[0] == MATCH_IMPOSSIBLE )
- {
- pos= init_pos+rec_len;
- goto start;
- }
-
- if (use_emb_key)
- {
- /* An embedded key is taken directly from the join buffer */
- *key= pos;
- len= emb_key_length;
- }
- else
+if (with_match_flag &&
+ (Match_flag) curr_rec_pos[0] == MATCH_IMPOSSIBLE )
+{
+ pos= init_pos+rec_len;
+ goto start;
+}
+
+if (use_emb_key)
+{
+ /* An embedded key is taken directly from the join buffer */
+ *key= pos;
+ len= emb_key_length;
+}
+else
+{
+ /* Read key arguments from previous caches if there are any such fields */
+ if (external_key_arg_fields)
{
- /* Read key arguments from previous caches if there are any such fields */
- if (external_key_arg_fields)
- {
- uchar *rec_ptr= curr_rec_pos;
- uint key_arg_count= external_key_arg_fields;
- CACHE_FIELD **copy_ptr= blob_ptr-key_arg_count;
- for (cache= prev_cache; key_arg_count; cache= cache->prev_cache)
- {
- uint len= 0;
+ uchar *rec_ptr= curr_rec_pos;
+ uint key_arg_count= external_key_arg_fields;
+ CACHE_FIELD **copy_ptr= blob_ptr-key_arg_count;
+ for (cache= prev_cache; key_arg_count; cache= cache->prev_cache)
+ {
+ uint len= 0;
+ DBUG_ASSERT(cache);
+ rec_ptr= cache->get_rec_ref(rec_ptr);
+ while (!cache->referenced_fields)
+ {
+ cache= cache->prev_cache;
DBUG_ASSERT(cache);
rec_ptr= cache->get_rec_ref(rec_ptr);
- while (!cache->referenced_fields)
- {
- cache= cache->prev_cache;
- DBUG_ASSERT(cache);
- rec_ptr= cache->get_rec_ref(rec_ptr);
- }
- while (key_arg_count &&
- cache->read_referenced_field(*copy_ptr, rec_ptr, &len))
- {
- copy_ptr++;
- --key_arg_count;
- }
+ }
+ while (key_arg_count &&
+ cache->read_referenced_field(*copy_ptr, rec_ptr, &len))
+ {
+ copy_ptr++;
+ --key_arg_count;
}
}
-
- /*
- Read the other key arguments from the current record. The fields for
- these arguments are always first in the sequence of the record's fields.
- */
- CACHE_FIELD *copy= field_descr+flag_fields;
- CACHE_FIELD *copy_end= copy+local_key_arg_fields;
- bool blob_in_rec_buff= blob_data_is_in_rec_buff(curr_rec_pos);
- for ( ; copy < copy_end; copy++)
- read_record_field(copy, blob_in_rec_buff);
-
- /* Build the key over the fields read into the record buffers */
- TABLE_REF *ref= &join_tab->ref;
- cp_buffer_from_ref(join->thd, join_tab->table, ref);
- *key= ref->key_buff;
- len= ref->key_length;
}
+
+ /*
+ Read the other key arguments from the current record. The fields for
+ these arguments are always first in the sequence of the record's fields.
+ */
+ CACHE_FIELD *copy= field_descr+flag_fields;
+ CACHE_FIELD *copy_end= copy+local_key_arg_fields;
+ bool blob_in_rec_buff= blob_data_is_in_rec_buff(curr_rec_pos);
+ for ( ; copy < copy_end; copy++)
+ read_record_field(copy, blob_in_rec_buff);
+
+ /* Build the key over the fields read into the record buffers */
+ TABLE_REF *ref= &join_tab->ref;
+ cp_buffer_from_ref(join->thd, join_tab->table, ref);
+ *key= ref->key_buff;
+ len= ref->key_length;
+}
- pos= init_pos+rec_len;
+pos= init_pos+rec_len;
- return len;
+return len;
}
/*
- Check the index condition of the joined table for a record from the BKA cache
-
- SYNOPSIS
- skip_index_tuple()
- range_info pointer to the record returned by MRR
-
- DESCRIPTION
- This function is invoked from MRR implementation to check if an index
- tuple matches the index condition. It is used in the case where the index
- condition actually depends on both columns of the used index and columns
- from previous tables.
-
- NOTES
- Accessing columns of the previous tables requires special handling with
- BKA. The idea of BKA is to collect record combinations in a buffer and
- then do a batch of ref access lookups, i.e. by the time we're doing a
- lookup its previous-records-combination is not in prev_table->record[0]
- but somewhere in the join buffer.
- We need to get it from there back into prev_table(s)->record[0] before we
- can evaluate the index condition, and that's why we need this function
- instead of regular IndexConditionPushdown.
-
- NOTES
- Possible optimization:
- Before we unpack the record from a previous table
- check if this table is used in the condition.
- If so then unpack the record otherwise skip the unpacking.
- This should be done by a special virtual method
- get_partial_record_by_pos().
+Check the index condition of the joined table for a record from the BKA cache
- RETURN VALUE
- 1 the record combination does not satisfies the index condition
- 0 otherwise
+SYNOPSIS
+ skip_index_tuple()
+ range_info pointer to the record returned by MRR
+
+DESCRIPTION
+ This function is invoked from MRR implementation to check if an index
+ tuple matches the index condition. It is used in the case where the index
+ condition actually depends on both columns of the used index and columns
+ from previous tables.
+
+NOTES
+ Accessing columns of the previous tables requires special handling with
+ BKA. The idea of BKA is to collect record combinations in a buffer and
+ then do a batch of ref access lookups, i.e. by the time we're doing a
+ lookup its previous-records-combination is not in prev_table->record[0]
+ but somewhere in the join buffer.
+ We need to get it from there back into prev_table(s)->record[0] before we
+ can evaluate the index condition, and that's why we need this function
+ instead of regular IndexConditionPushdown.
+
+NOTES
+ Possible optimization:
+ Before we unpack the record from a previous table
+ check if this table is used in the condition.
+ If so then unpack the record otherwise skip the unpacking.
+ This should be done by a special virtual method
+ get_partial_record_by_pos().
+
+RETURN VALUE
+ 1 the record combination does not satisfies the index condition
+ 0 otherwise
*/
bool JOIN_CACHE_BKA::skip_index_tuple(range_id_t range_info)
{
- DBUG_ENTER("JOIN_CACHE_BKA::skip_index_tuple");
- get_record_by_pos((uchar*)range_info);
- DBUG_RETURN(!join_tab->cache_idx_cond->val_int());
+DBUG_ENTER("JOIN_CACHE_BKA::skip_index_tuple");
+get_record_by_pos((uchar*)range_info);
+DBUG_RETURN(!join_tab->cache_idx_cond->val_int());
}
/*
- Initialize retrieval of range sequence for the BKAH join algorithm
-
- SYNOPSIS
- bkah_range_seq_init()
- init_params pointer to the BKAH join cache object
- n_ranges the number of ranges obtained
- flags combination of MRR flags
-
- DESCRIPTION
- The function interprets init_param as a pointer to a JOIN_CACHE_BKAH
- object. The function prepares for an iteration over distinct join keys
- built over the records from the cache join buffer.
-
- NOTE
- This function are used only as a callback function.
-
- RETURN VALUE
- init_param value that is to be used as a parameter of
- bkah_range_seq_next()
+Initialize retrieval of range sequence for the BKAH join algorithm
+
+SYNOPSIS
+ bkah_range_seq_init()
+ init_params pointer to the BKAH join cache object
+ n_ranges the number of ranges obtained
+ flags combination of MRR flags
+
+DESCRIPTION
+ The function interprets init_param as a pointer to a JOIN_CACHE_BKAH
+ object. The function prepares for an iteration over distinct join keys
+ built over the records from the cache join buffer.
+
+NOTE
+ This function are used only as a callback function.
+
+RETURN VALUE
+ init_param value that is to be used as a parameter of
+ bkah_range_seq_next()
*/
static
range_seq_t bkah_range_seq_init(void *init_param, uint n_ranges, uint flags)
{
- DBUG_ENTER("bkah_range_seq_init");
- JOIN_CACHE_BKAH *cache= (JOIN_CACHE_BKAH *) init_param;
- cache->reset(0);
- DBUG_RETURN((range_seq_t) init_param);
+DBUG_ENTER("bkah_range_seq_init");
+JOIN_CACHE_BKAH *cache= (JOIN_CACHE_BKAH *) init_param;
+cache->reset(0);
+DBUG_RETURN((range_seq_t) init_param);
}
/*
- Get the next range/key over records from the join buffer of a BKAH cache
-
- SYNOPSIS
- bkah_range_seq_next()
- seq value returned by bkah_range_seq_init()
- range OUT reference to the next range
+Get the next range/key over records from the join buffer of a BKAH cache
- DESCRIPTION
- The function interprets seq as a pointer to a JOIN_CACHE_BKAH
- object. The function returns a pointer to the range descriptor
- for the next unique key built over records from the join buffer.
-
- NOTE
- This function are used only as a callback function.
-
- RETURN VALUE
- FALSE ok, the range structure filled with info about the next range/key
- TRUE no more ranges
+SYNOPSIS
+ bkah_range_seq_next()
+ seq value returned by bkah_range_seq_init()
+ range OUT reference to the next range
+
+DESCRIPTION
+ The function interprets seq as a pointer to a JOIN_CACHE_BKAH
+ object. The function returns a pointer to the range descriptor
+ for the next unique key built over records from the join buffer.
+
+NOTE
+ This function are used only as a callback function.
+
+RETURN VALUE
+ FALSE ok, the range structure filled with info about the next range/key
+ TRUE no more ranges
*/
static
bool bkah_range_seq_next(range_seq_t rseq, KEY_MULTI_RANGE *range)
{
- DBUG_ENTER("bkah_range_seq_next");
- JOIN_CACHE_BKAH *cache= (JOIN_CACHE_BKAH *) rseq;
- TABLE_REF *ref= &cache->join_tab->ref;
- key_range *start_key= &range->start_key;
- if ((start_key->length= cache->get_next_key((uchar **) &start_key->key)))
- {
- start_key->keypart_map= (1 << ref->key_parts) - 1;
- 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_curr_key_chain();
- range->range_flag= EQ_RANGE;
- DBUG_RETURN(0);
- }
- DBUG_RETURN(1);
+DBUG_ENTER("bkah_range_seq_next");
+JOIN_CACHE_BKAH *cache= (JOIN_CACHE_BKAH *) rseq;
+TABLE_REF *ref= &cache->join_tab->ref;
+key_range *start_key= &range->start_key;
+if ((start_key->length= cache->get_next_key((uchar **) &start_key->key)))
+{
+ start_key->keypart_map= (1 << ref->key_parts) - 1;
+ 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_curr_key_chain();
+ range->range_flag= EQ_RANGE;
+ DBUG_RETURN(0);
+}
+DBUG_RETURN(1);
}
/*
- Check whether range_info orders to skip the next record from BKAH join buffer
+Check whether range_info orders to skip the next record from BKAH join buffer
- SYNOPSIS
- bkah_range_seq_skip_record()
- seq value returned by bkah_range_seq_init()
- range_info information about the next range/key returned by MRR
- rowid [NOT USED] rowid of the record to be checked (not used)
-
- DESCRIPTION
- The function interprets seq as a pointer to a JOIN_CACHE_BKAH
- object. The function returns TRUE if the record with this range_info
- is to be filtered out from the stream of records returned by
- multi_range_read_next().
-
- NOTE
- This function are used only as a callback function.
-
- RETURN VALUE
- 1 record with this range_info is to be filtered out from the stream
- of records returned by multi_range_read_next()
- 0 the record is to be left in the stream
+SYNOPSIS
+ bkah_range_seq_skip_record()
+ seq value returned by bkah_range_seq_init()
+ range_info information about the next range/key returned by MRR
+ rowid [NOT USED] rowid of the record to be checked (not used)
+
+DESCRIPTION
+ The function interprets seq as a pointer to a JOIN_CACHE_BKAH
+ object. The function returns TRUE if the record with this range_info
+ is to be filtered out from the stream of records returned by
+ multi_range_read_next().
+
+NOTE
+ This function are used only as a callback function.
+
+RETURN VALUE
+ 1 record with this range_info is to be filtered out from the stream
+ of records returned by multi_range_read_next()
+ 0 the record is to be left in the stream
*/
static
bool bkah_range_seq_skip_record(range_seq_t rseq, range_id_t range_info,
- uchar *rowid)
+ uchar *rowid)
{
- DBUG_ENTER("bkah_range_seq_skip_record");
- JOIN_CACHE_BKAH *cache= (JOIN_CACHE_BKAH *) rseq;
- bool res= cache->check_all_match_flags_for_key((uchar *) range_info);
- DBUG_RETURN(res);
+DBUG_ENTER("bkah_range_seq_skip_record");
+JOIN_CACHE_BKAH *cache= (JOIN_CACHE_BKAH *) rseq;
+bool res= cache->check_all_match_flags_for_key((uchar *) range_info);
+DBUG_RETURN(res);
}
-
+
/*
- Check if the record combination from BKAH cache matches the index condition
+Check if the record combination from BKAH cache matches the index condition
- SYNOPSIS
- bkah_skip_index_tuple()
- rseq value returned by bka_range_seq_init()
- range_info record chain for the next range/key returned by MRR
-
- DESCRIPTION
- This is wrapper for JOIN_CACHE_BKA_UNIQUE::skip_index_tuple method,
- see comments there.
+SYNOPSIS
+ bkah_skip_index_tuple()
+ rseq value returned by bka_range_seq_init()
+ range_info record chain for the next range/key returned by MRR
+
+DESCRIPTION
+ This is wrapper for JOIN_CACHE_BKA_UNIQUE::skip_index_tuple method,
+ see comments there.
- NOTE
- This function is used as a RANGE_SEQ_IF::skip_index_tuple callback.
-
- RETURN VALUE
- 0 some records from the chain satisfy the index condition
- 1 otherwise
+NOTE
+ This function is used as a RANGE_SEQ_IF::skip_index_tuple callback.
+
+RETURN VALUE
+ 0 some records from the chain satisfy the index condition
+ 1 otherwise
*/
static
bool bkah_skip_index_tuple(range_seq_t rseq, range_id_t range_info)
{
- DBUG_ENTER("bka_unique_skip_index_tuple");
- JOIN_CACHE_BKAH *cache= (JOIN_CACHE_BKAH *) rseq;
- THD *thd= cache->thd();
- bool res;
- status_var_increment(thd->status_var.ha_icp_attempts);
- if (!(res= cache->skip_index_tuple(range_info)))
- status_var_increment(thd->status_var.ha_icp_match);
- DBUG_RETURN(res);
+DBUG_ENTER("bka_unique_skip_index_tuple");
+JOIN_CACHE_BKAH *cache= (JOIN_CACHE_BKAH *) rseq;
+THD *thd= cache->thd();
+bool res;
+status_var_increment(thd->status_var.ha_icp_attempts);
+if (!(res= cache->skip_index_tuple(range_info)))
+ status_var_increment(thd->status_var.ha_icp_match);
+DBUG_RETURN(res);
}
/*
- Prepare to read record from BKAH cache matching the current joined record
-
- SYNOPSIS
- prepare_look_for_matches()
- skip_last <-> ignore the last record in the buffer (always unused here)
-
- DESCRIPTION
- The function prepares to iterate over records in the join cache buffer
- matching the record loaded into the record buffer for join_tab when
- performing join operation by BKAH join algorithm. With BKAH algorithm, if
- association labels are used, then record loaded into the record buffer
- for join_tab always has a direct reference to the chain of the mathing
- records from the join buffer. If association labels are not used then
- then the chain of the matching records is obtained by the call of the
- get_key_chain_by_join_key function.
-
- RETURN VALUE
- TRUE there are no records in the buffer to iterate over
- FALSE otherwise
+Prepare to read record from BKAH cache matching the current joined record
+
+SYNOPSIS
+ prepare_look_for_matches()
+ skip_last <-> ignore the last record in the buffer (always unused here)
+
+DESCRIPTION
+ The function prepares to iterate over records in the join cache buffer
+ matching the record loaded into the record buffer for join_tab when
+ performing join operation by BKAH join algorithm. With BKAH algorithm, if
+ association labels are used, then record loaded into the record buffer
+ for join_tab always has a direct reference to the chain of the mathing
+ records from the join buffer. If association labels are not used then
+ then the chain of the matching records is obtained by the call of the
+ get_key_chain_by_join_key function.
+
+RETURN VALUE
+ TRUE there are no records in the buffer to iterate over
+ FALSE otherwise
*/
-
+
bool JOIN_CACHE_BKAH::prepare_look_for_matches(bool skip_last)
{
- last_matching_rec_ref_ptr= next_matching_rec_ref_ptr= 0;
- if (no_association &&
- !(curr_matching_chain= get_matching_chain_by_join_key()))
+last_matching_rec_ref_ptr= next_matching_rec_ref_ptr= 0;
+if (no_association &&
+ !(curr_matching_chain= get_matching_chain_by_join_key())) //psergey: added '!'
return 1;
last_matching_rec_ref_ptr= get_next_rec_ref(curr_matching_chain);
return 0;