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:
*/
int QUICK_ROR_INTERSECT_SELECT::init_ror_merged_scan(bool reuse_handler)
{
List_iterator_fast<QUICK_RANGE_SELECT> quick_it(quick_selects);
QUICK_RANGE_SELECT* quick;
List_iterator_fast<QUICK_SELECT_WITH_RECORD> quick_it(quick_selects);
QUICK_SELECT_WITH_RECORD *cur;
QUICK_RANGE_SELECT *quick;
DBUG_ENTER("QUICK_ROR_INTERSECT_SELECT::init_ror_merged_scan");
/* Initialize all merged "children" quick selects */
DBUG_ASSERT(!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
selects.
......@@ -1424,8 +1426,9 @@ int QUICK_ROR_INTERSECT_SELECT::init_ror_merged_scan(bool reuse_handler)
DBUG_RETURN(1);
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))
DBUG_RETURN(1);
quick->file->extra(HA_EXTRA_KEYREAD_PRESERVE_FIELDS);
......@@ -1457,10 +1460,10 @@ int QUICK_ROR_INTERSECT_SELECT::reset()
if (!scans_inited && init_ror_merged_scan(TRUE))
DBUG_RETURN(1);
scans_inited= TRUE;
List_iterator_fast<QUICK_RANGE_SELECT> it(quick_selects);
QUICK_RANGE_SELECT *quick;
while ((quick= it++))
quick->reset();
List_iterator_fast<QUICK_SELECT_WITH_RECORD> it(quick_selects);
QUICK_SELECT_WITH_RECORD *qr;
while ((qr= it++))
qr->quick->reset();
DBUG_RETURN(0);
}
......@@ -1470,6 +1473,7 @@ int QUICK_ROR_INTERSECT_SELECT::reset()
SYNOPSIS
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
rows in rowid order.
NOTES
......@@ -1481,11 +1485,17 @@ int QUICK_ROR_INTERSECT_SELECT::reset()
*/
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()
{
DBUG_ENTER("QUICK_ROR_INTERSECT_SELECT::~QUICK_ROR_INTERSECT_SELECT");
......@@ -4948,7 +4958,7 @@ QUICK_SELECT_I *TRP_ROR_INTERSECT::make_quick(PARAM *param,
{
if (!(quick= get_quick_select(param, (*first_scan)->idx,
(*first_scan)->sel_arg, alloc)) ||
quick_intrsect->push_quick_back(quick))
quick_intrsect->push_quick_back(alloc, quick))
{
delete quick_intrsect;
DBUG_RETURN(NULL);
......@@ -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)
{
QUICK_RANGE_SELECT *quick;
List_iterator_fast<QUICK_RANGE_SELECT> it(quick_selects);
while ((quick= it++))
QUICK_SELECT_WITH_RECORD *qr;
List_iterator_fast<QUICK_SELECT_WITH_RECORD> it(quick_selects);
while ((qr= it++))
{
if (is_key_used(head, quick->index, fields))
if (is_key_used(head, qr->quick->index, fields))
return 1;
}
return 0;
......@@ -8281,7 +8291,8 @@ int QUICK_INDEX_MERGE_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;
int error, cmp;
uint last_rowid_count=0;
......@@ -8290,7 +8301,8 @@ int QUICK_ROR_INTERSECT_SELECT::get_next()
do
{
/* 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();
if (cpk_quick)
{
......@@ -8300,17 +8312,22 @@ int QUICK_ROR_INTERSECT_SELECT::get_next()
if (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);
memcpy(last_rowid, quick->file->ref, head->file->ref_length);
last_rowid_count= 1;
while (last_rowid_count < quick_selects.elements)
{
if (!(quick= quick_it++))
if (!(qr= quick_it++))
{
quick_it.rewind();
quick= quick_it++;
qr= quick_it++;
}
quick= qr->quick;
do
{
......@@ -8320,6 +8337,9 @@ int QUICK_ROR_INTERSECT_SELECT::get_next()
cmp= head->file->cmp_ref(quick->file->ref, last_rowid);
} 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 */
if (cmp > 0)
{
......@@ -8335,6 +8355,10 @@ int QUICK_ROR_INTERSECT_SELECT::get_next()
}
memcpy(last_rowid, quick->file->ref, head->file->ref_length);
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
{
......@@ -8347,6 +8371,21 @@ int QUICK_ROR_INTERSECT_SELECT::get_next()
if (need_to_fetch_row)
error= head->file->rnd_pos(head->record[0], last_rowid);
} 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);
}
......@@ -8969,12 +9008,12 @@ void QUICK_INDEX_MERGE_SELECT::add_info_string(String *str)
void QUICK_ROR_INTERSECT_SELECT::add_info_string(String *str)
{
bool first= TRUE;
QUICK_RANGE_SELECT *quick;
List_iterator_fast<QUICK_RANGE_SELECT> it(quick_selects);
QUICK_SELECT_WITH_RECORD *qr;
List_iterator_fast<QUICK_SELECT_WITH_RECORD> it(quick_selects);
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)
str->append(',');
else
......@@ -9060,11 +9099,11 @@ void QUICK_ROR_INTERSECT_SELECT::add_keys_and_lengths(String *key_names,
char buf[64];
uint length;
bool first= TRUE;
QUICK_RANGE_SELECT *quick;
List_iterator_fast<QUICK_RANGE_SELECT> it(quick_selects);
while ((quick= it++))
QUICK_SELECT_WITH_RECORD *qr;
List_iterator_fast<QUICK_SELECT_WITH_RECORD> it(quick_selects);
while ((qr= it++))
{
KEY *key_info= head->key_info + quick->index;
KEY *key_info= head->key_info + qr->quick->index;
if (first)
first= FALSE;
else
......@@ -9073,7 +9112,7 @@ void QUICK_ROR_INTERSECT_SELECT::add_keys_and_lengths(String *key_names,
used_lengths->append(',');
}
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);
}
......@@ -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)
{
List_iterator_fast<QUICK_RANGE_SELECT> it(quick_selects);
QUICK_RANGE_SELECT *quick;
List_iterator_fast<QUICK_SELECT_WITH_RECORD> it(quick_selects);
QUICK_SELECT_WITH_RECORD *qr;
fprintf(DBUG_FILE, "%*squick ROR-intersect select, %scovering\n",
indent, "", need_to_fetch_row? "":"non-");
fprintf(DBUG_FILE, "%*smerged scans {\n", indent, "");
while ((quick= it++))
quick->dbug_dump(indent+2, verbose);
while ((qr= it++))
qr->quick->dbug_dump(indent+2, verbose);
if (cpk_quick)
{
fprintf(DBUG_FILE, "%*sclustered PK quick:\n", indent, "");
......
......@@ -585,13 +585,21 @@ public:
void dbug_dump(int indent, bool verbose);
#endif
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
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
......
......@@ -4450,10 +4450,10 @@ xtPublic int xt_tab_maybe_committed(XTOpenTablePtr ot, xtRecordID rec_id, xtXact
xtXactID rec_xn_id = 0;
xtBool wait = FALSE;
xtXactID wait_xn_id = 0;
xtRowID row_id;
xtRowID row_id= 0;
xtRecordID var_rec_id;
xtXactID xn_id;
register XTTableHPtr tab;
register XTTableHPtr tab = 0;
#ifdef TRACE_VARIATIONS_IN_DUP_CHECK
char t_buf[500];
int len;
......@@ -4628,6 +4628,7 @@ xtPublic int xt_tab_maybe_committed(XTOpenTablePtr ot, xtRecordID rec_id, xtXact
return FALSE;
failed:
if (tab)
XT_TAB_ROW_UNLOCK(&tab->tab_row_rwlock[row_id % XT_ROW_RWLOCKS], ot->ot_thread);
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