diff options
author | unknown <tsmith@ramayana.hindu.god> | 2008-01-22 15:56:15 -0700 |
---|---|---|
committer | unknown <tsmith@ramayana.hindu.god> | 2008-01-22 15:56:15 -0700 |
commit | 6c26935035ce6fc646fc448dc181d9a3a870cd54 (patch) | |
tree | 22de11d4d65b9eb7c56b5e80669f19cf9ff242f4 /sql | |
parent | 74c9f82afb1d145636b91eff4b26131fd60e4f68 (diff) | |
parent | 37ff91b3bfdb946743e36ddd13bfda71598f45a8 (diff) | |
download | mariadb-git-6c26935035ce6fc646fc448dc181d9a3a870cd54.tar.gz |
Merge ramayana.hindu.god:/home/tsmith/m/bk/51
into ramayana.hindu.god:/home/tsmith/m/bk/maint/51
client/mysqldump.c:
Auto merged
configure.in:
Auto merged
sql/field.cc:
Auto merged
sql/filesort.cc:
Auto merged
sql/item.cc:
Auto merged
sql/item_timefunc.cc:
Auto merged
sql/log.cc:
Auto merged
sql/repl_failsafe.cc:
Auto merged
sql/set_var.cc:
Auto merged
sql/sp.cc:
Auto merged
sql/sql_base.cc:
Auto merged
sql/sql_class.cc:
Auto merged
sql/sql_class.h:
Auto merged
sql/sql_select.cc:
Auto merged
sql/sql_show.cc:
Auto merged
sql/sql_yacc.yy:
Auto merged
sql/item_sum.cc:
Manual merge.
Diffstat (limited to 'sql')
-rw-r--r-- | sql/field.cc | 10 | ||||
-rw-r--r-- | sql/field.h | 15 | ||||
-rw-r--r-- | sql/filesort.cc | 24 | ||||
-rw-r--r-- | sql/item.cc | 6 | ||||
-rw-r--r-- | sql/item_sum.cc | 156 | ||||
-rw-r--r-- | sql/item_sum.h | 28 | ||||
-rw-r--r-- | sql/item_timefunc.cc | 2 | ||||
-rw-r--r-- | sql/log.cc | 4 | ||||
-rw-r--r-- | sql/repl_failsafe.cc | 2 | ||||
-rw-r--r-- | sql/sql_base.cc | 31 | ||||
-rw-r--r-- | sql/sql_db.cc | 2 | ||||
-rw-r--r-- | sql/sql_select.cc | 2 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 11 | ||||
-rw-r--r-- | sql/unireg.cc | 8 |
14 files changed, 201 insertions, 100 deletions
diff --git a/sql/field.cc b/sql/field.cc index 16217e69de9..7c4f6c9ff5f 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -1308,7 +1308,8 @@ Field::Field(uchar *ptr_arg,uint32 length_arg,uchar *null_ptr_arg, field_name(field_name_arg), key_start(0), part_of_key(0), part_of_key_not_clustered(0), part_of_sortkey(0), unireg_check(unireg_check_arg), - field_length(length_arg), null_bit(null_bit_arg) + field_length(length_arg), null_bit(null_bit_arg), + is_created_from_null_item(FALSE) { flags=null_ptr ? 0: NOT_NULL_FLAG; comment.str= (char*) ""; @@ -5633,6 +5634,13 @@ String *Field_date::val_str(String *val_buffer, } +bool Field_date::get_time(MYSQL_TIME *ltime) +{ + bzero((char *)ltime, sizeof(MYSQL_TIME)); + return 0; +} + + int Field_date::cmp(const uchar *a_ptr, const uchar *b_ptr) { int32 a,b; diff --git a/sql/field.h b/sql/field.h index 9f76deb18bc..a6a1d8bfabc 100644 --- a/sql/field.h +++ b/sql/field.h @@ -90,6 +90,16 @@ public: uint32 flags; uint16 field_index; // field number in fields array uchar null_bit; // Bit used to test null bit + /** + If true, this field was created in create_tmp_field_from_item from a NULL + value. This means that the type of the field is just a guess, and the type + may be freely coerced to another type. + + @see create_tmp_field_from_item + @see Item_type_holder::get_real_type + + */ + bool is_created_from_null_item; Field(uchar *ptr_arg,uint32 length_arg,uchar *null_ptr_arg, uchar null_bit_arg, utype unireg_check_arg, @@ -1240,6 +1250,7 @@ public: double val_real(void); longlong val_int(void); String *val_str(String*,String *); + bool get_time(MYSQL_TIME *ltime); bool send_binary(Protocol *protocol); int cmp(const uchar *,const uchar *); void sort_string(uchar *buff,uint length); @@ -1258,6 +1269,10 @@ public: :Field_str(ptr_arg, 10, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, cs) {} + Field_newdate(bool maybe_null_arg, const char *field_name_arg, + CHARSET_INFO *cs) + :Field_str((uchar*) 0,10, maybe_null_arg ? (uchar*) "": 0,0, + NONE, field_name_arg, cs) {} enum_field_types type() const { return MYSQL_TYPE_DATE;} enum_field_types real_type() const { return MYSQL_TYPE_NEWDATE; } enum ha_base_keytype key_type() const { return HA_KEYTYPE_UINT24; } diff --git a/sql/filesort.cc b/sql/filesort.cc index 61c8ca3b256..3783aa2a06a 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -41,7 +41,8 @@ if (my_b_write((file),(uchar*) (from),param->ref_length)) \ static char **make_char_array(char **old_pos, register uint fields, uint length, myf my_flag); -static BUFFPEK *read_buffpek_from_file(IO_CACHE *buffer_file, uint count); +static uchar *read_buffpek_from_file(IO_CACHE *buffer_file, uint count, + uchar *buf); static ha_rows find_all_keys(SORTPARAM *param,SQL_SELECT *select, uchar * *sort_keys, IO_CACHE *buffer_file, IO_CACHE *tempfile,IO_CACHE *indexfile); @@ -246,9 +247,14 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length, } else { - if (!table_sort.buffpek && table_sort.buffpek_len < maxbuffer && - !(table_sort.buffpek= - (uchar *) read_buffpek_from_file(&buffpek_pointers, maxbuffer))) + if (table_sort.buffpek && table_sort.buffpek_len < maxbuffer) + { + x_free(table_sort.buffpek); + table_sort.buffpek= 0; + } + if (!(table_sort.buffpek= + (uchar *) read_buffpek_from_file(&buffpek_pointers, maxbuffer, + table_sort.buffpek))) goto err; buffpek= (BUFFPEK *) table_sort.buffpek; table_sort.buffpek_len= maxbuffer; @@ -376,14 +382,16 @@ static char **make_char_array(char **old_pos, register uint fields, /** Read 'count' number of buffer pointers into memory. */ -static BUFFPEK *read_buffpek_from_file(IO_CACHE *buffpek_pointers, uint count) +static uchar *read_buffpek_from_file(IO_CACHE *buffpek_pointers, uint count, + uchar *buf) { - ulong length; - BUFFPEK *tmp; + ulong length= sizeof(BUFFPEK)*count; + uchar *tmp= buf; DBUG_ENTER("read_buffpek_from_file"); if (count > UINT_MAX/sizeof(BUFFPEK)) return 0; /* sizeof(BUFFPEK)*count will overflow */ - tmp=(BUFFPEK*) my_malloc(length=sizeof(BUFFPEK)*count, MYF(MY_WME)); + if (!tmp) + tmp= (uchar *)my_malloc(length, MYF(MY_WME)); if (tmp) { if (reinit_io_cache(buffpek_pointers,READ_CACHE,0L,0,0) || diff --git a/sql/item.cc b/sql/item.cc index c33e5da0ca4..463de3e1c52 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -4460,7 +4460,7 @@ Field *Item::tmp_table_field_from_field_type(TABLE *table, bool fixed_length) break; case MYSQL_TYPE_NEWDATE: case MYSQL_TYPE_DATE: - field= new Field_date(maybe_null, name, &my_charset_bin); + field= new Field_newdate(maybe_null, name, &my_charset_bin); break; case MYSQL_TYPE_TIME: field= new Field_time(maybe_null, name, &my_charset_bin); @@ -6695,6 +6695,8 @@ enum_field_types Item_type_holder::get_real_type(Item *item) */ Field *field= ((Item_field *) item)->field; enum_field_types type= field->real_type(); + if (field->is_created_from_null_item) + return MYSQL_TYPE_NULL; /* work around about varchar type field detection */ if (type == MYSQL_TYPE_STRING && field->type() == MYSQL_TYPE_VAR_STRING) return MYSQL_TYPE_VAR_STRING; @@ -6948,6 +6950,8 @@ Field *Item_type_holder::make_field_by_type(TABLE *table) if (field) field->init(table); return field; + case MYSQL_TYPE_NULL: + return make_string_field(table); default: break; } diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 19c71cbc48d..91198d0fb7e 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -632,7 +632,7 @@ Field *Item_sum_hybrid::create_tmp_field(bool group, TABLE *table, */ switch (args[0]->field_type()) { case MYSQL_TYPE_DATE: - field= new Field_date(maybe_null, name, collation.collation); + field= new Field_newdate(maybe_null, name, collation.collation); break; case MYSQL_TYPE_TIME: field= new Field_time(maybe_null, name, collation.collation); @@ -2863,44 +2863,51 @@ String *Item_sum_udf_str::val_str(String *str) concat of values from "group by" operation BUGS - DISTINCT and ORDER BY only works if ORDER BY uses all fields and only fields - in expression list Blobs doesn't work with DISTINCT or ORDER BY *****************************************************************************/ -/** - function of sort for syntax: GROUP_CONCAT(DISTINCT expr,...) + + +/** + Compares the values for fields in expr list of GROUP_CONCAT. + @note + + GROUP_CONCAT([DISTINCT] expr [,expr ...] + [ORDER BY {unsigned_integer | col_name | expr} + [ASC | DESC] [,col_name ...]] + [SEPARATOR str_val]) + + @return + @retval -1 : key1 < key2 + @retval 0 : key1 = key2 + @retval 1 : key1 > key2 */ -int group_concat_key_cmp_with_distinct(void* arg, uchar* key1, - uchar* key2) +int group_concat_key_cmp_with_distinct(void* arg, const void* key1, + const void* key2) { - Item_func_group_concat* grp_item= (Item_func_group_concat*)arg; - TABLE *table= grp_item->table; - Item **field_item, **end; + Item_func_group_concat *item_func= (Item_func_group_concat*)arg; + TABLE *table= item_func->table; - for (field_item= grp_item->args, end= field_item + grp_item->arg_count_field; - field_item < end; - field_item++) + for (uint i= 0; i < item_func->arg_count_field; i++) { + Item *item= item_func->args[i]; + /* + If field_item is a const item then either get_tp_table_field returns 0 + or it is an item over a const table. + */ + if (item->const_item()) + continue; /* We have to use get_tmp_table_field() instead of real_item()->get_tmp_table_field() because we want the field in the temporary table, not the original field */ - Field *field= (*field_item)->get_tmp_table_field(); - /* - If field_item is a const item then either get_tmp_table_field returns 0 - or it is an item over a const table. - */ - if (field && !(*field_item)->const_item()) - { - int res; - uint offset= (field->offset(field->table->record[0]) - - table->s->null_bytes); - if ((res= field->cmp(key1 + offset, key2 + offset))) - return res; - } + Field *field= item->get_tmp_table_field(); + int res; + uint offset= field->offset(field->table->record[0])-table->s->null_bytes; + if((res= field->cmp((uchar*)key1 + offset, (uchar*)key2 + offset))) + return res; } return 0; } @@ -2910,7 +2917,8 @@ int group_concat_key_cmp_with_distinct(void* arg, uchar* key1, function of sort for syntax: GROUP_CONCAT(expr,... ORDER BY col,... ) */ -int group_concat_key_cmp_with_order(void* arg, uchar* key1, uchar* key2) +int group_concat_key_cmp_with_order(void* arg, const void* key1, + const void* key2) { Item_func_group_concat* grp_item= (Item_func_group_concat*) arg; ORDER **order_item, **end; @@ -2936,7 +2944,7 @@ int group_concat_key_cmp_with_order(void* arg, uchar* key1, uchar* key2) int res; uint offset= (field->offset(field->table->record[0]) - table->s->null_bytes); - if ((res= field->cmp(key1 + offset, key2 + offset))) + if ((res= field->cmp((uchar*)key1 + offset, (uchar*)key2 + offset))) return (*order_item)->asc ? res : -res; } } @@ -2950,25 +2958,6 @@ int group_concat_key_cmp_with_order(void* arg, uchar* key1, uchar* key2) /** - function of sort for syntax: - GROUP_CONCAT(DISTINCT expr,... ORDER BY col,... ). - - @bug - This doesn't work in the case when the order by contains data that - is not part of the field list because tree-insert will not notice - the duplicated values when inserting things sorted by ORDER BY -*/ - -int group_concat_key_cmp_with_distinct_and_order(void* arg,uchar* key1, - uchar* key2) -{ - if (!group_concat_key_cmp_with_distinct(arg,key1,key2)) - return 0; - return(group_concat_key_cmp_with_order(arg,key1,key2)); -} - - -/** Append data from current leaf to item->result. */ @@ -3054,7 +3043,7 @@ Item_func_group_concat(Name_resolution_context *context_arg, bool distinct_arg, List<Item> *select_list, SQL_LIST *order_list, String *separator_arg) :tmp_table_param(0), warning(0), - separator(separator_arg), tree(0), table(0), + separator(separator_arg), tree(0), unique_filter(NULL), table(0), order(0), context(context_arg), arg_count_order(order_list ? order_list->elements : 0), arg_count_field(select_list->elements), @@ -3109,6 +3098,7 @@ Item_func_group_concat::Item_func_group_concat(THD *thd, warning(item->warning), separator(item->separator), tree(item->tree), + unique_filter(item->unique_filter), table(item->table), order(item->order), context(item->context), @@ -3159,6 +3149,11 @@ void Item_func_group_concat::cleanup() delete_tree(tree); tree= 0; } + if (unique_filter) + { + delete unique_filter; + unique_filter= NULL; + } if (warning) { char warn_buff[MYSQL_ERRMSG_SIZE]; @@ -3188,6 +3183,8 @@ void Item_func_group_concat::clear() no_appended= TRUE; if (tree) reset_tree(tree); + if (distinct) + unique_filter->reset(); /* No need to reset the table as we never call write_row */ } @@ -3211,9 +3208,19 @@ bool Item_func_group_concat::add() } null_value= FALSE; + bool row_eligible= TRUE; + + if (distinct) + { + /* Filter out duplicate rows. */ + uint count= unique_filter->elements_in_tree(); + unique_filter->unique_add(table->record[0] + table->s->null_bytes); + if (count == unique_filter->elements_in_tree()) + row_eligible= FALSE; + } TREE_ELEMENT *el= 0; // Only for safety - if (tree) + if (row_eligible && tree) el= tree_insert(tree, table->record[0] + table->s->null_bytes, 0, tree->custom_arg); /* @@ -3221,7 +3228,7 @@ bool Item_func_group_concat::add() we can dump the row here in case of GROUP_CONCAT(DISTINCT...) instead of doing tree traverse later. */ - if (!warning_for_row && + if (row_eligible && !warning_for_row && (!tree || (el->count == 1 && distinct && !arg_count_order))) dump_leaf_key(table->record[0] + table->s->null_bytes, 1, this); @@ -3297,7 +3304,6 @@ bool Item_func_group_concat::setup(THD *thd) { List<Item> list; SELECT_LEX *select_lex= thd->lex->current_select; - qsort_cmp2 compare_key; DBUG_ENTER("Item_func_group_concat::setup"); /* @@ -3387,38 +3393,33 @@ bool Item_func_group_concat::setup(THD *thd) table->file->extra(HA_EXTRA_NO_ROWS); table->no_rows= 1; + /* + Need sorting or uniqueness: init tree and choose a function to sort. + Don't reserve space for NULLs: if any of gconcat arguments is NULL, + the row is not added to the result. + */ + uint tree_key_length= table->s->reclength - table->s->null_bytes; - if (distinct || arg_count_order) + if (arg_count_order) { - /* - Need sorting: init tree and choose a function to sort. - Don't reserve space for NULLs: if any of gconcat arguments is NULL, - the row is not added to the result. - */ - uint tree_key_length= table->s->reclength - table->s->null_bytes; - tree= &tree_base; - if (arg_count_order) - { - if (distinct) - compare_key= (qsort_cmp2) group_concat_key_cmp_with_distinct_and_order; - else - compare_key= (qsort_cmp2) group_concat_key_cmp_with_order; - } - else - { - compare_key= (qsort_cmp2) group_concat_key_cmp_with_distinct; - } /* - Create a tree for sorting. The tree is used to sort and to remove - duplicate values (according to the syntax of this function). If there - is no DISTINCT or ORDER BY clauses, we don't create this tree. + Create a tree for sorting. The tree is used to sort (according to the + syntax of this function). If there is no ORDER BY clause, we don't + create this tree. */ init_tree(tree, (uint) min(thd->variables.max_heap_table_size, thd->variables.sortbuff_size/16), 0, - tree_key_length, compare_key, 0, NULL, (void*) this); + tree_key_length, + group_concat_key_cmp_with_order , 0, NULL, (void*) this); } + if (distinct) + unique_filter= new Unique(group_concat_key_cmp_with_distinct, + (void*)this, + tree_key_length, + thd->variables.max_heap_table_size); + DBUG_RETURN(FALSE); } @@ -3488,3 +3489,10 @@ void Item_func_group_concat::print(String *str) str->append(*separator); str->append(STRING_WITH_LEN("\')")); } + + +Item_func_group_concat::~Item_func_group_concat() +{ + if (unique_filter) + delete unique_filter; +} diff --git a/sql/item_sum.h b/sql/item_sum.h index b3a382012f1..a3582967736 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -1173,11 +1173,22 @@ class Item_func_group_concat : public Item_sum String *separator; TREE tree_base; TREE *tree; + + /** + If DISTINCT is used with this GROUP_CONCAT, this member is used to filter + out duplicates. + @see Item_func_group_concat::setup + @see Item_func_group_concat::add + @see Item_func_group_concat::clear + */ + Unique *unique_filter; TABLE *table; ORDER **order; Name_resolution_context *context; - uint arg_count_order; // total count of ORDER BY items - uint arg_count_field; // count of arguments + /** The number of ORDER BY items. */ + uint arg_count_order; + /** The number of selected items, aka the expr list. */ + uint arg_count_field; uint count_cut_values; bool distinct; bool warning_for_row; @@ -1190,13 +1201,10 @@ class Item_func_group_concat : public Item_sum */ Item_func_group_concat *original; - friend int group_concat_key_cmp_with_distinct(void* arg, uchar* key1, - uchar* key2); - friend int group_concat_key_cmp_with_order(void* arg, uchar* key1, - uchar* key2); - friend int group_concat_key_cmp_with_distinct_and_order(void* arg, - uchar* key1, - uchar* key2); + friend int group_concat_key_cmp_with_distinct(void* arg, const void* key1, + const void* key2); + friend int group_concat_key_cmp_with_order(void* arg, const void* key1, + const void* key2); friend int dump_leaf_key(uchar* key, element_count count __attribute__((unused)), Item_func_group_concat *group_concat_item); @@ -1207,7 +1215,7 @@ public: SQL_LIST *is_order, String *is_separator); Item_func_group_concat(THD *thd, Item_func_group_concat *item); - ~Item_func_group_concat() {} + ~Item_func_group_concat(); void cleanup(); enum Sumfunctype sum_func () const {return GROUP_CONCAT_FUNC;} diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index ce760b8fd2a..a0beadcd481 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -3360,6 +3360,8 @@ bool Item_func_last_day::get_date(MYSQL_TIME *ltime, uint fuzzy_date) ltime->day= days_in_month[month_idx]; if ( month_idx == 1 && calc_days_in_year(ltime->year) == 366) ltime->day= 29; + ltime->hour= ltime->minute= ltime->second= 0; + ltime->second_part= 0; ltime->time_type= MYSQL_TIMESTAMP_DATE; return 0; } diff --git a/sql/log.cc b/sql/log.cc index ba457b3e10b..3a09acd8fca 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -3018,10 +3018,10 @@ err: void MYSQL_BIN_LOG::make_log_name(char* buf, const char* log_ident) { uint dir_len = dirname_length(log_file_name); - if (dir_len > FN_REFLEN) + if (dir_len >= FN_REFLEN) dir_len=FN_REFLEN-1; strnmov(buf, log_file_name, dir_len); - strmake(buf+dir_len, log_ident, FN_REFLEN - dir_len); + strmake(buf+dir_len, log_ident, FN_REFLEN - dir_len -1); } diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc index d33c81b55e8..589ee8b2605 100644 --- a/sql/repl_failsafe.cc +++ b/sql/repl_failsafe.cc @@ -946,7 +946,7 @@ bool load_master_data(THD* thd) 0, (SLAVE_IO | SLAVE_SQL))) my_message(ER_MASTER_INFO, ER(ER_MASTER_INFO), MYF(0)); strmake(active_mi->master_log_name, row[0], - sizeof(active_mi->master_log_name)); + sizeof(active_mi->master_log_name) -1); active_mi->master_log_pos= my_strtoll10(row[1], (char**) 0, &error_2); /* at least in recent versions, the condition below should be false */ if (active_mi->master_log_pos < BIN_LOG_HEADER_SIZE) diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 9e4dceff87d..41596b4faf2 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -6400,7 +6400,36 @@ find_item_in_list(Item *find, List<Item> &items, uint *counter, *resolution= RESOLVED_IGNORING_ALIAS; break; } - } + } + else if (table_name && item->type() == Item::REF_ITEM && + ((Item_ref *)item)->ref_type() == Item_ref::VIEW_REF) + { + /* + TODO:Here we process prefixed view references only. What we should + really do is process all types of Item_refs. But this will currently + lead to a clash with the way references to outer SELECTs (from the + HAVING clause) are handled in e.g. : + SELECT 1 FROM t1 AS t1_o GROUP BY a + HAVING (SELECT t1_o.a FROM t1 AS t1_i GROUP BY t1_i.a LIMIT 1). + Processing all Item_refs here will cause t1_o.a to resolve to itself. + We still need to process the special case of Item_direct_view_ref + because in the context of views they have the same meaning as + Item_field for tables. + */ + Item_ident *item_ref= (Item_ident *) item; + if (item_ref->name && item_ref->table_name && + !my_strcasecmp(system_charset_info, item_ref->name, field_name) && + !my_strcasecmp(table_alias_charset, item_ref->table_name, + table_name) && + (!db_name || (item_ref->db_name && + !strcmp (item_ref->db_name, db_name)))) + { + found= li.ref(); + *counter= i; + *resolution= RESOLVED_IGNORING_ALIAS; + break; + } + } } if (!found) { diff --git a/sql/sql_db.cc b/sql/sql_db.cc index f158b5488d0..b5f49b97ec9 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -1396,7 +1396,7 @@ static void backup_current_db_name(THD *thd, } else { - strmake(saved_db_name->str, thd->db, saved_db_name->length); + strmake(saved_db_name->str, thd->db, saved_db_name->length - 1); saved_db_name->length= thd->db_length; } } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index c735f70529e..d77fa6bbb04 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -9341,6 +9341,8 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table, *((*copy_func)++) = item; // Save for copy_funcs if (modify_item) item->set_result_field(new_field); + if (item->type() == Item::NULL_ITEM) + new_field->is_created_from_null_item= TRUE; return new_field; } diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 9fa4f8585f5..9cccc7c724e 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -6162,6 +6162,14 @@ select_paren: my_parse_error(ER(ER_SYNTAX_ERROR)); MYSQL_YYABORT; } + if (sel->linkage == UNION_TYPE && + sel->olap != UNSPECIFIED_OLAP_TYPE && + sel->master_unit()->fake_select_lex) + { + my_error(ER_WRONG_USAGE, MYF(0), + "CUBE/ROLLUP", "ORDER BY"); + MYSQL_YYABORT; + } /* select in braces, can't contain global parameters */ if (sel->master_unit()->fake_select_lex) sel->master_unit()->global_parameters= @@ -8050,7 +8058,8 @@ order_clause: SELECT_LEX *sel= lex->current_select; SELECT_LEX_UNIT *unit= sel-> master_unit(); if (sel->linkage != GLOBAL_OPTIONS_TYPE && - sel->olap != UNSPECIFIED_OLAP_TYPE) + sel->olap != UNSPECIFIED_OLAP_TYPE && + (sel->linkage != UNION_TYPE || sel->braces)) { my_error(ER_WRONG_USAGE, MYF(0), "CUBE/ROLLUP", "ORDER BY"); diff --git a/sql/unireg.cc b/sql/unireg.cc index dbdefd8d5b1..aab3f5606a8 100644 --- a/sql/unireg.cc +++ b/sql/unireg.cc @@ -227,6 +227,14 @@ bool mysql_create_frm(THD *thd, const char *file_name, strmake((char*) forminfo+47, create_info->comment.str ? create_info->comment.str : "", create_info->comment.length); forminfo[46]=(uchar) create_info->comment.length; +#ifdef EXTRA_DEBUG + /* + EXTRA_DEBUG causes strmake() to initialize its buffer behind the + payload with a magic value to detect wrong buffer-sizes. We + explicitly zero that segment again. + */ + memset((char*) forminfo+47 + forminfo[46], 0, 61 - forminfo[46]); +#endif #ifdef WITH_PARTITION_STORAGE_ENGINE if (part_info) { |