Commit fa9c70b3 authored by Igor Babaev's avatar Igor Babaev

Merge 5.2->5.3

parents 4cf8fe04 2ffdb815
select variable_name from information_schema.session_status where variable_name =
(select variable_name from information_schema.session_status where variable_name = 'uptime');
variable_name
UPTIME
select variable_name from information_schema.session_variables where variable_name =
(select variable_name from information_schema.session_variables where variable_name = 'basedir');
variable_name
BASEDIR
...@@ -103,5 +103,20 @@ sm ...@@ -103,5 +103,20 @@ sm
10323810 10323810
10325070 10325070
10326330 10326330
#
# Bug mdev-4063: SUM(DISTINCT...) with small'max_heap_table_size
# (bug #56927)
#
SET max_heap_table_size=default;
INSERT INTO t1 SELECT id+16384 FROM t1;
DELETE FROM t2;
INSERT INTO t2 SELECT id FROM t1 ORDER BY id*rand();
SELECT SUM(DISTINCT id) sm FROM t2;
sm
536887296
SET max_heap_table_size=16384;
SELECT SUM(DISTINCT id) sm FROM t2;
sm
536887296
DROP TABLE t1; DROP TABLE t1;
DROP TABLE t2; DROP TABLE t2;
...@@ -182,6 +182,17 @@ a b c ...@@ -182,6 +182,17 @@ a b c
2 3 y 2 3 y
0 1 y,n 0 1 y,n
drop table t1,t2; drop table t1,t2;
CREATE TABLE t1 (
ts TIMESTAMP,
tsv TIMESTAMP AS (ADDDATE(ts, INTERVAL 1 DAY)) VIRTUAL
) ENGINE=MyISAM;
INSERT INTO t1 (tsv) VALUES (DEFAULT);
INSERT DELAYED INTO t1 (tsv) VALUES (DEFAULT);
FLUSH TABLES;
SELECT COUNT(*) FROM t1;
COUNT(*)
2
DROP TABLE t1;
create table t1 (a int, b int); create table t1 (a int, b int);
insert into t1 values (3, 30), (4, 20), (1, 20); insert into t1 values (3, 30), (4, 20), (1, 20);
create table t2 (c int, d int, v int as (d+1), index idx(c)); create table t2 (c int, d int, v int as (d+1), index idx(c));
......
...@@ -178,6 +178,25 @@ select * from t2; ...@@ -178,6 +178,25 @@ select * from t2;
drop table t1,t2; drop table t1,t2;
#
# Bug mdev-3938: INSERT DELAYED for a table with virtual columns
#
CREATE TABLE t1 (
ts TIMESTAMP,
tsv TIMESTAMP AS (ADDDATE(ts, INTERVAL 1 DAY)) VIRTUAL
) ENGINE=MyISAM;
INSERT INTO t1 (tsv) VALUES (DEFAULT);
INSERT DELAYED INTO t1 (tsv) VALUES (DEFAULT);
FLUSH TABLES;
SELECT COUNT(*) FROM t1;
DROP TABLE t1;
# #
# SELECT that uses a virtual column and executed with BKA # SELECT that uses a virtual column and executed with BKA
# #
......
#
# MDEV-4029 SELECT on information_schema using a subquery locks up the information_schema table due to incorrect mutexes handling
#
select variable_name from information_schema.session_status where variable_name =
(select variable_name from information_schema.session_status where variable_name = 'uptime');
select variable_name from information_schema.session_variables where variable_name =
(select variable_name from information_schema.session_variables where variable_name = 'basedir');
...@@ -63,5 +63,22 @@ SELECT SUM(DISTINCT id) sm FROM t1; ...@@ -63,5 +63,22 @@ SELECT SUM(DISTINCT id) sm FROM t1;
SELECT SUM(DISTINCT id) sm FROM t2; SELECT SUM(DISTINCT id) sm FROM t2;
SELECT SUM(DISTINCT id) sm FROM t1 GROUP BY id % 13; SELECT SUM(DISTINCT id) sm FROM t1 GROUP BY id % 13;
--echo #
--echo # Bug mdev-4063: SUM(DISTINCT...) with small'max_heap_table_size
--echo # (bug #56927)
--echo #
SET max_heap_table_size=default;
INSERT INTO t1 SELECT id+16384 FROM t1;
DELETE FROM t2;
INSERT INTO t2 SELECT id FROM t1 ORDER BY id*rand();
SELECT SUM(DISTINCT id) sm FROM t2;
SET max_heap_table_size=16384;
SELECT SUM(DISTINCT id) sm FROM t2;
DROP TABLE t1; DROP TABLE t1;
DROP TABLE t2; DROP TABLE t2;
...@@ -1120,7 +1120,7 @@ void Item_sum_distinct::calculate_val_and_count() ...@@ -1120,7 +1120,7 @@ void Item_sum_distinct::calculate_val_and_count()
if (tree) if (tree)
{ {
table->field[0]->set_notnull(); table->field[0]->set_notnull();
tree->walk(item_sum_distinct_walk, (void*) this); tree->walk(table, item_sum_distinct_walk, (void*) this);
} }
is_evaluated= TRUE; is_evaluated= TRUE;
} }
...@@ -2621,7 +2621,7 @@ longlong Item_sum_count_distinct::val_int() ...@@ -2621,7 +2621,7 @@ longlong Item_sum_count_distinct::val_int()
if (tree->elements == 0) if (tree->elements == 0)
return (longlong) tree->elements_in_tree(); // everything fits in memory return (longlong) tree->elements_in_tree(); // everything fits in memory
count= 0; count= 0;
tree->walk(count_distinct_walk, (void*) &count); tree->walk(table, count_distinct_walk, (void*) &count);
is_evaluated= TRUE; is_evaluated= TRUE;
return (longlong) count; return (longlong) count;
} }
......
...@@ -2472,6 +2472,9 @@ void open_table_error(TABLE_SHARE *share, int error, int db_errno, int errarg); ...@@ -2472,6 +2472,9 @@ void open_table_error(TABLE_SHARE *share, int error, int db_errno, int errarg);
int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias, int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias,
uint db_stat, uint prgflag, uint ha_open_flags, uint db_stat, uint prgflag, uint ha_open_flags,
TABLE *outparam, bool is_create_table); TABLE *outparam, bool is_create_table);
bool unpack_vcol_info_from_frm(THD *thd, MEM_ROOT *mem_root,
TABLE *table, Field *field,
LEX_STRING *vcol_expr, bool *error_reported);
int readfrm(const char *name, uchar **data, size_t *length); int readfrm(const char *name, uchar **data, size_t *length);
int writefrm(const char* name, const uchar* data, size_t len); int writefrm(const char* name, const uchar* data, size_t len);
int closefrm(TABLE *table, bool free_share); int closefrm(TABLE *table, bool free_share);
......
...@@ -8679,7 +8679,8 @@ fill_record(THD * thd, List<Item> &fields, List<Item> &values, ...@@ -8679,7 +8679,8 @@ fill_record(THD * thd, List<Item> &fields, List<Item> &values,
ER(ER_WARNING_NON_DEFAULT_VALUE_FOR_VIRTUAL_COLUMN), ER(ER_WARNING_NON_DEFAULT_VALUE_FOR_VIRTUAL_COLUMN),
rfield->field_name, table->s->table_name.str); rfield->field_name, table->s->table_name.str);
} }
if ((value->save_in_field(rfield, 0)) < 0 && !ignore_errors) if ((!rfield->vcol_info || rfield->stored_in_db) &&
(value->save_in_field(rfield, 0)) < 0 && !ignore_errors)
{ {
my_message(ER_UNKNOWN_ERROR, ER(ER_UNKNOWN_ERROR), MYF(0)); my_message(ER_UNKNOWN_ERROR, ER(ER_UNKNOWN_ERROR), MYF(0));
goto err; goto err;
......
...@@ -3447,6 +3447,8 @@ class Unique :public Sql_alloc ...@@ -3447,6 +3447,8 @@ class Unique :public Sql_alloc
uint full_size; uint full_size;
uint min_dupl_count; /* always 0 for unions, > 0 for intersections */ uint min_dupl_count; /* always 0 for unions, > 0 for intersections */
bool merge(TABLE *table, uchar *buff, bool without_last_merge);
public: public:
ulong elements; ulong elements;
Unique(qsort_cmp2 comp_func, void *comp_func_fixed_arg, Unique(qsort_cmp2 comp_func, void *comp_func_fixed_arg,
...@@ -3487,7 +3489,7 @@ class Unique :public Sql_alloc ...@@ -3487,7 +3489,7 @@ class Unique :public Sql_alloc
} }
void reset(); void reset();
bool walk(tree_walk_action action, void *walk_action_arg); bool walk(TABLE *table, tree_walk_action action, void *walk_action_arg);
uint get_size() const { return size; } uint get_size() const { return size; }
ulonglong get_max_in_memory_size() const { return max_in_memory_size; } ulonglong get_max_in_memory_size() const { return max_in_memory_size; }
......
...@@ -2129,6 +2129,7 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd) ...@@ -2129,6 +2129,7 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd)
{ {
my_ptrdiff_t adjust_ptrs; my_ptrdiff_t adjust_ptrs;
Field **field,**org_field, *found_next_number_field; Field **field,**org_field, *found_next_number_field;
Field **vfield;
TABLE *copy; TABLE *copy;
TABLE_SHARE *share; TABLE_SHARE *share;
uchar *bitmap; uchar *bitmap;
...@@ -2172,6 +2173,13 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd) ...@@ -2172,6 +2173,13 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd)
if (!copy_tmp) if (!copy_tmp)
goto error; goto error;
if (share->vfields)
{
vfield= (Field **) client_thd->alloc((share->vfields+1)*sizeof(Field*));
if (!vfield)
goto error;
}
/* Copy the TABLE object. */ /* Copy the TABLE object. */
copy= new (copy_tmp) TABLE; copy= new (copy_tmp) TABLE;
*copy= *table; *copy= *table;
...@@ -2201,6 +2209,27 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd) ...@@ -2201,6 +2209,27 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd)
} }
*field=0; *field=0;
if (share->vfields)
{
copy->vfield= vfield;
for (field= copy->field; *field; field++)
{
if ((*field)->vcol_info)
{
bool error_reported= FALSE;
if (unpack_vcol_info_from_frm(client_thd,
client_thd->mem_root,
copy,
*field,
&(*field)->vcol_info->expr_str,
&error_reported))
goto error;
*vfield++= *field;
}
}
*vfield= 0;
}
/* Adjust timestamp */ /* Adjust timestamp */
if (table->timestamp_field) if (table->timestamp_field)
{ {
......
...@@ -2654,7 +2654,6 @@ static bool show_status_array(THD *thd, const char *wild, ...@@ -2654,7 +2654,6 @@ static bool show_status_array(THD *thd, const char *wild,
int len; int len;
LEX_STRING null_lex_str; LEX_STRING null_lex_str;
SHOW_VAR tmp, *var; SHOW_VAR tmp, *var;
COND *partial_cond= 0;
enum_check_fields save_count_cuted_fields= thd->count_cuted_fields; enum_check_fields save_count_cuted_fields= thd->count_cuted_fields;
bool res= FALSE; bool res= FALSE;
CHARSET_INFO *charset= system_charset_info; CHARSET_INFO *charset= system_charset_info;
...@@ -2668,7 +2667,6 @@ static bool show_status_array(THD *thd, const char *wild, ...@@ -2668,7 +2667,6 @@ static bool show_status_array(THD *thd, const char *wild,
if (*prefix) if (*prefix)
*prefix_end++= '_'; *prefix_end++= '_';
len=name_buffer + sizeof(name_buffer) - prefix_end; len=name_buffer + sizeof(name_buffer) - prefix_end;
partial_cond= make_cond_for_info_schema(cond, table->pos_in_table_list);
for (; variables->name; variables++) for (; variables->name; variables++)
{ {
...@@ -2691,13 +2689,13 @@ static bool show_status_array(THD *thd, const char *wild, ...@@ -2691,13 +2689,13 @@ static bool show_status_array(THD *thd, const char *wild,
if (show_type == SHOW_ARRAY) if (show_type == SHOW_ARRAY)
{ {
show_status_array(thd, wild, (SHOW_VAR *) var->value, value_type, show_status_array(thd, wild, (SHOW_VAR *) var->value, value_type,
status_var, name_buffer, table, ucase_names, partial_cond); status_var, name_buffer, table, ucase_names, cond);
} }
else else
{ {
if (!(wild && wild[0] && wild_case_compare(system_charset_info, if (!(wild && wild[0] && wild_case_compare(system_charset_info,
name_buffer, wild)) && name_buffer, wild)) &&
(!partial_cond || partial_cond->val_int())) (!cond || cond->val_int()))
{ {
char *value=var->value; char *value=var->value;
const char *pos, *end; // We assign a lot of const's const char *pos, *end; // We assign a lot of const's
...@@ -6280,9 +6278,12 @@ int fill_variables(THD *thd, TABLE_LIST *tables, COND *cond) ...@@ -6280,9 +6278,12 @@ int fill_variables(THD *thd, TABLE_LIST *tables, COND *cond)
schema_table_idx == SCH_GLOBAL_VARIABLES) schema_table_idx == SCH_GLOBAL_VARIABLES)
option_type= OPT_GLOBAL; option_type= OPT_GLOBAL;
COND *partial_cond= make_cond_for_info_schema(cond, tables);
rw_rdlock(&LOCK_system_variables_hash); rw_rdlock(&LOCK_system_variables_hash);
res= show_status_array(thd, wild, enumerate_sys_vars(thd, sorted_vars), res= show_status_array(thd, wild, enumerate_sys_vars(thd, sorted_vars),
option_type, NULL, "", tables->table, upper_case_names, cond); option_type, NULL, "", tables->table, upper_case_names,
partial_cond);
rw_unlock(&LOCK_system_variables_hash); rw_unlock(&LOCK_system_variables_hash);
DBUG_RETURN(res); DBUG_RETURN(res);
} }
...@@ -6319,13 +6320,18 @@ int fill_status(THD *thd, TABLE_LIST *tables, COND *cond) ...@@ -6319,13 +6320,18 @@ int fill_status(THD *thd, TABLE_LIST *tables, COND *cond)
tmp1= &thd->status_var; tmp1= &thd->status_var;
} }
COND *partial_cond= make_cond_for_info_schema(cond, tables);
// Evaluate and cache const subqueries now, before the mutex.
if (partial_cond)
partial_cond->val_int();
pthread_mutex_lock(&LOCK_status); pthread_mutex_lock(&LOCK_status);
if (option_type == OPT_GLOBAL) if (option_type == OPT_GLOBAL)
calc_sum_of_all_status(&tmp); calc_sum_of_all_status(&tmp);
res= show_status_array(thd, wild, res= show_status_array(thd, wild,
(SHOW_VAR *)all_status_vars.buffer, (SHOW_VAR *)all_status_vars.buffer,
option_type, tmp1, "", tables->table, option_type, tmp1, "", tables->table,
upper_case_names, cond); upper_case_names, partial_cond);
pthread_mutex_unlock(&LOCK_status); pthread_mutex_unlock(&LOCK_status);
DBUG_RETURN(res); DBUG_RETURN(res);
} }
......
...@@ -1916,8 +1916,10 @@ bool fix_vcol_expr(THD *thd, ...@@ -1916,8 +1916,10 @@ bool fix_vcol_expr(THD *thd,
@brief @brief
Unpack the definition of a virtual column from its linear representation Unpack the definition of a virtual column from its linear representation
@parm @param
thd The thread object thd The thread object
@param
mem_root The mem_root object where to allocated memory
@param @param
table The table containing the virtual column table The table containing the virtual column
@param @param
...@@ -1947,6 +1949,7 @@ bool fix_vcol_expr(THD *thd, ...@@ -1947,6 +1949,7 @@ bool fix_vcol_expr(THD *thd,
TRUE Otherwise TRUE Otherwise
*/ */
bool unpack_vcol_info_from_frm(THD *thd, bool unpack_vcol_info_from_frm(THD *thd,
MEM_ROOT *mem_root,
TABLE *table, TABLE *table,
Field *field, Field *field,
LEX_STRING *vcol_expr, LEX_STRING *vcol_expr,
...@@ -1972,7 +1975,7 @@ bool unpack_vcol_info_from_frm(THD *thd, ...@@ -1972,7 +1975,7 @@ bool unpack_vcol_info_from_frm(THD *thd,
"PARSE_VCOL_EXPR (<expr_string_from_frm>)". "PARSE_VCOL_EXPR (<expr_string_from_frm>)".
*/ */
if (!(vcol_expr_str= (char*) alloc_root(&table->mem_root, if (!(vcol_expr_str= (char*) alloc_root(mem_root,
vcol_expr->length + vcol_expr->length +
parse_vcol_keyword.length + 3))) parse_vcol_keyword.length + 3)))
{ {
...@@ -2006,10 +2009,10 @@ bool unpack_vcol_info_from_frm(THD *thd, ...@@ -2006,10 +2009,10 @@ bool unpack_vcol_info_from_frm(THD *thd,
We need to use CONVENTIONAL_EXECUTION here to ensure that We need to use CONVENTIONAL_EXECUTION here to ensure that
any new items created by fix_fields() are not reverted. any new items created by fix_fields() are not reverted.
*/ */
Query_arena expr_arena(&table->mem_root, Query_arena expr_arena(mem_root,
Query_arena::CONVENTIONAL_EXECUTION); Query_arena::CONVENTIONAL_EXECUTION);
if (!(vcol_arena= (Query_arena *) alloc_root(&table->mem_root, if (!(vcol_arena= (Query_arena *) alloc_root(mem_root,
sizeof(Query_arena)))) sizeof(Query_arena))))
goto err; goto err;
*vcol_arena= expr_arena; *vcol_arena= expr_arena;
table->expr_arena= vcol_arena; table->expr_arena= vcol_arena;
...@@ -2265,6 +2268,7 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias, ...@@ -2265,6 +2268,7 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias,
if ((*field_ptr)->vcol_info) if ((*field_ptr)->vcol_info)
{ {
if (unpack_vcol_info_from_frm(thd, if (unpack_vcol_info_from_frm(thd,
&outparam->mem_root,
outparam, outparam,
*field_ptr, *field_ptr,
&(*field_ptr)->vcol_info->expr_str, &(*field_ptr)->vcol_info->expr_str,
......
...@@ -580,6 +580,7 @@ static bool merge_walk(uchar *merge_buffer, ulong merge_buffer_size, ...@@ -580,6 +580,7 @@ static bool merge_walk(uchar *merge_buffer, ulong merge_buffer_size,
SYNOPSIS SYNOPSIS
Unique:walk() Unique:walk()
All params are 'IN': All params are 'IN':
table parameter for the call of the merge method
action function-visitor, typed in include/my_tree.h action function-visitor, typed in include/my_tree.h
function is called for each unique element function is called for each unique element
arg argument for visitor, which is passed to it on each call arg argument for visitor, which is passed to it on each call
...@@ -588,70 +589,68 @@ static bool merge_walk(uchar *merge_buffer, ulong merge_buffer_size, ...@@ -588,70 +589,68 @@ static bool merge_walk(uchar *merge_buffer, ulong merge_buffer_size,
<> 0 error <> 0 error
*/ */
bool Unique::walk(tree_walk_action action, void *walk_action_arg) bool Unique::walk(TABLE *table, tree_walk_action action, void *walk_action_arg)
{ {
int res; int res= 0;
uchar *merge_buffer; uchar *merge_buffer;
if (elements == 0) /* the whole tree is in memory */ if (elements == 0) /* the whole tree is in memory */
return tree_walk(&tree, action, walk_action_arg, left_root_right); return tree_walk(&tree, action, walk_action_arg, left_root_right);
table->sort.found_records=elements+tree.elements_in_tree;
/* flush current tree to the file to have some memory for merge buffer */ /* flush current tree to the file to have some memory for merge buffer */
if (flush()) if (flush())
return 1; return 1;
if (flush_io_cache(&file) || reinit_io_cache(&file, READ_CACHE, 0L, 0, 0)) if (flush_io_cache(&file) || reinit_io_cache(&file, READ_CACHE, 0L, 0, 0))
return 1; return 1;
if (!(merge_buffer= (uchar *) my_malloc((ulong) max_in_memory_size, MYF(0)))) ulong buff_sz= (max_in_memory_size / full_size + 1) * full_size;
if (!(merge_buffer= (uchar *) my_malloc((ulong) buff_sz, MYF(0))))
return 1; return 1;
res= merge_walk(merge_buffer, (ulong) max_in_memory_size, size, if (buff_sz < (ulong) (full_size * (file_ptrs.elements + 1)))
(BUFFPEK *) file_ptrs.buffer, res= merge(table, merge_buffer, buff_sz >= full_size * MERGEBUFF2) ;
(BUFFPEK *) file_ptrs.buffer + file_ptrs.elements,
action, walk_action_arg, if (!res)
tree.compare, tree.custom_arg, &file); {
res= merge_walk(merge_buffer, (ulong) max_in_memory_size, full_size,
(BUFFPEK *) file_ptrs.buffer,
(BUFFPEK *) file_ptrs.buffer + file_ptrs.elements,
action, walk_action_arg,
tree.compare, tree.custom_arg, &file);
}
my_free((char*) merge_buffer, MYF(0)); my_free((char*) merge_buffer, MYF(0));
return res; return res;
} }
/* /*
Modify the TABLE element so that when one calls init_records() DESCRIPTION
the rows will be read in priority order. Perform multi-pass sort merge of the elements accessed through table->sort,
*/ using the buffer buff as the merge buffer. The last pass is not performed
if without_last_merge is TRUE.
SYNOPSIS
Unique:merge()
All params are 'IN':
table the parameter to access sort context
buff merge buffer
without_last_merge TRUE <=> do not perform the last merge
RETURN VALUE
0 OK
<> 0 error
*/
bool Unique::get(TABLE *table) bool Unique::merge(TABLE *table, uchar *buff, bool without_last_merge)
{ {
SORTPARAM sort_param; SORTPARAM sort_param;
table->sort.found_records=elements+tree.elements_in_tree; IO_CACHE *outfile= table->sort.io_cache;
if (my_b_tell(&file) == 0)
{
/* Whole tree is in memory; Don't use disk if you don't need to */
if ((record_pointers=table->sort.record_pointers= (uchar*)
my_malloc(size * tree.elements_in_tree, MYF(0))))
{
tree_walk_action action= min_dupl_count ?
(tree_walk_action) unique_intersect_write_to_ptrs :
(tree_walk_action) unique_write_to_ptrs;
filtered_out_elems= 0;
(void) tree_walk(&tree, action,
this, left_root_right);
table->sort.found_records-= filtered_out_elems;
return 0;
}
}
/* Not enough memory; Save the result to file && free memory used by tree */
if (flush())
return 1;
IO_CACHE *outfile=table->sort.io_cache;
BUFFPEK *file_ptr= (BUFFPEK*) file_ptrs.buffer; BUFFPEK *file_ptr= (BUFFPEK*) file_ptrs.buffer;
uint maxbuffer= file_ptrs.elements - 1; uint maxbuffer= file_ptrs.elements - 1;
uchar *sort_buffer;
my_off_t save_pos; my_off_t save_pos;
bool error=1; bool error= 1;
/* Open cached file if it isn't open */
outfile=table->sort.io_cache=(IO_CACHE*) my_malloc(sizeof(IO_CACHE),
MYF(MY_ZEROFILL));
/* Open cached file if it isn't open */
if (!outfile)
outfile= table->sort.io_cache= (IO_CACHE*) my_malloc(sizeof(IO_CACHE),
MYF(MY_ZEROFILL));
if (!outfile || if (!outfile ||
(! my_b_inited(outfile) && (! my_b_inited(outfile) &&
open_cached_file(outfile,mysql_tmpdir,TEMP_PREFIX,READ_RECORD_BUFFER, open_cached_file(outfile,mysql_tmpdir,TEMP_PREFIX,READ_RECORD_BUFFER,
...@@ -661,47 +660,89 @@ bool Unique::get(TABLE *table) ...@@ -661,47 +660,89 @@ bool Unique::get(TABLE *table)
bzero((char*) &sort_param,sizeof(sort_param)); bzero((char*) &sort_param,sizeof(sort_param));
sort_param.max_rows= elements; sort_param.max_rows= elements;
sort_param.sort_form=table; sort_param.sort_form= table;
sort_param.rec_length= sort_param.sort_length= sort_param.ref_length= sort_param.rec_length= sort_param.sort_length= sort_param.ref_length=
full_size; full_size;
sort_param.min_dupl_count= min_dupl_count; sort_param.min_dupl_count= min_dupl_count;
sort_param.res_length= 0; sort_param.res_length= 0;
sort_param.keys= (uint) (max_in_memory_size / sort_param.sort_length); sort_param.keys= (uint) (max_in_memory_size / sort_param.sort_length);
sort_param.not_killable=1; sort_param.not_killable= 1;
if (!(sort_buffer=(uchar*) my_malloc((sort_param.keys+1) * sort_param.unique_buff= buff + (sort_param.keys * sort_param.sort_length);
sort_param.sort_length,
MYF(0))))
return 1;
sort_param.unique_buff= sort_buffer+(sort_param.keys*
sort_param.sort_length);
sort_param.compare= (qsort2_cmp) buffpek_compare; sort_param.compare= (qsort2_cmp) buffpek_compare;
sort_param.cmp_context.key_compare= tree.compare; sort_param.cmp_context.key_compare= tree.compare;
sort_param.cmp_context.key_compare_arg= tree.custom_arg; sort_param.cmp_context.key_compare_arg= tree.custom_arg;
/* Merge the buffers to one file, removing duplicates */ /* Merge the buffers to one file, removing duplicates */
if (merge_many_buff(&sort_param,sort_buffer,file_ptr,&maxbuffer,&file)) if (merge_many_buff(&sort_param,buff,file_ptr,&maxbuffer,&file))
goto err; goto err;
if (flush_io_cache(&file) || if (flush_io_cache(&file) ||
reinit_io_cache(&file,READ_CACHE,0L,0,0)) reinit_io_cache(&file,READ_CACHE,0L,0,0))
goto err; goto err;
sort_param.res_length= sort_param.rec_length- sort_param.res_length= sort_param.rec_length-
(min_dupl_count ? sizeof(min_dupl_count) : 0); (min_dupl_count ? sizeof(min_dupl_count) : 0);
if (merge_index(&sort_param, sort_buffer, file_ptr, maxbuffer, &file, outfile)) if (without_last_merge)
{
file_ptrs.elements= maxbuffer+1;
return 0;
}
if (merge_index(&sort_param, buff, file_ptr, maxbuffer, &file, outfile))
goto err; goto err;
error=0; error= 0;
err: err:
x_free(sort_buffer);
if (flush_io_cache(outfile)) if (flush_io_cache(outfile))
error=1; error= 1;
/* Setup io_cache for reading */ /* Setup io_cache for reading */
save_pos=outfile->pos_in_file; save_pos= outfile->pos_in_file;
if (reinit_io_cache(outfile,READ_CACHE,0L,0,0)) if (reinit_io_cache(outfile,READ_CACHE,0L,0,0))
error=1; error= 1;
outfile->end_of_file=save_pos; outfile->end_of_file=save_pos;
return error; return error;
} }
/*
Modify the TABLE element so that when one calls init_records()
the rows will be read in priority order.
*/
bool Unique::get(TABLE *table)
{
bool rc= 1;
uchar *sort_buffer= NULL;
table->sort.found_records= elements+tree.elements_in_tree;
if (my_b_tell(&file) == 0)
{
/* Whole tree is in memory; Don't use disk if you don't need to */
if ((record_pointers=table->sort.record_pointers= (uchar*)
my_malloc(size * tree.elements_in_tree, MYF(0))))
{
tree_walk_action action= min_dupl_count ?
(tree_walk_action) unique_intersect_write_to_ptrs :
(tree_walk_action) unique_write_to_ptrs;
filtered_out_elems= 0;
(void) tree_walk(&tree, action,
this, left_root_right);
table->sort.found_records-= filtered_out_elems;
return 0;
}
}
/* Not enough memory; Save the result to file && free memory used by tree */
if (flush())
return 1;
ulong buff_sz= (max_in_memory_size / full_size + 1) * full_size;
if (!(sort_buffer= (uchar*) my_malloc(buff_sz, MYF(0))))
return 1;
if (merge(table, sort_buffer, FALSE))
goto err;
rc= 0;
err:
x_free(sort_buffer);
return rc;
}
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