summaryrefslogtreecommitdiff
path: root/sql/filesort.cc
diff options
context:
space:
mode:
authorSergei Golubchik <sergii@pisem.net>2014-02-25 16:04:35 +0100
committerSergei Golubchik <sergii@pisem.net>2014-02-25 16:04:35 +0100
commit0b9a0a3517ca2b75655f3af5c372cf333d3d5fe2 (patch)
tree5c67457ff8abbb89b203a7f55cda776b738c385b /sql/filesort.cc
parent6324c36bd703a0f55dcd49dd721af262f73cf7aa (diff)
parentff2e82f4a175b7b023cd167b2fa6e6fcd1bd192e (diff)
downloadmariadb-git-0b9a0a3517ca2b75655f3af5c372cf333d3d5fe2.tar.gz
5.5 merge
Diffstat (limited to 'sql/filesort.cc')
-rw-r--r--sql/filesort.cc133
1 files changed, 116 insertions, 17 deletions
diff --git a/sql/filesort.cc b/sql/filesort.cc
index 7bc8c1d972e..be84dd0736c 100644
--- a/sql/filesort.cc
+++ b/sql/filesort.cc
@@ -39,6 +39,7 @@
#include "sql_select.h"
#include "log_slow.h"
#include "debug_sync.h"
+#include "sql_base.h"
/// How to write record_ref.
#define WRITE_REF(file,from) \
@@ -386,6 +387,14 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length,
{
int kill_errno= thd->killed_errno();
DBUG_ASSERT(thd->is_error() || kill_errno || thd->killed == ABORT_QUERY);
+
+ /*
+ We replace the table->sort at the end.
+ Hence calling free_io_cache to make sure table->sort.io_cache
+ used for QUICK_INDEX_MERGE_SELECT is free.
+ */
+ free_io_cache(table);
+
my_printf_error(ER_FILSORT_ABORT,
"%s: %s",
MYF(0),
@@ -411,6 +420,9 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length,
DBUG_POP(); /* Ok to DBUG */
#endif
+ /* table->sort.io_cache should be free by this time */
+ DBUG_ASSERT(NULL == table->sort.io_cache);
+
// Assign the copy back!
table->sort= table_sort;
@@ -469,6 +481,84 @@ static uchar *read_buffpek_from_file(IO_CACHE *buffpek_pointers, uint count,
}
#ifndef DBUG_OFF
+
+/* Buffer where record is returned */
+char dbug_print_row_buff[512];
+
+/* Temporary buffer for printing a column */
+char dbug_print_row_buff_tmp[512];
+
+/*
+ Print table's current row into a buffer and return a pointer to it.
+
+ This is intended to be used from gdb:
+
+ (gdb) p dbug_print_table_row(table)
+ $33 = "SUBQUERY2_t1(col_int_key,col_varchar_nokey)=(7,c)"
+ (gdb)
+
+ Only columns in table->read_set are printed
+*/
+
+const char* dbug_print_table_row(TABLE *table)
+{
+ Field **pfield;
+ String tmp(dbug_print_row_buff_tmp,
+ sizeof(dbug_print_row_buff_tmp),&my_charset_bin);
+
+ String output(dbug_print_row_buff, sizeof(dbug_print_row_buff),
+ &my_charset_bin);
+
+ output.length(0);
+ output.append(table->alias);
+ output.append("(");
+ bool first= true;
+
+ for (pfield= table->field; *pfield ; pfield++)
+ {
+ if (table->read_set && !bitmap_is_set(table->read_set, (*pfield)->field_index))
+ continue;
+
+ if (first)
+ first= false;
+ else
+ output.append(",");
+
+ output.append((*pfield)->field_name? (*pfield)->field_name: "NULL");
+ }
+
+ output.append(")=(");
+
+ first= true;
+ for (pfield= table->field; *pfield ; pfield++)
+ {
+ Field *field= *pfield;
+
+ if (table->read_set && !bitmap_is_set(table->read_set, (*pfield)->field_index))
+ continue;
+
+ if (first)
+ first= false;
+ else
+ output.append(",");
+
+ if (field->is_null())
+ output.append("NULL");
+ else
+ {
+ if (field->type() == MYSQL_TYPE_BIT)
+ (void) field->val_int_as_str(&tmp, 1);
+ else
+ field->val_str(&tmp);
+ output.append(tmp.ptr(), tmp.length());
+ }
+ }
+ output.append(")");
+
+ return output.c_ptr_safe();
+}
+
+
/*
Print a text, SQL-like record representation into dbug trace.
@@ -517,6 +607,7 @@ static void dbug_print_record(TABLE *table, bool print_rowid)
fprintf(DBUG_FILE, "\n");
DBUG_UNLOCK_FILE;
}
+
#endif
@@ -640,6 +731,7 @@ static ha_rows find_all_keys(Sort_param *param, SQL_SELECT *select,
DBUG_RETURN(HA_POS_ERROR);
}
+ DEBUG_SYNC(thd, "after_index_merge_phase1");
for (;;)
{
if (quick_select)
@@ -732,12 +824,17 @@ static ha_rows find_all_keys(Sort_param *param, SQL_SELECT *select,
make_sortkey(param, fs_info->get_record_buffer(idx++), ref_pos);
}
}
- else
- file->unlock_row();
/* It does not make sense to read more keys in case of a fatal error */
if (thd->is_error())
break;
+
+ /*
+ We need to this after checking the error as the transaction may have
+ rolled back in case of a deadlock
+ */
+ if (!write_record)
+ file->unlock_row();
}
if (!quick_select)
{
@@ -880,8 +977,6 @@ static void make_sortkey(register Sort_param *param,
{
const CHARSET_INFO *cs=item->collation.collation;
char fill_char= ((cs->state & MY_CS_BINSORT) ? (char) 0 : ' ');
- int diff;
- uint sort_field_length;
if (maybe_null)
*to++=1;
@@ -909,25 +1004,13 @@ static void make_sortkey(register Sort_param *param,
break;
}
length= res->length();
- sort_field_length= sort_field->length - sort_field->suffix_length;
- diff=(int) (sort_field_length - length);
- if (diff < 0)
- {
- diff=0;
- length= sort_field_length;
- }
- if (sort_field->suffix_length)
- {
- /* Store length last in result_string */
- store_length(to + sort_field_length, length,
- sort_field->suffix_length);
- }
if (sort_field->need_strxnfrm)
{
char *from=(char*) res->ptr();
uint tmp_length __attribute__((unused));
if ((uchar*) from == to)
{
+ DBUG_ASSERT(sort_field->length >= length);
set_if_smaller(length,sort_field->length);
memcpy(param->tmp_buffer,from,length);
from=param->tmp_buffer;
@@ -938,6 +1021,22 @@ static void make_sortkey(register Sort_param *param,
}
else
{
+ uint diff;
+ uint sort_field_length= sort_field->length -
+ sort_field->suffix_length;
+ if (sort_field_length < length)
+ {
+ diff= 0;
+ length= sort_field_length;
+ }
+ else
+ diff= sort_field_length - length;
+ if (sort_field->suffix_length)
+ {
+ /* Store length last in result_string */
+ store_length(to + sort_field_length, length,
+ sort_field->suffix_length);
+ }
my_strnxfrm(cs,(uchar*)to,length,(const uchar*)res->ptr(),length);
cs->cset->fill(cs, (char *)to+length,diff,fill_char);
}