diff options
Diffstat (limited to 'sql')
-rw-r--r-- | sql/field.h | 2 | ||||
-rw-r--r-- | sql/filesort.cc | 1 | ||||
-rw-r--r-- | sql/item.cc | 1 | ||||
-rw-r--r-- | sql/item_sum.cc | 22 | ||||
-rw-r--r-- | sql/mysql_priv.h | 3 | ||||
-rw-r--r-- | sql/sql_lex.cc | 3 | ||||
-rw-r--r-- | sql/sql_select.cc | 2 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 8 | ||||
-rw-r--r-- | sql/unireg.cc | 60 |
9 files changed, 79 insertions, 23 deletions
diff --git a/sql/field.h b/sql/field.h index fce3b51c04b..a9ba57580b7 100644 --- a/sql/field.h +++ b/sql/field.h @@ -1476,6 +1476,8 @@ public: uint decimals, flags, pack_length, key_length; Field::utype unireg_check; TYPELIB *interval; // Which interval to use + TYPELIB *save_interval; // Temporary copy for the above + // Used only for UCS2 intervals List<String> interval_list; CHARSET_INFO *charset; Field::geometry_type geom_type; diff --git a/sql/filesort.cc b/sql/filesort.cc index 1851d5a5cff..dcea2d328af 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -1344,6 +1344,7 @@ sortlength(THD *thd, SORT_FIELD *sortorder, uint s_length, switch ((sortorder->result_type=sortorder->item->result_type())) { case STRING_RESULT: sortorder->length=sortorder->item->max_length; + set_if_smaller(sortorder->length, thd->variables.max_sort_length); if (use_strnxfrm((cs=sortorder->item->collation.collation))) { sortorder->length= cs->coll->strnxfrmlen(cs, sortorder->length); diff --git a/sql/item.cc b/sql/item.cc index 62292a38245..920eefdb449 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1210,6 +1210,7 @@ void Item::split_sum_func2(THD *thd, Item **ref_pointer_array, split_sum_func(thd, ref_pointer_array, fields); } else if ((type() == SUM_FUNC_ITEM || (used_tables() & ~PARAM_TABLE_BIT)) && + type() != SUBSELECT_ITEM && (type() != REF_ITEM || ((Item_ref*)this)->ref_type() == Item_ref::VIEW_REF)) { diff --git a/sql/item_sum.cc b/sql/item_sum.cc index cf122f565ff..73e2c5e6935 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -246,7 +246,27 @@ bool Item_sum::register_sum_func(THD *thd, Item **ref) aggr_sl->inner_sum_func_list->next= this; } aggr_sl->inner_sum_func_list= this; - + aggr_sl->with_sum_func= 1; + + /* + Mark Item_subselect(s) as containing aggregate function all the way up + to aggregate function's calculation context. + Note that we must not mark the Item of calculation context itself + because with_sum_func on the calculation context st_select_lex is + already set above. + + with_sum_func being set for an Item means that this Item refers + (somewhere in it, e.g. one of its arguments if it's a function) directly + or through intermediate items to an aggregate function that is calculated + in a context "outside" of the Item (e.g. in the current or outer select). + + with_sum_func being set for an st_select_lex means that this st_select_lex + has aggregate functions directly referenced (i.e. not through a sub-select). + */ + for (sl= thd->lex->current_select; + sl && sl != aggr_sl && sl->master_unit()->item; + sl= sl->master_unit()->outer_select() ) + sl->master_unit()->item->with_sum_func= 1; } return FALSE; } diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index f232aca3811..4c9f6286542 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -455,7 +455,8 @@ enum enum_parsing_place NO_MATTER, IN_HAVING, SELECT_LIST, - IN_WHERE + IN_WHERE, + IN_ON }; struct st_table; diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 3f3fde03bce..d94c45c4bdd 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1722,7 +1722,8 @@ bool st_lex::can_be_merged() unit= unit->next_unit()) { if (unit->first_select()->parent_lex == this && - (unit->item == 0 || unit->item->place() != IN_WHERE)) + (unit->item == 0 || + (unit->item->place() != IN_WHERE && unit->item->place() != IN_ON))) { selects_allow_merge= 0; break; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 9a05aa7da04..f247bfe7b14 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -11875,8 +11875,6 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, We must not try to use disabled keys. */ usable_keys= table->s->keys_in_use; - /* we must not consider keys that are disabled by IGNORE INDEX */ - usable_keys.intersect(table->keys_in_use_for_query); for (ORDER *tmp_order=order; tmp_order ; tmp_order=tmp_order->next) { diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 4aab923d8c0..435cb5d4765 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -6847,11 +6847,13 @@ join_table: /* Change the current name resolution context to a local context. */ if (push_new_name_resolution_context(YYTHD, $1, $3)) YYABORT; + Select->parsing_place= IN_ON; } expr { add_join_on($3,$6); Lex->pop_context(); + Select->parsing_place= NO_MATTER; } | table_ref STRAIGHT_JOIN table_factor ON @@ -6860,12 +6862,14 @@ join_table: /* Change the current name resolution context to a local context. */ if (push_new_name_resolution_context(YYTHD, $1, $3)) YYABORT; + Select->parsing_place= IN_ON; } expr { $3->straight=1; add_join_on($3,$6); Lex->pop_context(); + Select->parsing_place= NO_MATTER; } | table_ref normal_join table_ref USING @@ -6889,6 +6893,7 @@ join_table: /* Change the current name resolution context to a local context. */ if (push_new_name_resolution_context(YYTHD, $1, $5)) YYABORT; + Select->parsing_place= IN_ON; } expr { @@ -6896,6 +6901,7 @@ join_table: Lex->pop_context(); $5->outer_join|=JOIN_TYPE_LEFT; $$=$5; + Select->parsing_place= NO_MATTER; } | table_ref LEFT opt_outer JOIN_SYM table_factor { @@ -6920,6 +6926,7 @@ join_table: /* Change the current name resolution context to a local context. */ if (push_new_name_resolution_context(YYTHD, $1, $5)) YYABORT; + Select->parsing_place= IN_ON; } expr { @@ -6928,6 +6935,7 @@ join_table: YYABORT; add_join_on($$, $8); Lex->pop_context(); + Select->parsing_place= NO_MATTER; } | table_ref RIGHT opt_outer JOIN_SYM table_factor { diff --git a/sql/unireg.cc b/sql/unireg.cc index 396ff4fba27..11d974e644e 100644 --- a/sql/unireg.cc +++ b/sql/unireg.cc @@ -292,13 +292,19 @@ bool mysql_create_frm(THD *thd, const char *file_name, goto err3; { - /* Unescape all UCS2 intervals: were escaped in pack_headers */ + /* + Restore all UCS2 intervals. + HEX representation of them is not needed anymore. + */ List_iterator<create_field> it(create_fields); create_field *field; while ((field=it++)) { - if (field->interval && field->charset->mbminlen > 1) - unhex_type2(field->interval); + if (field->save_interval) + { + field->interval= field->save_interval; + field->save_interval= 0; + } } } DBUG_RETURN(0); @@ -589,18 +595,36 @@ static bool pack_header(uchar *forminfo, enum legacy_db_type table_type, reclength=(uint) (field->offset+ data_offset + length); n_length+= (ulong) strlen(field->field_name)+1; field->interval_id=0; + field->save_interval= 0; if (field->interval) { uint old_int_count=int_count; if (field->charset->mbminlen > 1) { - /* Escape UCS2 intervals using HEX notation */ + /* + Escape UCS2 intervals using HEX notation to avoid + problems with delimiters between enum elements. + As the original representation is still needed in + the function make_empty_rec to create a record of + filled with default values it is saved in save_interval + The HEX representation is created from this copy. + */ + field->save_interval= field->interval; + field->interval= (TYPELIB*) sql_alloc(sizeof(TYPELIB)); + *field->interval= *field->save_interval; + field->interval->type_names= + (const char **) sql_alloc(sizeof(char*) * + (field->interval->count+1)); + field->interval->type_names[field->interval->count]= 0; + field->interval->type_lengths= + (uint *) sql_alloc(sizeof(uint) * field->interval->count); + for (uint pos= 0; pos < field->interval->count; pos++) { char *dst; - uint length= field->interval->type_lengths[pos], hex_length; - const char *src= field->interval->type_names[pos]; + uint length= field->save_interval->type_lengths[pos], hex_length; + const char *src= field->save_interval->type_names[pos]; hex_length= length * 2; field->interval->type_lengths[pos]= hex_length; field->interval->type_names[pos]= dst= sql_alloc(hex_length + 1); @@ -842,18 +866,18 @@ static bool make_empty_rec(THD *thd, File file,enum legacy_db_type table_type, /* regfield don't have to be deleted as it's allocated with sql_alloc() */ - Field *regfield= make_field(&share, - (char*) buff+field->offset + data_offset, - field->length, - null_pos + null_count / 8, - null_count & 7, - field->pack_flag, - field->sql_type, - field->charset, - field->geom_type, - field->unireg_check, - field->interval, - field->field_name); + Field *regfield=make_field((char*) buff+field->offset + data_offset, + field->length, + null_pos + null_count / 8, + null_count & 7, + field->pack_flag, + field->sql_type, + field->charset, + field->geom_type, + field->unireg_check, + field->save_interval ? field->save_interval : + field->interval, + field->field_name); if (!regfield) goto err; // End of memory |