diff options
author | Igor Babaev <igor@askmonty.org> | 2013-01-21 21:29:19 -0800 |
---|---|---|
committer | Igor Babaev <igor@askmonty.org> | 2013-01-21 21:29:19 -0800 |
commit | 746152959a8787f3c7cf6b1c710fc1ee6c54419f (patch) | |
tree | fc887933e9d5aaf6d9c83d3e36bba237862c6e65 /sql | |
parent | 2255132f200940186c6e9dfcedae6edb85e7cee7 (diff) | |
parent | 8127e631de90dddc25b3cdffe59e147333eb6c74 (diff) | |
download | mariadb-git-746152959a8787f3c7cf6b1c710fc1ee6c54419f.tar.gz |
Merge 5.2->5.3
Diffstat (limited to 'sql')
-rw-r--r-- | sql/item_sum.cc | 4 | ||||
-rw-r--r-- | sql/mysql_priv.h | 3 | ||||
-rw-r--r-- | sql/sql_base.cc | 3 | ||||
-rw-r--r-- | sql/sql_class.h | 4 | ||||
-rw-r--r-- | sql/sql_insert.cc | 29 | ||||
-rw-r--r-- | sql/sql_show.cc | 18 | ||||
-rw-r--r-- | sql/table.cc | 14 | ||||
-rw-r--r-- | sql/uniques.cc | 151 |
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; +} |