diff options
author | msvensson@pilot.blaudden <> | 2007-03-01 18:12:56 +0100 |
---|---|---|
committer | msvensson@pilot.blaudden <> | 2007-03-01 18:12:56 +0100 |
commit | f5778fc73e4e676f38c4734bca3a96f4d08dc2d7 (patch) | |
tree | dd839a6db9e2985054d2bc99faaafdc4440866fc /sql/item.cc | |
parent | ab61d07a30b73e3446b6eab9536ba464a0d55f74 (diff) | |
parent | 2f5a2b2476a0ca43d0a5bdfb979b427ff806839f (diff) | |
download | mariadb-git-f5778fc73e4e676f38c4734bca3a96f4d08dc2d7.tar.gz |
Merge pilot.blaudden:/home/msvensson/mysql/mysql-5.0
into pilot.blaudden:/home/msvensson/mysql/mysql-5.0-maint
Diffstat (limited to 'sql/item.cc')
-rw-r--r-- | sql/item.cc | 194 |
1 files changed, 154 insertions, 40 deletions
diff --git a/sql/item.cc b/sql/item.cc index 050171b8fbe..92008a344ef 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -25,10 +25,6 @@ #include "sql_trigger.h" #include "sql_select.h" -static void mark_as_dependent(THD *thd, - SELECT_LEX *last, SELECT_LEX *current, - Item_ident *item); - const String my_null_string("NULL", 4, default_charset_info); /****************************************************************************/ @@ -1525,6 +1521,8 @@ bool agg_item_charsets(DTCollation &coll, const char *fname, doesn't display each argument's characteristics. - if nargs is 1, then this error cannot happen. */ + LINT_INIT(safe_args[0]); + LINT_INIT(safe_args[1]); if (nargs >=2 && nargs <= 3) { safe_args[0]= args[0]; @@ -1609,7 +1607,7 @@ 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), - have_privileges(0), any_privileges(0) + have_privileges(0), any_privileges(0), fixed_as_field(0) { set_field(f); /* @@ -1623,7 +1621,7 @@ 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_equal(0), no_const_subst(0), - have_privileges(0), any_privileges(0) + have_privileges(0), any_privileges(0), fixed_as_field(0) { /* We always need to provide Item_field with a fully qualified field @@ -1662,9 +1660,12 @@ Item_field::Item_field(Name_resolution_context *context_arg, const char *field_name_arg) :Item_ident(context_arg, db_arg,table_name_arg,field_name_arg), field(0), result_field(0), item_equal(0), no_const_subst(0), - have_privileges(0), any_privileges(0) + have_privileges(0), any_privileges(0), fixed_as_field(0) { + SELECT_LEX *select= current_thd->lex->current_select; collation.set(DERIVATION_IMPLICIT); + if (select && select->parsing_place != IN_HAVING) + select->select_n_where_fields++; } // Constructor need to process subselect with temporary tables (see Item) @@ -1675,7 +1676,8 @@ Item_field::Item_field(THD *thd, Item_field *item) item_equal(item->item_equal), no_const_subst(item->no_const_subst), have_privileges(item->have_privileges), - any_privileges(item->any_privileges) + any_privileges(item->any_privileges), + fixed_as_field(item->fixed_as_field) { collation.set(DERIVATION_IMPLICIT); } @@ -1685,7 +1687,7 @@ void Item_field::set_field(Field *field_par) field=result_field=field_par; // for easy coding with fields maybe_null=field->maybe_null(); decimals= field->decimals(); - max_length= field_par->max_length(); + 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; @@ -2394,21 +2396,22 @@ void Item_param::set_decimal(const char *str, ulong length) the fact that even wrong value sent over binary protocol fits into MAX_DATE_STRING_REP_LENGTH buffer. */ -void Item_param::set_time(TIME *tm, timestamp_type type, uint32 max_length_arg) +void Item_param::set_time(TIME *tm, timestamp_type time_type, + uint32 max_length_arg) { DBUG_ENTER("Item_param::set_time"); value.time= *tm; - value.time.time_type= type; + value.time.time_type= time_type; if (value.time.year > 9999 || value.time.month > 12 || value.time.day > 31 || - type != MYSQL_TIMESTAMP_TIME && value.time.hour > 23 || + time_type != MYSQL_TIMESTAMP_TIME && value.time.hour > 23 || value.time.minute > 59 || value.time.second > 59) { char buff[MAX_DATE_STRING_REP_LENGTH]; uint length= my_TIME_to_str(&value.time, buff); - make_truncated_value_warning(current_thd, buff, length, type, 0); + make_truncated_value_warning(current_thd, buff, length, time_type, 0); set_zero_time(&value.time, MYSQL_TIMESTAMP_ERROR); } @@ -2873,7 +2876,7 @@ bool Item_param::basic_const_item() const Item * -Item_param::new_item() +Item_param::clone_item() { /* see comments in the header file */ switch (state) { @@ -3484,34 +3487,73 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference) } if (*from_field != view_ref_found) { + prev_subselect_item->used_tables_cache|= (*from_field)->table->map; prev_subselect_item->const_item_cache= 0; + if (!last_checked_context->select_lex->having_fix_field && + !fixed_as_field) + { + Item_outer_ref *rf; + Query_arena *arena= 0, backup; + /* + Each outer field is replaced for an Item_outer_ref object. + This is done in order to get correct results when the outer + select employs a temporary table. + The original fields are saved in the inner_fields_list of the + outer select. This list is created by the following reasons: + 1. We can't add field items to the outer select list directly + because the outer select hasn't been fully fixed yet. + 2. We need a location to refer to in the Item_ref object + so the inner_fields_list is used as such temporary + reference storage. + The new Item_outer_ref object replaces the original field and is + also saved in the inner_refs_list of the outer select. Here + it is only created. It can be fixed only after the original + field has been fixed and this is done in the fix_inner_refs() + function. + */ + set_field(*from_field); + arena= thd->activate_stmt_arena_if_needed(&backup); + rf= new Item_outer_ref(context, this); + if (!rf) + { + if (arena) + thd->restore_active_arena(arena, &backup); + return -1; + } + *reference= rf; + select->inner_refs_list.push_back(rf); + if (arena) + thd->restore_active_arena(arena, &backup); + fixed_as_field= 1; + } if (thd->lex->in_sum_func && thd->lex->in_sum_func->nest_level == thd->lex->current_select->nest_level) { - Item::Type type= (*reference)->type(); + Item::Type ref_type= (*reference)->type(); set_if_bigger(thd->lex->in_sum_func->max_arg_level, select->nest_level); set_field(*from_field); fixed= 1; mark_as_dependent(thd, last_checked_context->select_lex, context->select_lex, this, - ((type == REF_ITEM || type == FIELD_ITEM) ? + ((ref_type == REF_ITEM || + ref_type == FIELD_ITEM) ? (Item_ident*) (*reference) : 0)); return 0; } } else { - Item::Type type= (*reference)->type(); + Item::Type ref_type= (*reference)->type(); prev_subselect_item->used_tables_cache|= (*reference)->used_tables(); prev_subselect_item->const_item_cache&= (*reference)->const_item(); mark_as_dependent(thd, last_checked_context->select_lex, context->select_lex, this, - ((type == REF_ITEM || type == FIELD_ITEM) ? + ((ref_type == REF_ITEM || ref_type == FIELD_ITEM) ? (Item_ident*) (*reference) : 0)); /* @@ -3612,7 +3654,7 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference) { mark_as_dependent(thd, last_checked_context->select_lex, context->select_lex, - this, this); + this, (Item_ident*)*reference); if (last_checked_context->select_lex->having_fix_field) { Item_ref *rf; @@ -4049,7 +4091,7 @@ Item *Item_field::replace_equal_field(byte *arg) void Item::init_make_field(Send_field *tmp_field, - enum enum_field_types field_type) + enum enum_field_types field_type_arg) { char *empty_name= (char*) ""; tmp_field->db_name= empty_name; @@ -4061,7 +4103,7 @@ void Item::init_make_field(Send_field *tmp_field, tmp_field->flags= (maybe_null ? 0 : NOT_NULL_FLAG) | (my_binary_compare(collation.collation) ? BINARY_FLAG : 0); - tmp_field->type=field_type; + tmp_field->type= field_type_arg; tmp_field->length=max_length; tmp_field->decimals=decimals; if (unsigned_flag) @@ -4076,12 +4118,12 @@ void Item::make_field(Send_field *tmp_field) void Item_empty_string::make_field(Send_field *tmp_field) { - enum_field_types type= FIELD_TYPE_VAR_STRING; + enum_field_types f_type= FIELD_TYPE_VAR_STRING; if (max_length >= 16777216) - type= FIELD_TYPE_LONG_BLOB; + f_type= FIELD_TYPE_LONG_BLOB; else if (max_length >= 65536) - type= FIELD_TYPE_MEDIUM_BLOB; - init_make_field(tmp_field, type); + f_type= FIELD_TYPE_MEDIUM_BLOB; + init_make_field(tmp_field, f_type); } @@ -4416,7 +4458,7 @@ bool Item_int::eq(const Item *arg, bool binary_cmp) const } -Item *Item_int_with_ref::new_item() +Item *Item_int_with_ref::clone_item() { DBUG_ASSERT(ref->const_item()); /* @@ -4694,10 +4736,10 @@ bool Item_null::send(Protocol *protocol, String *packet) bool Item::send(Protocol *protocol, String *buffer) { bool result; - enum_field_types type; + enum_field_types f_type; LINT_INIT(result); // Will be set if null_value == 0 - switch ((type=field_type())) { + switch ((f_type=field_type())) { default: case MYSQL_TYPE_NULL: case MYSQL_TYPE_DECIMAL: @@ -4776,7 +4818,7 @@ bool Item::send(Protocol *protocol, String *buffer) get_date(&tm, TIME_FUZZY_DATE); if (!null_value) { - if (type == MYSQL_TYPE_DATE) + if (f_type == MYSQL_TYPE_DATE) return protocol->store_date(&tm); else result= protocol->store(&tm); @@ -4820,6 +4862,51 @@ void Item_field::update_null_value() } +/* + Add the field to the select list and substitute it for the reference to + the field. + + SYNOPSIS + Item_field::update_value_transformer() + select_arg current select + + DESCRIPTION + If the field doesn't belong to the table being inserted into then it is + added to the select list, pointer to it is stored in the ref_pointer_array + of the select and the field itself is substituted for the Item_ref object. + This is done in order to get correct values from update fields that + belongs to the SELECT part in the INSERT .. SELECT .. ON DUPLICATE KEY + UPDATE statement. + + RETURN + 0 if error occured + ref if all conditions are met + this field otherwise +*/ + +Item *Item_field::update_value_transformer(byte *select_arg) +{ + SELECT_LEX *select= (SELECT_LEX*)select_arg; + DBUG_ASSERT(fixed); + + if (field->table != select->context.table_list->table && + type() != Item::TRIGGER_FIELD_ITEM) + { + List<Item> *all_fields= &select->join->all_fields; + Item **ref_pointer_array= select->ref_pointer_array; + int el= all_fields->elements; + Item_ref *ref; + + ref_pointer_array[el]= (Item*)this; + all_fields->push_front((Item*)this); + ref= new Item_ref(&select->context, ref_pointer_array + el, + table_name, field_name); + return ref; + } + return this; +} + + Item_ref::Item_ref(Name_resolution_context *context_arg, Item **item, const char *table_name_arg, const char *field_name_arg) @@ -4829,8 +4916,7 @@ Item_ref::Item_ref(Name_resolution_context *context_arg, /* This constructor used to create some internals references over fixed items */ - DBUG_ASSERT(ref != 0); - if (*ref && (*ref)->fixed) + if (ref && *ref && (*ref)->fixed) set_properties(); } @@ -4989,7 +5075,7 @@ bool Item_ref::fix_fields(THD *thd, Item **reference) goto error; if (from_field == view_ref_found) { - Item::Type type= (*reference)->type(); + Item::Type refer_type= (*reference)->type(); prev_subselect_item->used_tables_cache|= (*reference)->used_tables(); prev_subselect_item->const_item_cache&= @@ -4997,7 +5083,8 @@ bool Item_ref::fix_fields(THD *thd, Item **reference) DBUG_ASSERT((*reference)->type() == REF_ITEM); mark_as_dependent(thd, last_checked_context->select_lex, context->select_lex, this, - ((type == REF_ITEM || type == FIELD_ITEM) ? + ((refer_type == REF_ITEM || + refer_type == FIELD_ITEM) ? (Item_ident*) (*reference) : 0)); /* @@ -5130,7 +5217,7 @@ void Item_ref::print(String *str) if (ref) { if ((*ref)->type() != Item::CACHE_ITEM && ref_type() != VIEW_REF && - name && alias_name_used) + ref_type() != OUTER_REF && name && alias_name_used) { THD *thd= current_thd; append_identifier(thd, str, name, (uint) strlen(name)); @@ -5378,7 +5465,7 @@ bool Item_direct_ref::get_date(TIME *ltime,uint fuzzydate) /* - Prepare referenced view viewld then call usual Item_direct_ref::fix_fields + Prepare referenced field then call usual Item_direct_ref::fix_fields SYNOPSIS Item_direct_view_ref::fix_fields() @@ -5402,6 +5489,31 @@ bool Item_direct_view_ref::fix_fields(THD *thd, Item **reference) } /* + Prepare referenced outer field then call usual Item_direct_ref::fix_fields + + SYNOPSIS + Item_outer_ref::fix_fields() + thd thread handler + reference reference on reference where this item stored + + RETURN + FALSE OK + TRUE Error +*/ + +bool Item_outer_ref::fix_fields(THD *thd, Item **reference) +{ + DBUG_ASSERT(*ref); + /* outer_field->check_cols() will be made in Item_direct_ref::fix_fields */ + outer_field->fixed_as_field= 1; + if (!outer_field->fixed && + (outer_field->fix_fields(thd, reference))) + return TRUE; + table_name= outer_field->table_name; + return Item_direct_ref::fix_fields(thd, reference); +} + +/* Compare two view column references for equality. SYNOPSIS @@ -5731,8 +5843,9 @@ bool Item_trigger_field::fix_fields(THD *thd, Item **items) { table_grants->want_privilege= want_privilege; - if (check_grant_column(thd, table_grants, triggers->table->s->db, - triggers->table->s->table_name, field_name, + if (check_grant_column(thd, table_grants, triggers->trigger_table->s->db, + triggers->trigger_table->s->table_name, + field_name, strlen(field_name), thd->security_ctx)) return TRUE; } @@ -5850,7 +5963,8 @@ void resolve_const_item(THD *thd, Item **ref, Item *comp_item) DBUG_ASSERT(item_row->cols() == comp_item_row->cols()); col= item_row->cols(); while (col-- > 0) - resolve_const_item(thd, item_row->addr(col), comp_item_row->el(col)); + resolve_const_item(thd, item_row->addr(col), + comp_item_row->element_index(col)); break; } /* Fallthrough */ @@ -6118,7 +6232,7 @@ bool Item_cache_row::setup(Item * item) return 1; for (uint i= 0; i < item_count; i++) { - Item *el= item->el(i); + Item *el= item->element_index(i); Item_cache *tmp; if (!(tmp= values[i]= Item_cache::get_cache(el->result_type()))) return 1; @@ -6134,7 +6248,7 @@ void Item_cache_row::store(Item * item) item->bring_value(); for (uint i= 0; i < item_count; i++) { - values[i]->store(item->el(i)); + values[i]->store(item->element_index(i)); null_value|= values[i]->null_value; } } |