summaryrefslogtreecommitdiff
path: root/sql/item.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/item.cc')
-rw-r--r--sql/item.cc462
1 files changed, 313 insertions, 149 deletions
diff --git a/sql/item.cc b/sql/item.cc
index e3e17a3ceea..1dac5ed8c78 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -56,7 +56,7 @@ Hybrid_type_traits::val_decimal(Hybrid_type *val, my_decimal *to) const
String *
Hybrid_type_traits::val_str(Hybrid_type *val, String *to, uint8 decimals) const
{
- to->set(val->real, decimals, &my_charset_bin);
+ to->set_real(val->real, decimals, &my_charset_bin);
return to;
}
@@ -161,6 +161,7 @@ Hybrid_type_traits_integer::fix_length_and_dec(Item *item, Item *arg) const
void item_init(void)
{
item_user_lock_init();
+ uuid_short_init();
}
@@ -197,7 +198,7 @@ String *Item::val_string_from_real(String *str)
double nr= val_real();
if (null_value)
return 0; /* purecov: inspected */
- str->set(nr,decimals, &my_charset_bin);
+ str->set_real(nr,decimals, &my_charset_bin);
return str;
}
@@ -207,10 +208,7 @@ String *Item::val_string_from_int(String *str)
longlong nr= val_int();
if (null_value)
return 0;
- if (unsigned_flag)
- str->set((ulonglong) nr, &my_charset_bin);
- else
- str->set(nr, &my_charset_bin);
+ str->set_int(nr, unsigned_flag, &my_charset_bin);
return str;
}
@@ -466,7 +464,7 @@ void Item::cleanup()
arg - a dummy parameter, is not used here
*/
-bool Item::cleanup_processor(byte *arg)
+bool Item::cleanup_processor(uchar *arg)
{
if (fixed)
cleanup();
@@ -529,7 +527,7 @@ void Item::rename(char *new_name)
pointer to newly allocated item is returned.
*/
-Item* Item::transform(Item_transformer transformer, byte *arg)
+Item* Item::transform(Item_transformer transformer, uchar *arg)
{
DBUG_ASSERT(!current_thd->is_stmt_prepare());
@@ -587,7 +585,7 @@ void Item_ident::cleanup()
DBUG_VOID_RETURN;
}
-bool Item_ident::remove_dependence_processor(byte * arg)
+bool Item_ident::remove_dependence_processor(uchar * arg)
{
DBUG_ENTER("Item_ident::remove_dependence_processor");
if (depended_from == (st_select_lex *) arg)
@@ -618,7 +616,7 @@ bool Item_ident::remove_dependence_processor(byte * arg)
for the subsequent items.
*/
-bool Item_field::collect_item_field_processor(byte *arg)
+bool Item_field::collect_item_field_processor(uchar *arg)
{
DBUG_ENTER("Item_field::collect_item_field_processor");
DBUG_PRINT("info", ("%s", field->field_name ? field->field_name : "noname"));
@@ -653,7 +651,7 @@ bool Item_field::collect_item_field_processor(byte *arg)
FALSE otherwise
*/
-bool Item_field::find_item_in_field_list_processor(byte *arg)
+bool Item_field::find_item_in_field_list_processor(uchar *arg)
{
KEY_PART_INFO *first_non_group_part= *((KEY_PART_INFO **) arg);
KEY_PART_INFO *last_part= *(((KEY_PART_INFO **) arg) + 1);
@@ -668,6 +666,23 @@ bool Item_field::find_item_in_field_list_processor(byte *arg)
}
+/*
+ Mark field in read_map
+
+ NOTES
+ This is used by filesort to register used fields in a a temporary
+ column read set or to register used fields in a view
+*/
+
+bool Item_field::register_field_in_read_map(uchar *arg)
+{
+ TABLE *table= (TABLE *) arg;
+ if (field->table == table || !table)
+ bitmap_set_bit(field->table->read_set, field->field_index);
+ return 0;
+}
+
+
bool Item::check_cols(uint c)
{
if (c != 1)
@@ -714,7 +729,7 @@ void Item::set_name(const char *str, uint length, CHARSET_INFO *cs)
}
if (!my_charset_same(cs, system_charset_info))
{
- uint32 res_length;
+ size_t res_length;
name= sql_strmake_with_convert(str, name_length= length, cs,
MAX_ALIAS_NAME, system_charset_info,
&res_length);
@@ -794,6 +809,7 @@ Item *Item_string::safe_charset_converter(CHARSET_INFO *tocs)
{
Item_string *conv;
uint conv_errors;
+ char *ptr;
String tmp, cstr, *ostr= val_str(&tmp);
cstr.copy(ostr->ptr(), ostr->length(), ostr->charset(), tocs, &conv_errors);
if (conv_errors || !(conv= new Item_string(cstr.ptr(), cstr.length(),
@@ -808,7 +824,9 @@ Item *Item_string::safe_charset_converter(CHARSET_INFO *tocs)
*/
return NULL;
}
- conv->str_value.copy();
+ if (!(ptr= current_thd->strmake(cstr.ptr(), cstr.length())))
+ return NULL;
+ conv->str_value.set(ptr, cstr.length(), cstr.charset());
/* Ensure that no one is going to change the result string */
conv->str_value.mark_as_const();
return conv;
@@ -934,16 +952,27 @@ CHARSET_INFO *Item::default_charset()
}
+/*
+ Save value in field, but don't give any warnings
+
+ NOTES
+ This is used to temporary store and retrieve a value in a column,
+ for example in opt_range to adjust the key value to fit the column.
+*/
+
int Item::save_in_field_no_warnings(Field *field, bool no_conversions)
{
int res;
- THD *thd= field->table->in_use;
+ TABLE *table= field->table;
+ THD *thd= table->in_use;
enum_check_fields tmp= thd->count_cuted_fields;
+ my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->write_set);
ulong sql_mode= thd->variables.sql_mode;
thd->variables.sql_mode&= ~(MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE);
thd->count_cuted_fields= CHECK_FIELD_IGNORE;
res= save_in_field(field, no_conversions);
thd->count_cuted_fields= tmp;
+ dbug_tmp_restore_column_map(table->write_set, old_map);
thd->variables.sql_mode= sql_mode;
return res;
}
@@ -1120,8 +1149,8 @@ bool Item_splocal::set_value(THD *thd, sp_rcontext *ctx, Item **it)
Item_case_expr methods
*****************************************************************************/
-Item_case_expr::Item_case_expr(int case_expr_id)
- :Item_sp_variable((char *) STRING_WITH_LEN("case_expr")),
+Item_case_expr::Item_case_expr(uint case_expr_id)
+ :Item_sp_variable( C_STRING_WITH_LEN("case_expr")),
m_case_expr_id(case_expr_id)
{
}
@@ -1157,6 +1186,8 @@ Item_case_expr::this_item_addr(THD *thd, Item **)
void Item_case_expr::print(String *str)
{
+ if (str->reserve(MAX_INT_WIDTH + sizeof("case_expr@")))
+ return; /* purecov: inspected */
VOID(str->append(STRING_WITH_LEN("case_expr@")));
str->qs_append(m_case_expr_id);
}
@@ -1209,7 +1240,17 @@ bool Item_name_const::is_null()
Item::Type Item_name_const::type() const
{
- return value_item->type();
+ /*
+ As
+ 1. one can try to create the Item_name_const passing non-constant
+ arguments, although it's incorrect and
+ 2. the type() method can be called before the fix_fields() to get
+ type information for a further type cast, e.g.
+ if (item->type() == FIELD_ITEM)
+ ((Item_field *) item)->...
+ we return NULL_ITEM in the case to avoid wrong casting.
+ */
+ return valid_args ? value_item->type() : NULL_ITEM;
}
@@ -1221,14 +1262,14 @@ bool Item_name_const::fix_fields(THD *thd, Item **ref)
s.length(0);
if (value_item->fix_fields(thd, &value_item) ||
- name_item->fix_fields(thd, &name_item))
- return TRUE;
- if (!(value_item->const_item() && name_item->const_item()))
+ name_item->fix_fields(thd, &name_item) ||
+ !value_item->const_item() ||
+ !name_item->const_item() ||
+ !(item_name= name_item->val_str(&s))) // Can't have a NULL name
+ {
+ my_error(ER_RESERVED_SYNTAX, MYF(0), "NAME_CONST");
return TRUE;
-
- if (!(item_name= name_item->val_str(&s)))
- return TRUE; /* Can't have a NULL name */
-
+ }
set_name(item_name->ptr(), (uint) item_name->length(), system_charset_info);
max_length= value_item->max_length;
decimals= value_item->decimals;
@@ -1588,6 +1629,10 @@ bool agg_item_charsets(DTCollation &coll, const char *fname,
Item **args, uint nargs, uint flags, int item_sep)
{
Item **arg, *safe_args[2];
+
+ LINT_INIT(safe_args[0]);
+ LINT_INIT(safe_args[1]);
+
if (agg_item_collations(coll, fname, args, nargs, flags, item_sep))
return TRUE;
@@ -1654,7 +1699,7 @@ bool agg_item_charsets(DTCollation &coll, const char *fname,
been created in prepare. In this case register the change for
rollback.
*/
- if (arena)
+ if (thd->is_stmt_prepare())
*arg= conv;
else
thd->change_item_tree(arg, conv);
@@ -1687,20 +1732,21 @@ void Item_ident_for_show::make_field(Send_field *tmp_field)
Item_field::Item_field(Field *f)
:Item_ident(0, NullS, *f->table_name, f->field_name),
- item_equal(0), no_const_subst(0),
+ item_equal(0), no_const_subst(0),
have_privileges(0), any_privileges(0)
{
set_field(f);
/*
- field_name and talbe_name should not point to garbage
+ field_name and table_name should not point to garbage
if this item is to be reused
*/
orig_table_name= orig_field_name= "";
}
+
Item_field::Item_field(THD *thd, Name_resolution_context *context_arg,
Field *f)
- :Item_ident(context_arg, f->table->s->db, *f->table_name, f->field_name),
+ :Item_ident(context_arg, f->table->s->db.str, *f->table_name, f->field_name),
item_equal(0), no_const_subst(0),
have_privileges(0), any_privileges(0)
{
@@ -1770,7 +1816,7 @@ void Item_field::set_field(Field *field_par)
max_length= field_par->max_display_length();
table_name= *field_par->table_name;
field_name= field_par->field_name;
- db_name= field_par->table->s->db;
+ db_name= field_par->table->s->db.str;
alias_name_used= field_par->table->alias_name_used;
unsigned_flag=test(field_par->flags & UNSIGNED_FLAG);
collation.set(field_par->charset(), field_par->derivation());
@@ -2043,6 +2089,11 @@ Item *Item_field::get_tmp_table_item(THD *thd)
return new_item;
}
+longlong Item_field::val_int_endpoint(bool left_endp, bool *incl_endp)
+{
+ longlong res= val_int();
+ return null_value? LONGLONG_MIN : res;
+}
/*
Create an item from a string we KNOW points to a valid longlong
@@ -2166,7 +2217,7 @@ Item_decimal::Item_decimal(my_decimal *value_par)
}
-Item_decimal::Item_decimal(const char *bin, int precision, int scale)
+Item_decimal::Item_decimal(const uchar *bin, int precision, int scale)
{
binary2my_decimal(E_DEC_FATAL_ERROR, bin,
&decimal_value, precision, scale);
@@ -2237,7 +2288,7 @@ String *Item_float::val_str(String *str)
{
// following assert is redundant, because fixed=1 assigned in constructor
DBUG_ASSERT(fixed == 1);
- str->set(value,decimals,&my_charset_bin);
+ str->set_real(value,decimals,&my_charset_bin);
return str;
}
@@ -2374,7 +2425,7 @@ default_set_param_func(Item_param *param,
}
-Item_param::Item_param(unsigned pos_in_query_arg) :
+Item_param::Item_param(uint pos_in_query_arg) :
strict_type(FALSE),
state(NO_VALUE),
item_result_type(STRING_RESULT),
@@ -2587,7 +2638,8 @@ bool Item_param::set_from_user_var(THD *thd, const user_var_entry *entry)
CHARSET_INFO *tocs= thd->variables.collation_connection;
uint32 dummy_offset;
- value.cs_info.character_set_of_placeholder= fromcs;
+ value.cs_info.character_set_of_placeholder=
+ value.cs_info.character_set_client= fromcs;
/*
Setup source and destination character sets so that they
are different only if conversion is necessary: this will
@@ -2828,7 +2880,7 @@ String *Item_param::val_str(String* str)
case LONG_DATA_VALUE:
return &str_value_ptr;
case REAL_VALUE:
- str->set(value.real, NOT_FIXED_DEC, &my_charset_bin);
+ str->set_real(value.real, NOT_FIXED_DEC, &my_charset_bin);
return str;
case INT_VALUE:
str->set(value.integer, &my_charset_bin);
@@ -2868,7 +2920,7 @@ const String *Item_param::query_val_str(String* str) const
str->set(value.integer, &my_charset_bin);
break;
case REAL_VALUE:
- str->set(value.real, NOT_FIXED_DEC, &my_charset_bin);
+ str->set_real(value.real, NOT_FIXED_DEC, &my_charset_bin);
break;
case DECIMAL_VALUE:
if (my_decimal2string(E_DEC_FATAL_ERROR, &decimal_value,
@@ -3356,7 +3408,7 @@ static Item** find_field_in_group_list(Item *find_item, ORDER *group_list)
resolve_ref_in_select_and_group()
thd current thread
ref column reference being resolved
- select the sub-select that ref is resolved against
+ select the select that ref is resolved against
DESCRIPTION
Resolve a column reference (usually inside a HAVING clause) against the
@@ -3427,6 +3479,7 @@ resolve_ref_in_select_and_group(THD *thd, Item_ident *ref, SELECT_LEX *select)
}
if (thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY &&
+ select->having_fix_field &&
select_ref != not_found_item && !group_by_ref)
{
/*
@@ -3821,7 +3874,9 @@ bool Item_field::fix_fields(THD *thd, Item **reference)
context->first_name_resolution_table,
context->last_name_resolution_table,
reference,
- IGNORE_EXCEPT_NON_UNIQUE,
+ thd->lex->use_only_table_context ?
+ REPORT_ALL_ERRORS :
+ IGNORE_EXCEPT_NON_UNIQUE,
!any_privileges,
TRUE)) ==
not_found_field)
@@ -3844,15 +3899,15 @@ bool Item_field::fix_fields(THD *thd, Item **reference)
if ((*res)->type() == Item::FIELD_ITEM)
{
/*
- It's an Item_field referencing another Item_field in the select
- list.
- use the field from the Item_field in the select list and leave
- the Item_field instance in place.
+ It's an Item_field referencing another Item_field in the select
+ list.
+ Use the field from the Item_field in the select list and leave
+ the Item_field instance in place.
*/
- Field *field= (*((Item_field**)res))->field;
+ Field *new_field= (*((Item_field**)res))->field;
- if (field == NULL)
+ if (new_field == NULL)
{
/* The column to which we link isn't valid. */
my_error(ER_BAD_FIELD_ERROR, MYF(0), (*res)->name,
@@ -3860,7 +3915,7 @@ bool Item_field::fix_fields(THD *thd, Item **reference)
return(1);
}
- set_field(field);
+ set_field(new_field);
return 0;
}
else
@@ -3892,11 +3947,23 @@ bool Item_field::fix_fields(THD *thd, Item **reference)
else if (!from_field)
goto error;
+ if (!outer_fixed && cached_table && cached_table->select_lex &&
+ context->select_lex &&
+ cached_table->select_lex != context->select_lex)
+ {
+ int ret;
+ if ((ret= fix_outer_field(thd, &from_field, reference)) < 0)
+ goto error;
+ if (!ret)
+ return FALSE;
+ outer_fixed= 1;
+ }
+
/*
if it is not expression from merged VIEW we will set this field.
We can leave expression substituted from view for next PS/SP rexecution
- (i.e. do not register this substitution for reverting on cleupup()
+ (i.e. do not register this substitution for reverting on cleanup()
(register_item_tree_changing())), because this subtree will be
fix_field'ed during setup_tables()->setup_underlying() (i.e. before
all other expressions of query, and references on tables which do
@@ -3907,18 +3974,6 @@ bool Item_field::fix_fields(THD *thd, Item **reference)
if (from_field == view_ref_found)
return FALSE;
- if (!outer_fixed && cached_table && cached_table->select_lex &&
- context->select_lex &&
- cached_table->select_lex != context->select_lex)
- {
- int ret;
- if ((ret= fix_outer_field(thd, &from_field, reference)) < 0)
- goto error;
- else if (!ret)
- return FALSE;
- outer_fixed= 1;
- }
-
set_field(from_field);
if (thd->lex->in_sum_func &&
thd->lex->in_sum_func->nest_level ==
@@ -3926,13 +3981,31 @@ bool Item_field::fix_fields(THD *thd, Item **reference)
set_if_bigger(thd->lex->in_sum_func->max_arg_level,
thd->lex->current_select->nest_level);
}
- else if (thd->set_query_id && field->query_id != thd->query_id)
+ else if (thd->mark_used_columns != MARK_COLUMNS_NONE)
{
- /* We only come here in unions */
- TABLE *table=field->table;
- field->query_id=thd->query_id;
- table->used_fields++;
- table->used_keys.intersect(field->part_of_key);
+ TABLE *table= field->table;
+ MY_BITMAP *current_bitmap, *other_bitmap;
+ if (thd->mark_used_columns == MARK_COLUMNS_READ)
+ {
+ current_bitmap= table->read_set;
+ other_bitmap= table->write_set;
+ }
+ else
+ {
+ current_bitmap= table->write_set;
+ other_bitmap= table->read_set;
+ }
+ if (!bitmap_fast_test_and_set(current_bitmap, field->field_index))
+ {
+ if (!bitmap_is_set(other_bitmap, field->field_index))
+ {
+ /* First usage of column */
+ table->used_fields++; // Used to optimize loops
+ /* purecov: begin inspected */
+ table->covering_keys.intersect(field->part_of_key);
+ /* purecov: end */
+ }
+ }
}
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (any_privileges)
@@ -4066,7 +4139,7 @@ Item_equal *Item_field::find_item_equal(COND_EQUAL *cond_equal)
FALSE otherwise
*/
-bool Item_field::subst_argument_checker(byte **arg)
+bool Item_field::subst_argument_checker(uchar **arg)
{
return (result_type() != STRING_RESULT) || (*arg);
}
@@ -4122,7 +4195,7 @@ static void convert_zerofill_number_to_string(Item **item, Field_num *field)
pointer to the field item, otherwise.
*/
-Item *Item_field::equal_fields_propagator(byte *arg)
+Item *Item_field::equal_fields_propagator(uchar *arg)
{
if (no_const_subst)
return this;
@@ -4160,7 +4233,7 @@ Item *Item_field::equal_fields_propagator(byte *arg)
See comments in Arg_comparator::set_compare_func() for details
*/
-bool Item_field::set_no_const_sub(byte *arg)
+bool Item_field::set_no_const_sub(uchar *arg)
{
if (field->charset() != &my_charset_bin)
no_const_subst=1;
@@ -4195,7 +4268,7 @@ bool Item_field::set_no_const_sub(byte *arg)
this - otherwise.
*/
-Item *Item_field::replace_equal_field(byte *arg)
+Item *Item_field::replace_equal_field(uchar *arg)
{
if (item_equal)
{
@@ -4241,24 +4314,30 @@ void Item::make_field(Send_field *tmp_field)
}
-void Item_empty_string::make_field(Send_field *tmp_field)
+enum_field_types Item::string_field_type() const
{
- enum_field_types f_type= FIELD_TYPE_VAR_STRING;
+ enum_field_types f_type= MYSQL_TYPE_VAR_STRING;
if (max_length >= 16777216)
- f_type= FIELD_TYPE_LONG_BLOB;
+ f_type= MYSQL_TYPE_LONG_BLOB;
else if (max_length >= 65536)
- f_type= FIELD_TYPE_MEDIUM_BLOB;
- init_make_field(tmp_field, f_type);
+ f_type= MYSQL_TYPE_MEDIUM_BLOB;
+ return f_type;
+}
+
+
+void Item_empty_string::make_field(Send_field *tmp_field)
+{
+ init_make_field(tmp_field, string_field_type());
}
enum_field_types Item::field_type() const
{
switch (result_type()) {
- case STRING_RESULT: return MYSQL_TYPE_VARCHAR;
- case INT_RESULT: return FIELD_TYPE_LONGLONG;
- case DECIMAL_RESULT: return FIELD_TYPE_NEWDECIMAL;
- case REAL_RESULT: return FIELD_TYPE_DOUBLE;
+ case STRING_RESULT: return string_field_type();
+ case INT_RESULT: return MYSQL_TYPE_LONGLONG;
+ case DECIMAL_RESULT: return MYSQL_TYPE_NEWDECIMAL;
+ case REAL_RESULT: return MYSQL_TYPE_DOUBLE;
case ROW_RESULT:
default:
DBUG_ASSERT(0);
@@ -4322,6 +4401,49 @@ String *Item::check_well_formed_result(String *str, bool send_error)
return str;
}
+/*
+ Compare two items using a given collation
+
+ SYNOPSIS
+ eq_by_collation()
+ item item to compare with
+ binary_cmp TRUE <-> compare as binaries
+ cs collation to use when comparing strings
+
+ DESCRIPTION
+ This method works exactly as Item::eq if the collation cs coincides with
+ the collation of the compared objects. Otherwise, first the collations that
+ differ from cs are replaced for cs and then the items are compared by
+ Item::eq. After the comparison the original collations of items are
+ restored.
+
+ RETURN
+ 1 compared items has been detected as equal
+ 0 otherwise
+*/
+
+bool Item::eq_by_collation(Item *item, bool binary_cmp, CHARSET_INFO *cs)
+{
+ CHARSET_INFO *save_cs= 0;
+ CHARSET_INFO *save_item_cs= 0;
+ if (collation.collation != cs)
+ {
+ save_cs= collation.collation;
+ collation.collation= cs;
+ }
+ if (item->collation.collation != cs)
+ {
+ save_item_cs= item->collation.collation;
+ item->collation.collation= cs;
+ }
+ bool res= eq(item, binary_cmp);
+ if (save_cs)
+ collation.collation= save_cs;
+ if (save_item_cs)
+ item->collation.collation= save_item_cs;
+ return res;
+}
+
/*
Create a field to hold a string value from an item
@@ -4339,17 +4461,22 @@ String *Item::check_well_formed_result(String *str, bool send_error)
Field *Item::make_string_field(TABLE *table)
{
+ Field *field;
DBUG_ASSERT(collation.collation);
if (max_length/collation.collation->mbmaxlen > CONVERT_IF_BIGGER_TO_BLOB)
- return new Field_blob(max_length, maybe_null, name, table,
+ field= new Field_blob(max_length, maybe_null, name,
collation.collation);
/* Item_type_holder holds the exact type, do not change it */
- if (max_length > 0 &&
+ else if (max_length > 0 &&
(type() != Item::TYPE_HOLDER || field_type() != MYSQL_TYPE_STRING))
- return new Field_varstring(max_length, maybe_null, name, table,
+ field= new Field_varstring(max_length, maybe_null, name, table->s,
collation.collation);
- return new Field_string(max_length, maybe_null, name, table,
- collation.collation);
+ else
+ field= new Field_string(max_length, maybe_null, name,
+ collation.collation);
+ if (field)
+ field->init(table);
+ return field;
}
@@ -4357,74 +4484,97 @@ Field *Item::make_string_field(TABLE *table)
Create a field based on field_type of argument
For now, this is only used to create a field for
- IFNULL(x,something)
+ IFNULL(x,something) and time functions
RETURN
0 error
# Created field
*/
-Field *Item::tmp_table_field_from_field_type(TABLE *table)
+Field *Item::tmp_table_field_from_field_type(TABLE *table, bool fixed_length)
{
/*
The field functions defines a field to be not null if null_ptr is not 0
*/
uchar *null_ptr= maybe_null ? (uchar*) "" : 0;
+ Field *field;
switch (field_type()) {
case MYSQL_TYPE_DECIMAL:
case MYSQL_TYPE_NEWDECIMAL:
- return new Field_new_decimal((char*) 0, max_length, null_ptr, 0,
- Field::NONE, name, table, decimals, 0,
+ field= new Field_new_decimal((uchar*) 0, max_length, null_ptr, 0,
+ Field::NONE, name, decimals, 0,
unsigned_flag);
+ break;
case MYSQL_TYPE_TINY:
- return new Field_tiny((char*) 0, max_length, null_ptr, 0, Field::NONE,
- name, table, 0, unsigned_flag);
+ field= new Field_tiny((uchar*) 0, max_length, null_ptr, 0, Field::NONE,
+ name, 0, unsigned_flag);
+ break;
case MYSQL_TYPE_SHORT:
- return new Field_short((char*) 0, max_length, null_ptr, 0, Field::NONE,
- name, table, 0, unsigned_flag);
+ field= new Field_short((uchar*) 0, max_length, null_ptr, 0, Field::NONE,
+ name, 0, unsigned_flag);
+ break;
case MYSQL_TYPE_LONG:
- return new Field_long((char*) 0, max_length, null_ptr, 0, Field::NONE,
- name, table, 0, unsigned_flag);
+ field= new Field_long((uchar*) 0, max_length, null_ptr, 0, Field::NONE,
+ name, 0, unsigned_flag);
+ break;
#ifdef HAVE_LONG_LONG
case MYSQL_TYPE_LONGLONG:
- return new Field_longlong((char*) 0, max_length, null_ptr, 0, Field::NONE,
- name, table, 0, unsigned_flag);
+ field= new Field_longlong((uchar*) 0, max_length, null_ptr, 0, Field::NONE,
+ name, 0, unsigned_flag);
+ break;
#endif
case MYSQL_TYPE_FLOAT:
- return new Field_float((char*) 0, max_length, null_ptr, 0, Field::NONE,
- name, table, decimals, 0, unsigned_flag);
+ field= new Field_float((uchar*) 0, max_length, null_ptr, 0, Field::NONE,
+ name, decimals, 0, unsigned_flag);
+ break;
case MYSQL_TYPE_DOUBLE:
- return new Field_double((char*) 0, max_length, null_ptr, 0, Field::NONE,
- name, table, decimals, 0, unsigned_flag);
+ field= new Field_double((uchar*) 0, max_length, null_ptr, 0, Field::NONE,
+ name, decimals, 0, unsigned_flag);
+ break;
case MYSQL_TYPE_NULL:
- return new Field_null((char*) 0, max_length, Field::NONE,
- name, table, &my_charset_bin);
+ field= new Field_null((uchar*) 0, max_length, Field::NONE,
+ name, &my_charset_bin);
+ break;
case MYSQL_TYPE_INT24:
- return new Field_medium((char*) 0, max_length, null_ptr, 0, Field::NONE,
- name, table, 0, unsigned_flag);
+ field= new Field_medium((uchar*) 0, max_length, null_ptr, 0, Field::NONE,
+ name, 0, unsigned_flag);
+ break;
case MYSQL_TYPE_NEWDATE:
case MYSQL_TYPE_DATE:
- return new Field_date(maybe_null, name, table, &my_charset_bin);
+ field= new Field_newdate(maybe_null, name, &my_charset_bin);
+ break;
case MYSQL_TYPE_TIME:
- return new Field_time(maybe_null, name, table, &my_charset_bin);
+ field= new Field_time(maybe_null, name, &my_charset_bin);
+ break;
case MYSQL_TYPE_TIMESTAMP:
- return new Field_timestamp(maybe_null, name, table, &my_charset_bin);
+ field= new Field_timestamp(maybe_null, name, &my_charset_bin);
+ break;
case MYSQL_TYPE_DATETIME:
- return new Field_datetime(maybe_null, name, table, &my_charset_bin);
+ field= new Field_datetime(maybe_null, name, &my_charset_bin);
+ break;
case MYSQL_TYPE_YEAR:
- return new Field_year((char*) 0, max_length, null_ptr, 0, Field::NONE,
- name, table);
+ field= new Field_year((uchar*) 0, max_length, null_ptr, 0, Field::NONE,
+ name);
+ break;
case MYSQL_TYPE_BIT:
- return new Field_bit_as_char(NULL, max_length, null_ptr, 0,
- Field::NONE, name, table);
+ field= new Field_bit_as_char(NULL, max_length, null_ptr, 0,
+ Field::NONE, name);
+ break;
default:
/* This case should never be chosen */
DBUG_ASSERT(0);
/* If something goes awfully wrong, it's better to get a string than die */
+ case MYSQL_TYPE_STRING:
+ if (fixed_length && max_length < CONVERT_IF_BIGGER_TO_BLOB)
+ {
+ field= new Field_string(max_length, maybe_null, name,
+ collation.collation);
+ break;
+ }
+ /* Fall through to make_string_field() */
case MYSQL_TYPE_ENUM:
case MYSQL_TYPE_SET:
- case MYSQL_TYPE_STRING:
case MYSQL_TYPE_VAR_STRING:
case MYSQL_TYPE_VARCHAR:
return make_string_field(table);
@@ -4433,18 +4583,20 @@ Field *Item::tmp_table_field_from_field_type(TABLE *table)
case MYSQL_TYPE_LONG_BLOB:
case MYSQL_TYPE_BLOB:
if (this->type() == Item::TYPE_HOLDER)
- return new Field_blob(max_length, maybe_null, name, table,
- collation.collation, 1);
+ field= new Field_blob(max_length, maybe_null, name, collation.collation,
+ 1);
else
- return new Field_blob(max_length, maybe_null, name, table,
- collation.collation);
+ field= new Field_blob(max_length, maybe_null, name, collation.collation);
break; // Blob handled outside of case
#ifdef HAVE_SPATIAL
case MYSQL_TYPE_GEOMETRY:
- return new Field_geom(max_length, maybe_null,
- name, table, get_geometry_type());
+ field= new Field_geom(max_length, maybe_null,
+ name, table->s, get_geometry_type());
#endif /* HAVE_SPATIAL */
}
+ if (field)
+ field->init(table);
+ return field;
}
@@ -4735,7 +4887,7 @@ void Item_float::print(String *str)
}
char buffer[20];
String num(buffer, sizeof(buffer), &my_charset_bin);
- num.set(value, decimals, &my_charset_bin);
+ num.set_real(value, decimals, &my_charset_bin);
str->append(num);
}
@@ -5083,7 +5235,7 @@ void Item_field::update_null_value()
this field otherwise
*/
-Item *Item_field::update_value_transformer(byte *select_arg)
+Item *Item_field::update_value_transformer(uchar *select_arg)
{
SELECT_LEX *select= (SELECT_LEX*)select_arg;
DBUG_ASSERT(fixed);
@@ -5842,8 +5994,9 @@ bool Item_default_value::fix_fields(THD *thd, Item **items)
if (!(def_field= (Field*) sql_alloc(field_arg->field->size_of())))
goto error;
memcpy(def_field, field_arg->field, field_arg->field->size_of());
- def_field->move_field(def_field->table->s->default_values -
- def_field->table->record[0]);
+ def_field->move_field_offset((my_ptrdiff_t)
+ (def_field->table->s->default_values -
+ def_field->table->record[0]));
set_field(def_field);
return FALSE;
@@ -5911,7 +6064,7 @@ int Item_default_value::save_in_field(Field *field_arg, bool no_conversions)
same time it can replace some nodes in the tree
*/
-Item *Item_default_value::transform(Item_transformer transformer, byte *args)
+Item *Item_default_value::transform(Item_transformer transformer, uchar *args)
{
DBUG_ASSERT(!current_thd->is_stmt_prepare());
@@ -5977,16 +6130,22 @@ bool Item_insert_value::fix_fields(THD *thd, Item **items)
if (!def_field)
return TRUE;
memcpy(def_field, field_arg->field, field_arg->field->size_of());
- def_field->move_field(def_field->table->insert_values -
- def_field->table->record[0]);
+ def_field->move_field_offset((my_ptrdiff_t)
+ (def_field->table->insert_values -
+ def_field->table->record[0]));
set_field(def_field);
}
else
{
Field *tmp_field= field_arg->field;
/* charset doesn't matter here, it's to avoid sigsegv only */
- set_field(new Field_null(0, 0, Field::NONE, tmp_field->field_name,
- tmp_field->table, &my_charset_bin));
+ tmp_field= new Field_null(0, 0, Field::NONE, field_arg->field->field_name,
+ &my_charset_bin);
+ if (tmp_field)
+ {
+ tmp_field->init(field_arg->field->table);
+ set_field(tmp_field);
+ }
}
return FALSE;
}
@@ -6025,21 +6184,21 @@ void Item_trigger_field::setup_field(THD *thd, TABLE *table,
GRANT_INFO *table_grant_info)
{
/*
- There is no sense in marking fields used by trigger with current value
- of THD::query_id since it is completely unrelated to the THD::query_id
- value for statements which will invoke trigger. So instead we use
- Table_triggers_list::mark_fields_used() method which is called during
- execution of these statements.
+ It is too early to mark fields used here, because before execution
+ of statement that will invoke trigger other statements may use same
+ TABLE object, so all such mark-up will be wiped out.
+ So instead we do it in Table_triggers_list::mark_fields_used()
+ method which is called during execution of these statements.
*/
- bool save_set_query_id= thd->set_query_id;
- thd->set_query_id= 0;
+ enum_mark_columns save_mark_used_columns= thd->mark_used_columns;
+ thd->mark_used_columns= MARK_COLUMNS_NONE;
/*
Try to find field by its name and if it will be found
set field_idx properly.
*/
(void)find_field_in_table(thd, table, field_name, (uint) strlen(field_name),
0, &field_idx);
- thd->set_query_id= save_set_query_id;
+ thd->mark_used_columns= save_mark_used_columns;
triggers= table->triggers;
table_grants= table_grant_info;
}
@@ -6097,9 +6256,8 @@ bool Item_trigger_field::fix_fields(THD *thd, Item **items)
{
table_grants->want_privilege= want_privilege;
- if (check_grant_column(thd, table_grants, triggers->trigger_table->s->db,
- triggers->trigger_table->s->table_name,
- field_name,
+ if (check_grant_column(thd, table_grants, triggers->trigger_table->s->db.str,
+ triggers->trigger_table->s->table_name.str, field_name,
strlen(field_name), thd->security_ctx))
return TRUE;
}
@@ -6137,11 +6295,6 @@ void Item_trigger_field::cleanup()
}
-/*
- If item is a const function, calculate it and return a const item
- The original item is freed if not returned
-*/
-
Item_result item_cmp_type(Item_result a,Item_result b)
{
if (a == STRING_RESULT && b == STRING_RESULT)
@@ -6371,7 +6524,7 @@ longlong Item_cache_real::val_int()
String* Item_cache_real::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
- str->set(value, decimals, default_charset());
+ str->set_real(value, decimals, default_charset());
return str;
}
@@ -6629,6 +6782,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;
@@ -6866,24 +7021,33 @@ Field *Item_type_holder::make_field_by_type(TABLE *table)
The field functions defines a field to be not null if null_ptr is not 0
*/
uchar *null_ptr= maybe_null ? (uchar*) "" : 0;
- switch (fld_type)
- {
+ Field *field;
+
+ switch (fld_type) {
case MYSQL_TYPE_ENUM:
DBUG_ASSERT(enum_set_typelib);
- return new Field_enum((char *) 0, max_length, null_ptr, 0,
+ field= new Field_enum((uchar *) 0, max_length, null_ptr, 0,
Field::NONE, name,
- table, get_enum_pack_length(enum_set_typelib->count),
+ get_enum_pack_length(enum_set_typelib->count),
enum_set_typelib, collation.collation);
+ if (field)
+ field->init(table);
+ return field;
case MYSQL_TYPE_SET:
DBUG_ASSERT(enum_set_typelib);
- return new Field_set((char *) 0, max_length, null_ptr, 0,
+ field= new Field_set((uchar *) 0, max_length, null_ptr, 0,
Field::NONE, name,
- table, get_set_pack_length(enum_set_typelib->count),
+ get_set_pack_length(enum_set_typelib->count),
enum_set_typelib, collation.collation);
+ if (field)
+ field->init(table);
+ return field;
+ case MYSQL_TYPE_NULL:
+ return make_string_field(table);
default:
break;
}
- return tmp_table_field_from_field_type(table);
+ return tmp_table_field_from_field_type(table, 0);
}