Commit b8b3716a authored by Michael Widenius's avatar Michael Widenius

Patch from Sergey Petrunya:

Fix post-merge failure in 5.1-merge 
- Let QUICK_RANGE_INTERSECT_SELECT not make assumption that HA_EXTRA_KEYREAD 
  scans do not touch parts of table->record[0] that refer to fields that are 
  not covered by the used index.
  This assumption is not true for XtraDB (e.g. grep row/row0sel.c for 
  "init null bytes with default values as they might be").
parent 171260f3
...@@ -1407,15 +1407,17 @@ failure: ...@@ -1407,15 +1407,17 @@ failure:
*/ */
int QUICK_ROR_INTERSECT_SELECT::init_ror_merged_scan(bool reuse_handler) int QUICK_ROR_INTERSECT_SELECT::init_ror_merged_scan(bool reuse_handler)
{ {
List_iterator_fast<QUICK_RANGE_SELECT> quick_it(quick_selects); List_iterator_fast<QUICK_SELECT_WITH_RECORD> quick_it(quick_selects);
QUICK_RANGE_SELECT* quick; QUICK_SELECT_WITH_RECORD *cur;
QUICK_RANGE_SELECT *quick;
DBUG_ENTER("QUICK_ROR_INTERSECT_SELECT::init_ror_merged_scan"); DBUG_ENTER("QUICK_ROR_INTERSECT_SELECT::init_ror_merged_scan");
/* Initialize all merged "children" quick selects */ /* Initialize all merged "children" quick selects */
DBUG_ASSERT(!need_to_fetch_row || reuse_handler); DBUG_ASSERT(!need_to_fetch_row || reuse_handler);
if (!need_to_fetch_row && reuse_handler) if (!need_to_fetch_row && reuse_handler)
{ {
quick= quick_it++; cur= quick_it++;
quick= cur->quick;
/* /*
There is no use of this->file. Use it for the first of merged range There is no use of this->file. Use it for the first of merged range
selects. selects.
...@@ -1424,8 +1426,9 @@ int QUICK_ROR_INTERSECT_SELECT::init_ror_merged_scan(bool reuse_handler) ...@@ -1424,8 +1426,9 @@ int QUICK_ROR_INTERSECT_SELECT::init_ror_merged_scan(bool reuse_handler)
DBUG_RETURN(1); DBUG_RETURN(1);
quick->file->extra(HA_EXTRA_KEYREAD_PRESERVE_FIELDS); quick->file->extra(HA_EXTRA_KEYREAD_PRESERVE_FIELDS);
} }
while ((quick= quick_it++)) while ((cur= quick_it++))
{ {
quick= cur->quick;
if (quick->init_ror_merged_scan(FALSE)) if (quick->init_ror_merged_scan(FALSE))
DBUG_RETURN(1); DBUG_RETURN(1);
quick->file->extra(HA_EXTRA_KEYREAD_PRESERVE_FIELDS); quick->file->extra(HA_EXTRA_KEYREAD_PRESERVE_FIELDS);
...@@ -1457,10 +1460,10 @@ int QUICK_ROR_INTERSECT_SELECT::reset() ...@@ -1457,10 +1460,10 @@ int QUICK_ROR_INTERSECT_SELECT::reset()
if (!scans_inited && init_ror_merged_scan(TRUE)) if (!scans_inited && init_ror_merged_scan(TRUE))
DBUG_RETURN(1); DBUG_RETURN(1);
scans_inited= TRUE; scans_inited= TRUE;
List_iterator_fast<QUICK_RANGE_SELECT> it(quick_selects); List_iterator_fast<QUICK_SELECT_WITH_RECORD> it(quick_selects);
QUICK_RANGE_SELECT *quick; QUICK_SELECT_WITH_RECORD *qr;
while ((quick= it++)) while ((qr= it++))
quick->reset(); qr->quick->reset();
DBUG_RETURN(0); DBUG_RETURN(0);
} }
...@@ -1470,6 +1473,7 @@ int QUICK_ROR_INTERSECT_SELECT::reset() ...@@ -1470,6 +1473,7 @@ int QUICK_ROR_INTERSECT_SELECT::reset()
SYNOPSIS SYNOPSIS
QUICK_ROR_INTERSECT_SELECT::push_quick_back() QUICK_ROR_INTERSECT_SELECT::push_quick_back()
alloc Mem root to create auxiliary structures on
quick Quick select to be added. The quick select must return quick Quick select to be added. The quick select must return
rows in rowid order. rows in rowid order.
NOTES NOTES
...@@ -1481,11 +1485,17 @@ int QUICK_ROR_INTERSECT_SELECT::reset() ...@@ -1481,11 +1485,17 @@ int QUICK_ROR_INTERSECT_SELECT::reset()
*/ */
bool bool
QUICK_ROR_INTERSECT_SELECT::push_quick_back(QUICK_RANGE_SELECT *quick) QUICK_ROR_INTERSECT_SELECT::push_quick_back(MEM_ROOT *alloc, QUICK_RANGE_SELECT *quick)
{ {
return quick_selects.push_back(quick); QUICK_SELECT_WITH_RECORD *qr;
if (!(qr= new QUICK_SELECT_WITH_RECORD) ||
!(qr->key_tuple= (uchar*)alloc_root(alloc, quick->max_used_key_length)))
return TRUE;
qr->quick= quick;
return quick_selects.push_back(qr);
} }
QUICK_ROR_INTERSECT_SELECT::~QUICK_ROR_INTERSECT_SELECT() QUICK_ROR_INTERSECT_SELECT::~QUICK_ROR_INTERSECT_SELECT()
{ {
DBUG_ENTER("QUICK_ROR_INTERSECT_SELECT::~QUICK_ROR_INTERSECT_SELECT"); DBUG_ENTER("QUICK_ROR_INTERSECT_SELECT::~QUICK_ROR_INTERSECT_SELECT");
...@@ -4948,7 +4958,7 @@ QUICK_SELECT_I *TRP_ROR_INTERSECT::make_quick(PARAM *param, ...@@ -4948,7 +4958,7 @@ QUICK_SELECT_I *TRP_ROR_INTERSECT::make_quick(PARAM *param,
{ {
if (!(quick= get_quick_select(param, (*first_scan)->idx, if (!(quick= get_quick_select(param, (*first_scan)->idx,
(*first_scan)->sel_arg, alloc)) || (*first_scan)->sel_arg, alloc)) ||
quick_intrsect->push_quick_back(quick)) quick_intrsect->push_quick_back(alloc, quick))
{ {
delete quick_intrsect; delete quick_intrsect;
DBUG_RETURN(NULL); DBUG_RETURN(NULL);
...@@ -7978,11 +7988,11 @@ bool QUICK_INDEX_MERGE_SELECT::is_keys_used(const MY_BITMAP *fields) ...@@ -7978,11 +7988,11 @@ bool QUICK_INDEX_MERGE_SELECT::is_keys_used(const MY_BITMAP *fields)
bool QUICK_ROR_INTERSECT_SELECT::is_keys_used(const MY_BITMAP *fields) bool QUICK_ROR_INTERSECT_SELECT::is_keys_used(const MY_BITMAP *fields)
{ {
QUICK_RANGE_SELECT *quick; QUICK_SELECT_WITH_RECORD *qr;
List_iterator_fast<QUICK_RANGE_SELECT> it(quick_selects); List_iterator_fast<QUICK_SELECT_WITH_RECORD> it(quick_selects);
while ((quick= it++)) while ((qr= it++))
{ {
if (is_key_used(head, quick->index, fields)) if (is_key_used(head, qr->quick->index, fields))
return 1; return 1;
} }
return 0; return 0;
...@@ -8281,7 +8291,8 @@ int QUICK_INDEX_MERGE_SELECT::get_next() ...@@ -8281,7 +8291,8 @@ int QUICK_INDEX_MERGE_SELECT::get_next()
int QUICK_ROR_INTERSECT_SELECT::get_next() int QUICK_ROR_INTERSECT_SELECT::get_next()
{ {
List_iterator_fast<QUICK_RANGE_SELECT> quick_it(quick_selects); List_iterator_fast<QUICK_SELECT_WITH_RECORD> quick_it(quick_selects);
QUICK_SELECT_WITH_RECORD *qr;
QUICK_RANGE_SELECT* quick; QUICK_RANGE_SELECT* quick;
int error, cmp; int error, cmp;
uint last_rowid_count=0; uint last_rowid_count=0;
...@@ -8290,7 +8301,8 @@ int QUICK_ROR_INTERSECT_SELECT::get_next() ...@@ -8290,7 +8301,8 @@ int QUICK_ROR_INTERSECT_SELECT::get_next()
do do
{ {
/* Get a rowid for first quick and save it as a 'candidate' */ /* Get a rowid for first quick and save it as a 'candidate' */
quick= quick_it++; qr= quick_it++;
quick= qr->quick;
error= quick->get_next(); error= quick->get_next();
if (cpk_quick) if (cpk_quick)
{ {
...@@ -8300,17 +8312,22 @@ int QUICK_ROR_INTERSECT_SELECT::get_next() ...@@ -8300,17 +8312,22 @@ int QUICK_ROR_INTERSECT_SELECT::get_next()
if (error) if (error)
DBUG_RETURN(error); DBUG_RETURN(error);
/* Save the read key tuple */
key_copy(qr->key_tuple, record, head->key_info + quick->index,
quick->max_used_key_length);
quick->file->position(quick->record); quick->file->position(quick->record);
memcpy(last_rowid, quick->file->ref, head->file->ref_length); memcpy(last_rowid, quick->file->ref, head->file->ref_length);
last_rowid_count= 1; last_rowid_count= 1;
while (last_rowid_count < quick_selects.elements) while (last_rowid_count < quick_selects.elements)
{ {
if (!(quick= quick_it++)) if (!(qr= quick_it++))
{ {
quick_it.rewind(); quick_it.rewind();
quick= quick_it++; qr= quick_it++;
} }
quick= qr->quick;
do do
{ {
...@@ -8320,6 +8337,9 @@ int QUICK_ROR_INTERSECT_SELECT::get_next() ...@@ -8320,6 +8337,9 @@ int QUICK_ROR_INTERSECT_SELECT::get_next()
cmp= head->file->cmp_ref(quick->file->ref, last_rowid); cmp= head->file->cmp_ref(quick->file->ref, last_rowid);
} while (cmp < 0); } while (cmp < 0);
key_copy(qr->key_tuple, record, head->key_info + quick->index,
quick->max_used_key_length);
/* Ok, current select 'caught up' and returned ref >= cur_ref */ /* Ok, current select 'caught up' and returned ref >= cur_ref */
if (cmp > 0) if (cmp > 0)
{ {
...@@ -8335,6 +8355,10 @@ int QUICK_ROR_INTERSECT_SELECT::get_next() ...@@ -8335,6 +8355,10 @@ int QUICK_ROR_INTERSECT_SELECT::get_next()
} }
memcpy(last_rowid, quick->file->ref, head->file->ref_length); memcpy(last_rowid, quick->file->ref, head->file->ref_length);
last_rowid_count= 1; last_rowid_count= 1;
//save the fields here
key_copy(qr->key_tuple, record, head->key_info + quick->index,
quick->max_used_key_length);
} }
else else
{ {
...@@ -8347,6 +8371,21 @@ int QUICK_ROR_INTERSECT_SELECT::get_next() ...@@ -8347,6 +8371,21 @@ int QUICK_ROR_INTERSECT_SELECT::get_next()
if (need_to_fetch_row) if (need_to_fetch_row)
error= head->file->rnd_pos(head->record[0], last_rowid); error= head->file->rnd_pos(head->record[0], last_rowid);
} while (error == HA_ERR_RECORD_DELETED); } while (error == HA_ERR_RECORD_DELETED);
if (!need_to_fetch_row)
{
/* Restore the columns we've read/saved with other quick selects */
quick_it.rewind();
while ((qr= quick_it++))
{
if (qr->quick != quick)
{
key_restore(record, qr->key_tuple, head->key_info + qr->quick->index,
qr->quick->max_used_key_length);
}
}
}
DBUG_RETURN(error); DBUG_RETURN(error);
} }
...@@ -8969,12 +9008,12 @@ void QUICK_INDEX_MERGE_SELECT::add_info_string(String *str) ...@@ -8969,12 +9008,12 @@ void QUICK_INDEX_MERGE_SELECT::add_info_string(String *str)
void QUICK_ROR_INTERSECT_SELECT::add_info_string(String *str) void QUICK_ROR_INTERSECT_SELECT::add_info_string(String *str)
{ {
bool first= TRUE; bool first= TRUE;
QUICK_RANGE_SELECT *quick; QUICK_SELECT_WITH_RECORD *qr;
List_iterator_fast<QUICK_RANGE_SELECT> it(quick_selects); List_iterator_fast<QUICK_SELECT_WITH_RECORD> it(quick_selects);
str->append(STRING_WITH_LEN("intersect(")); str->append(STRING_WITH_LEN("intersect("));
while ((quick= it++)) while ((qr= it++))
{ {
KEY *key_info= head->key_info + quick->index; KEY *key_info= head->key_info + qr->quick->index;
if (!first) if (!first)
str->append(','); str->append(',');
else else
...@@ -9060,11 +9099,11 @@ void QUICK_ROR_INTERSECT_SELECT::add_keys_and_lengths(String *key_names, ...@@ -9060,11 +9099,11 @@ void QUICK_ROR_INTERSECT_SELECT::add_keys_and_lengths(String *key_names,
char buf[64]; char buf[64];
uint length; uint length;
bool first= TRUE; bool first= TRUE;
QUICK_RANGE_SELECT *quick; QUICK_SELECT_WITH_RECORD *qr;
List_iterator_fast<QUICK_RANGE_SELECT> it(quick_selects); List_iterator_fast<QUICK_SELECT_WITH_RECORD> it(quick_selects);
while ((quick= it++)) while ((qr= it++))
{ {
KEY *key_info= head->key_info + quick->index; KEY *key_info= head->key_info + qr->quick->index;
if (first) if (first)
first= FALSE; first= FALSE;
else else
...@@ -9073,7 +9112,7 @@ void QUICK_ROR_INTERSECT_SELECT::add_keys_and_lengths(String *key_names, ...@@ -9073,7 +9112,7 @@ void QUICK_ROR_INTERSECT_SELECT::add_keys_and_lengths(String *key_names,
used_lengths->append(','); used_lengths->append(',');
} }
key_names->append(key_info->name); key_names->append(key_info->name);
length= longlong2str(quick->max_used_key_length, buf, 10) - buf; length= longlong2str(qr->quick->max_used_key_length, buf, 10) - buf;
used_lengths->append(buf, length); used_lengths->append(buf, length);
} }
...@@ -11427,13 +11466,13 @@ void QUICK_INDEX_MERGE_SELECT::dbug_dump(int indent, bool verbose) ...@@ -11427,13 +11466,13 @@ void QUICK_INDEX_MERGE_SELECT::dbug_dump(int indent, bool verbose)
void QUICK_ROR_INTERSECT_SELECT::dbug_dump(int indent, bool verbose) void QUICK_ROR_INTERSECT_SELECT::dbug_dump(int indent, bool verbose)
{ {
List_iterator_fast<QUICK_RANGE_SELECT> it(quick_selects); List_iterator_fast<QUICK_SELECT_WITH_RECORD> it(quick_selects);
QUICK_RANGE_SELECT *quick; QUICK_SELECT_WITH_RECORD *qr;
fprintf(DBUG_FILE, "%*squick ROR-intersect select, %scovering\n", fprintf(DBUG_FILE, "%*squick ROR-intersect select, %scovering\n",
indent, "", need_to_fetch_row? "":"non-"); indent, "", need_to_fetch_row? "":"non-");
fprintf(DBUG_FILE, "%*smerged scans {\n", indent, ""); fprintf(DBUG_FILE, "%*smerged scans {\n", indent, "");
while ((quick= it++)) while ((qr= it++))
quick->dbug_dump(indent+2, verbose); qr->quick->dbug_dump(indent+2, verbose);
if (cpk_quick) if (cpk_quick)
{ {
fprintf(DBUG_FILE, "%*sclustered PK quick:\n", indent, ""); fprintf(DBUG_FILE, "%*sclustered PK quick:\n", indent, "");
......
...@@ -585,13 +585,21 @@ public: ...@@ -585,13 +585,21 @@ public:
void dbug_dump(int indent, bool verbose); void dbug_dump(int indent, bool verbose);
#endif #endif
int init_ror_merged_scan(bool reuse_handler); int init_ror_merged_scan(bool reuse_handler);
bool push_quick_back(QUICK_RANGE_SELECT *quick_sel_range); bool push_quick_back(MEM_ROOT *alloc, QUICK_RANGE_SELECT *quick_sel_range);
class QUICK_SELECT_WITH_RECORD : public Sql_alloc
{
public:
QUICK_RANGE_SELECT *quick;
uchar *key_tuple;
~QUICK_SELECT_WITH_RECORD() { delete quick; }
};
/* /*
Range quick selects this intersection consists of, not including Range quick selects this intersection consists of, not including
cpk_quick. cpk_quick.
*/ */
List<QUICK_RANGE_SELECT> quick_selects; List<QUICK_SELECT_WITH_RECORD> quick_selects;
/* /*
Merged quick select that uses Clustered PK, if there is one. This quick Merged quick select that uses Clustered PK, if there is one. This quick
......
...@@ -4450,10 +4450,10 @@ xtPublic int xt_tab_maybe_committed(XTOpenTablePtr ot, xtRecordID rec_id, xtXact ...@@ -4450,10 +4450,10 @@ xtPublic int xt_tab_maybe_committed(XTOpenTablePtr ot, xtRecordID rec_id, xtXact
xtXactID rec_xn_id = 0; xtXactID rec_xn_id = 0;
xtBool wait = FALSE; xtBool wait = FALSE;
xtXactID wait_xn_id = 0; xtXactID wait_xn_id = 0;
xtRowID row_id; xtRowID row_id= 0;
xtRecordID var_rec_id; xtRecordID var_rec_id;
xtXactID xn_id; xtXactID xn_id;
register XTTableHPtr tab; register XTTableHPtr tab = 0;
#ifdef TRACE_VARIATIONS_IN_DUP_CHECK #ifdef TRACE_VARIATIONS_IN_DUP_CHECK
char t_buf[500]; char t_buf[500];
int len; int len;
...@@ -4628,6 +4628,7 @@ xtPublic int xt_tab_maybe_committed(XTOpenTablePtr ot, xtRecordID rec_id, xtXact ...@@ -4628,6 +4628,7 @@ xtPublic int xt_tab_maybe_committed(XTOpenTablePtr ot, xtRecordID rec_id, xtXact
return FALSE; return FALSE;
failed: failed:
if (tab)
XT_TAB_ROW_UNLOCK(&tab->tab_row_rwlock[row_id % XT_ROW_RWLOCKS], ot->ot_thread); XT_TAB_ROW_UNLOCK(&tab->tab_row_rwlock[row_id % XT_ROW_RWLOCKS], ot->ot_thread);
return XT_ERR; return XT_ERR;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment