summaryrefslogtreecommitdiff
path: root/sql/item.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/item.cc')
-rw-r--r--sql/item.cc34
1 files changed, 25 insertions, 9 deletions
diff --git a/sql/item.cc b/sql/item.cc
index ad8b79182d4..27cb6d49fd4 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -1424,7 +1424,8 @@ bool agg_item_charsets(DTCollation &coll, const char *fname,
In case we're in statement prepare, create conversion item
in its memory: it will be reused on each execute.
*/
- arena= thd->activate_stmt_arena_if_needed(&backup);
+ arena= thd->is_stmt_prepare() ? thd->activate_stmt_arena_if_needed(&backup)
+ : NULL;
for (i= 0, arg= args; i < nargs; i++, arg+= item_sep)
{
@@ -1459,7 +1460,7 @@ bool agg_item_charsets(DTCollation &coll, const char *fname,
been created in prepare. In this case register the change for
rollback.
*/
- if (arena && arena->is_conventional())
+ if (arena)
*arg= conv;
else
thd->change_item_tree(arg, conv);
@@ -3903,7 +3904,9 @@ Field *Item::make_string_field(TABLE *table)
if (max_length/collation.collation->mbmaxlen > CONVERT_IF_BIGGER_TO_BLOB)
return new Field_blob(max_length, maybe_null, name, table,
collation.collation);
- if (max_length > 0)
+ /* Item_type_holder holds the exact type, do not change it */
+ if (max_length > 0 &&
+ (type() != Item::TYPE_HOLDER || field_type() != MYSQL_TYPE_STRING))
return new Field_varstring(max_length, maybe_null, name, table,
collation.collation);
return new Field_string(max_length, maybe_null, name, table,
@@ -3967,6 +3970,7 @@ Field *Item::tmp_table_field_from_field_type(TABLE *table)
case MYSQL_TYPE_TIME:
return new Field_time(maybe_null, name, table, &my_charset_bin);
case MYSQL_TYPE_TIMESTAMP:
+ return new Field_timestamp(maybe_null, name, table, &my_charset_bin);
case MYSQL_TYPE_DATETIME:
return new Field_datetime(maybe_null, name, table, &my_charset_bin);
case MYSQL_TYPE_YEAR:
@@ -3990,7 +3994,11 @@ Field *Item::tmp_table_field_from_field_type(TABLE *table)
case MYSQL_TYPE_LONG_BLOB:
case MYSQL_TYPE_BLOB:
case MYSQL_TYPE_GEOMETRY:
- return new Field_blob(max_length, maybe_null, name, table,
+ if (this->type() == Item::TYPE_HOLDER)
+ return new Field_blob(max_length, maybe_null, name, table,
+ collation.collation, 1);
+ else
+ return new Field_blob(max_length, maybe_null, name, table,
collation.collation);
break; // Blob handled outside of case
}
@@ -6053,14 +6061,13 @@ bool Item_type_holder::join_types(THD *thd, Item *item)
max_length= my_decimal_precision_to_length(precision, decimals,
unsigned_flag);
}
- else
- max_length= max(max_length, display_length(item));
-
+
switch (Field::result_merge_type(fld_type))
{
case STRING_RESULT:
{
const char *old_cs, *old_derivation;
+ uint32 old_max_chars= max_length / collation.collation->mbmaxlen;
old_cs= collation.collation->name;
old_derivation= collation.derivation_name();
if (collation.aggregate(item->collation, MY_COLL_ALLOW_CONV))
@@ -6072,6 +6079,14 @@ bool Item_type_holder::join_types(THD *thd, Item *item)
"UNION");
DBUG_RETURN(TRUE);
}
+ /*
+ To figure out max_length, we have to take into account possible
+ expansion of the size of the values because of character set
+ conversions.
+ */
+ max_length= max(old_max_chars * collation.collation->mbmaxlen,
+ display_length(item) / item->collation.collation->mbmaxlen *
+ collation.collation->mbmaxlen);
break;
}
case REAL_RESULT:
@@ -6090,7 +6105,8 @@ bool Item_type_holder::join_types(THD *thd, Item *item)
max_length= (fld_type == MYSQL_TYPE_FLOAT) ? FLT_DIG+6 : DBL_DIG+7;
break;
}
- default:;
+ default:
+ max_length= max(max_length, display_length(item));
};
maybe_null|= item->maybe_null;
get_full_info(item);
@@ -6151,7 +6167,7 @@ uint32 Item_type_holder::display_length(Item *item)
case MYSQL_TYPE_DOUBLE:
return 53;
case MYSQL_TYPE_NULL:
- return 4;
+ return 0;
case MYSQL_TYPE_LONGLONG:
return 20;
case MYSQL_TYPE_INT24: