summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/field.h2
-rw-r--r--sql/filesort.cc1
-rw-r--r--sql/item.cc1
-rw-r--r--sql/item_sum.cc22
-rw-r--r--sql/mysql_priv.h3
-rw-r--r--sql/sql_lex.cc3
-rw-r--r--sql/sql_select.cc2
-rw-r--r--sql/sql_yacc.yy8
-rw-r--r--sql/unireg.cc60
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