summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorIgor Babaev <igor@askmonty.org>2013-01-21 21:29:19 -0800
committerIgor Babaev <igor@askmonty.org>2013-01-21 21:29:19 -0800
commit746152959a8787f3c7cf6b1c710fc1ee6c54419f (patch)
treefc887933e9d5aaf6d9c83d3e36bba237862c6e65 /sql
parent2255132f200940186c6e9dfcedae6edb85e7cee7 (diff)
parent8127e631de90dddc25b3cdffe59e147333eb6c74 (diff)
downloadmariadb-git-746152959a8787f3c7cf6b1c710fc1ee6c54419f.tar.gz
Merge 5.2->5.3
Diffstat (limited to 'sql')
-rw-r--r--sql/item_sum.cc4
-rw-r--r--sql/mysql_priv.h3
-rw-r--r--sql/sql_base.cc3
-rw-r--r--sql/sql_class.h4
-rw-r--r--sql/sql_insert.cc29
-rw-r--r--sql/sql_show.cc18
-rw-r--r--sql/table.cc14
-rw-r--r--sql/uniques.cc151
8 files changed, 156 insertions, 70 deletions
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 1c83f0e2422..b9c041c1a2e 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -1120,7 +1120,7 @@ void Item_sum_distinct::calculate_val_and_count()
if (tree)
{
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;
}
@@ -2621,7 +2621,7 @@ longlong Item_sum_count_distinct::val_int()
if (tree->elements == 0)
return (longlong) tree->elements_in_tree(); // everything fits in memory
count= 0;
- tree->walk(count_distinct_walk, (void*) &count);
+ tree->walk(table, count_distinct_walk, (void*) &count);
is_evaluated= TRUE;
return (longlong) count;
}
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 4f397ed2334..4f7bf0fe59e 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -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,
uint db_stat, uint prgflag, uint ha_open_flags,
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 writefrm(const char* name, const uchar* data, size_t len);
int closefrm(TABLE *table, bool free_share);
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 3952ae1ff82..630474fcecc 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -8679,7 +8679,8 @@ fill_record(THD * thd, List<Item> &fields, List<Item> &values,
ER(ER_WARNING_NON_DEFAULT_VALUE_FOR_VIRTUAL_COLUMN),
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));
goto err;
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 94bd3c3caae..5224c2ecf47 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -3447,6 +3447,8 @@ class Unique :public Sql_alloc
uint full_size;
uint min_dupl_count; /* always 0 for unions, > 0 for intersections */
+ bool merge(TABLE *table, uchar *buff, bool without_last_merge);
+
public:
ulong elements;
Unique(qsort_cmp2 comp_func, void *comp_func_fixed_arg,
@@ -3487,7 +3489,7 @@ public:
}
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; }
ulonglong get_max_in_memory_size() const { return max_in_memory_size; }
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 713cc7465fe..bfd08e83ca2 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -2129,6 +2129,7 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd)
{
my_ptrdiff_t adjust_ptrs;
Field **field,**org_field, *found_next_number_field;
+ Field **vfield;
TABLE *copy;
TABLE_SHARE *share;
uchar *bitmap;
@@ -2172,6 +2173,13 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd)
if (!copy_tmp)
goto error;
+ if (share->vfields)
+ {
+ vfield= (Field **) client_thd->alloc((share->vfields+1)*sizeof(Field*));
+ if (!vfield)
+ goto error;
+ }
+
/* Copy the TABLE object. */
copy= new (copy_tmp) TABLE;
*copy= *table;
@@ -2201,6 +2209,27 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd)
}
*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 */
if (table->timestamp_field)
{
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 13ead720438..6ff4654e7d4 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -2654,7 +2654,6 @@ static bool show_status_array(THD *thd, const char *wild,
int len;
LEX_STRING null_lex_str;
SHOW_VAR tmp, *var;
- COND *partial_cond= 0;
enum_check_fields save_count_cuted_fields= thd->count_cuted_fields;
bool res= FALSE;
CHARSET_INFO *charset= system_charset_info;
@@ -2668,7 +2667,6 @@ static bool show_status_array(THD *thd, const char *wild,
if (*prefix)
*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++)
{
@@ -2691,13 +2689,13 @@ static bool show_status_array(THD *thd, const char *wild,
if (show_type == SHOW_ARRAY)
{
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
{
if (!(wild && wild[0] && wild_case_compare(system_charset_info,
name_buffer, wild)) &&
- (!partial_cond || partial_cond->val_int()))
+ (!cond || cond->val_int()))
{
char *value=var->value;
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)
schema_table_idx == SCH_GLOBAL_VARIABLES)
option_type= OPT_GLOBAL;
+ COND *partial_cond= make_cond_for_info_schema(cond, tables);
+
rw_rdlock(&LOCK_system_variables_hash);
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);
DBUG_RETURN(res);
}
@@ -6319,13 +6320,18 @@ int fill_status(THD *thd, TABLE_LIST *tables, COND *cond)
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);
if (option_type == OPT_GLOBAL)
calc_sum_of_all_status(&tmp);
res= show_status_array(thd, wild,
(SHOW_VAR *)all_status_vars.buffer,
option_type, tmp1, "", tables->table,
- upper_case_names, cond);
+ upper_case_names, partial_cond);
pthread_mutex_unlock(&LOCK_status);
DBUG_RETURN(res);
}
diff --git a/sql/table.cc b/sql/table.cc
index abdd0b0f9e6..32549568086 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -1916,9 +1916,11 @@ end:
@brief
Unpack the definition of a virtual column from its linear representation
- @parm
+ @param
thd The thread object
@param
+ mem_root The mem_root object where to allocated memory
+ @param
table The table containing the virtual column
@param
field The field for the virtual
@@ -1947,6 +1949,7 @@ end:
TRUE Otherwise
*/
bool unpack_vcol_info_from_frm(THD *thd,
+ MEM_ROOT *mem_root,
TABLE *table,
Field *field,
LEX_STRING *vcol_expr,
@@ -1972,7 +1975,7 @@ bool unpack_vcol_info_from_frm(THD *thd,
"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 +
parse_vcol_keyword.length + 3)))
{
@@ -2006,10 +2009,10 @@ bool unpack_vcol_info_from_frm(THD *thd,
We need to use CONVENTIONAL_EXECUTION here to ensure that
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);
- if (!(vcol_arena= (Query_arena *) alloc_root(&table->mem_root,
- sizeof(Query_arena))))
+ if (!(vcol_arena= (Query_arena *) alloc_root(mem_root,
+ sizeof(Query_arena))))
goto err;
*vcol_arena= expr_arena;
table->expr_arena= vcol_arena;
@@ -2265,6 +2268,7 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias,
if ((*field_ptr)->vcol_info)
{
if (unpack_vcol_info_from_frm(thd,
+ &outparam->mem_root,
outparam,
*field_ptr,
&(*field_ptr)->vcol_info->expr_str,
diff --git a/sql/uniques.cc b/sql/uniques.cc
index 0d0c253df5d..5549d68490c 100644
--- a/sql/uniques.cc
+++ b/sql/uniques.cc
@@ -580,6 +580,7 @@ end:
SYNOPSIS
Unique:walk()
All params are 'IN':
+ table parameter for the call of the merge method
action function-visitor, typed in include/my_tree.h
function is called for each unique element
arg argument for visitor, which is passed to it on each call
@@ -588,70 +589,68 @@ end:
<> 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;
if (elements == 0) /* the whole tree is in memory */
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 */
if (flush())
return 1;
if (flush_io_cache(&file) || reinit_io_cache(&file, READ_CACHE, 0L, 0, 0))
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;
- res= merge_walk(merge_buffer, (ulong) max_in_memory_size, size,
- (BUFFPEK *) file_ptrs.buffer,
- (BUFFPEK *) file_ptrs.buffer + file_ptrs.elements,
- action, walk_action_arg,
- tree.compare, tree.custom_arg, &file);
+ if (buff_sz < (ulong) (full_size * (file_ptrs.elements + 1)))
+ res= merge(table, merge_buffer, buff_sz >= full_size * MERGEBUFF2) ;
+
+ if (!res)
+ {
+ 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));
return res;
}
+
/*
- Modify the TABLE element so that when one calls init_records()
- the rows will be read in priority order.
-*/
+ DESCRIPTION
+ 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;
- 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;
-
- IO_CACHE *outfile=table->sort.io_cache;
+ IO_CACHE *outfile= table->sort.io_cache;
BUFFPEK *file_ptr= (BUFFPEK*) file_ptrs.buffer;
uint maxbuffer= file_ptrs.elements - 1;
- uchar *sort_buffer;
my_off_t save_pos;
- 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));
+ bool error= 1;
+ /* 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 ||
(! my_b_inited(outfile) &&
open_cached_file(outfile,mysql_tmpdir,TEMP_PREFIX,READ_RECORD_BUFFER,
@@ -661,47 +660,89 @@ bool Unique::get(TABLE *table)
bzero((char*) &sort_param,sizeof(sort_param));
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=
full_size;
sort_param.min_dupl_count= min_dupl_count;
sort_param.res_length= 0;
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.sort_length,
- MYF(0))))
- return 1;
- sort_param.unique_buff= sort_buffer+(sort_param.keys*
- sort_param.sort_length);
+ sort_param.unique_buff= buff + (sort_param.keys * sort_param.sort_length);
sort_param.compare= (qsort2_cmp) buffpek_compare;
sort_param.cmp_context.key_compare= tree.compare;
sort_param.cmp_context.key_compare_arg= tree.custom_arg;
/* 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;
if (flush_io_cache(&file) ||
reinit_io_cache(&file,READ_CACHE,0L,0,0))
goto err;
sort_param.res_length= sort_param.rec_length-
(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;
- error=0;
+ error= 0;
err:
- x_free(sort_buffer);
if (flush_io_cache(outfile))
- error=1;
+ error= 1;
/* 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))
- error=1;
+ error= 1;
outfile->end_of_file=save_pos;
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;
+}