diff options
author | igor@olga.mysql.com <> | 2007-02-13 01:34:36 -0800 |
---|---|---|
committer | igor@olga.mysql.com <> | 2007-02-13 01:34:36 -0800 |
commit | fb9e0ad3be786c69ffe24a5a60fc70dc53675c8d (patch) | |
tree | 0ebadd1cbf0ccf30ae7b01d82842db102e6a9fb3 /sql | |
parent | 4aab8494e9dab70f7ccd70f3033122580c729ffe (diff) | |
parent | 30614d22c195f25d7b59fb2651cfaca15697002c (diff) | |
download | mariadb-git-fb9e0ad3be786c69ffe24a5a60fc70dc53675c8d.tar.gz |
Merge olga.mysql.com:/home/igor/mysql-5.0-opt
into olga.mysql.com:/home/igor/mysql-5.1-opt
Diffstat (limited to 'sql')
-rw-r--r-- | sql/field.h | 4 | ||||
-rw-r--r-- | sql/field_conv.cc | 15 | ||||
-rw-r--r-- | sql/item.cc | 20 | ||||
-rw-r--r-- | sql/item_cmpfunc.cc | 8 | ||||
-rw-r--r-- | sql/item_cmpfunc.h | 1 | ||||
-rw-r--r-- | sql/mysql_priv.h | 4 | ||||
-rw-r--r-- | sql/opt_range.cc | 45 | ||||
-rw-r--r-- | sql/sql_insert.cc | 37 | ||||
-rw-r--r-- | sql/sql_lex.cc | 1 | ||||
-rw-r--r-- | sql/sql_select.cc | 4 | ||||
-rw-r--r-- | sql/sql_show.cc | 28 | ||||
-rw-r--r-- | sql/sql_update.cc | 11 | ||||
-rw-r--r-- | sql/sql_view.cc | 1 | ||||
-rw-r--r-- | sql/table.cc | 2 | ||||
-rw-r--r-- | sql/table.h | 8 |
15 files changed, 114 insertions, 75 deletions
diff --git a/sql/field.h b/sql/field.h index a2a4936fc5e..b7264df3146 100644 --- a/sql/field.h +++ b/sql/field.h @@ -30,7 +30,7 @@ class Send_field; class Protocol; class create_field; struct st_cache_field; -void field_conv(Field *to,Field *from); +int field_conv(Field *to,Field *from); inline uint get_enum_pack_length(int elements) { @@ -1312,7 +1312,7 @@ public: uint max_packed_col_length(uint max_length); void free() { value.free(); } inline void clear_temporary() { bzero((char*) &value,sizeof(value)); } - friend void field_conv(Field *to,Field *from); + friend int field_conv(Field *to,Field *from); uint size_of() const { return sizeof(*this); } bool has_charset(void) const { return charset() == &my_charset_bin ? FALSE : TRUE; } diff --git a/sql/field_conv.cc b/sql/field_conv.cc index 2670de0387b..805aba01754 100644 --- a/sql/field_conv.cc +++ b/sql/field_conv.cc @@ -678,7 +678,7 @@ void (*Copy_field::get_copy_func(Field *to,Field *from))(Copy_field*) /* Simple quick field convert that is called on insert */ -void field_conv(Field *to,Field *from) +int field_conv(Field *to,Field *from) { if (to->real_type() == from->real_type() && !(to->type() == MYSQL_TYPE_BLOB && to->table->copy_blobs)) @@ -706,7 +706,7 @@ void field_conv(Field *to,Field *from) if (to->ptr != from->ptr) #endif memcpy(to->ptr,from->ptr,to->pack_length()); - return; + return 0; } } if (to->type() == MYSQL_TYPE_BLOB) @@ -722,8 +722,7 @@ void field_conv(Field *to,Field *from) from->real_type() != MYSQL_TYPE_STRING && from->real_type() != MYSQL_TYPE_VARCHAR)) blob->value.copy(); - blob->store(blob->value.ptr(),blob->value.length(),from->charset()); - return; + return blob->store(blob->value.ptr(),blob->value.length(),from->charset()); } if ((from->result_type() == STRING_RESULT && (to->result_type() == STRING_RESULT || @@ -740,15 +739,15 @@ void field_conv(Field *to,Field *from) end with \0. Can be replaced with .ptr() when we have our own string->double conversion. */ - to->store(result.c_ptr_quick(),result.length(),from->charset()); + return to->store(result.c_ptr_quick(),result.length(),from->charset()); } else if (from->result_type() == REAL_RESULT) - to->store(from->val_real()); + return to->store(from->val_real()); else if (from->result_type() == DECIMAL_RESULT) { my_decimal buff; - to->store_decimal(from->val_decimal(&buff)); + return to->store_decimal(from->val_decimal(&buff)); } else - to->store(from->val_int(), test(from->flags & UNSIGNED_FLAG)); + return to->store(from->val_int(), test(from->flags & UNSIGNED_FLAG)); } diff --git a/sql/item.cc b/sql/item.cc index d0993ebabae..48ca03ada0a 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -4329,18 +4329,19 @@ void Item_field::save_org_in_field(Field *to) int Item_field::save_in_field(Field *to, bool no_conversions) { + int res; if (result_field->is_null()) { null_value=1; - return set_field_to_null_with_conversions(to, no_conversions); + res= set_field_to_null_with_conversions(to, no_conversions); } else { to->set_notnull(); - field_conv(to,result_field); + res= field_conv(to,result_field); null_value=0; } - return 0; + return res; } @@ -5361,18 +5362,7 @@ my_decimal *Item_ref::val_decimal(my_decimal *decimal_value) int Item_ref::save_in_field(Field *to, bool no_conversions) { int res; - if (result_field) - { - if (result_field->is_null()) - { - null_value= 1; - return set_field_to_null_with_conversions(to, no_conversions); - } - to->set_notnull(); - field_conv(to, result_field); - null_value= 0; - return 0; - } + DBUG_ASSERT(!result_field); res= (*ref)->save_in_field(to, no_conversions); null_value= (*ref)->null_value; return res; diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index fa760566a3f..bd616d0658c 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -1236,11 +1236,11 @@ void Item_func_between::fix_length_and_dec() They are compared as integers, so for const item this time-consuming conversion can be done only once, not for every single comparison */ - if (args[0]->type() == FIELD_ITEM && + if (args[0]->real_item()->type() == FIELD_ITEM && thd->lex->sql_command != SQLCOM_CREATE_VIEW && thd->lex->sql_command != SQLCOM_SHOW_CREATE) { - Field *field=((Item_field*) args[0])->field; + Field *field=((Item_field*) (args[0]->real_item()))->field; if (field->can_be_compared_as_longlong()) { /* @@ -4129,11 +4129,9 @@ longlong Item_equal::val_int() void Item_equal::fix_length_and_dec() { - Item *item= const_item ? const_item : get_first(); + Item *item= get_first(); eval_item= cmp_item::get_comparator(item->result_type(), item->collation.collation); - if (item->result_type() == STRING_RESULT) - eval_item->cmp_charset= cmp_collation.collation; } bool Item_equal::walk(Item_processor processor, bool walk_subquery, byte *arg) diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index f1ec33d1c3e..8b13d3df7a5 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -1378,7 +1378,6 @@ class Item_equal: public Item_bool_func Item *const_item; /* optional constant item equal to fields items */ cmp_item *eval_item; bool cond_false; - DTCollation cmp_collation; public: inline Item_equal() : Item_bool_func(), const_item(0), eval_item(0), cond_false(0) diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index e8398e5ebb2..8a8788c7f72 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -828,6 +828,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, char* packet, uint packet_length); void log_slow_statement(THD *thd); bool check_dup(const char *db, const char *name, TABLE_LIST *tables); +bool compare_record(TABLE *table, query_id_t query_id); bool append_file_to_dir(THD *thd, const char **filename_ptr, const char *table_name); @@ -1097,7 +1098,8 @@ int fill_schema_user_privileges(THD *thd, TABLE_LIST *tables, COND *cond); int fill_schema_schema_privileges(THD *thd, TABLE_LIST *tables, COND *cond); int fill_schema_table_privileges(THD *thd, TABLE_LIST *tables, COND *cond); int fill_schema_column_privileges(THD *thd, TABLE_LIST *tables, COND *cond); -bool get_schema_tables_result(JOIN *join); +bool get_schema_tables_result(JOIN *join, + enum enum_schema_table_state executed_place); #define is_schema_db(X) \ !my_strcasecmp(system_charset_info, information_schema_name.str, (X)) diff --git a/sql/opt_range.cc b/sql/opt_range.cc index f613b1b9f02..2e31b72fa5c 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -5595,7 +5595,22 @@ get_mm_leaf(RANGE_OPT_PARAM *param, COND *conf_func, Field *field, err= value->save_in_field_no_warnings(field, 1); if (err > 0 && field->cmp_type() != value->result_type()) { - tree= 0; + if ((type == Item_func::EQ_FUNC || type == Item_func::EQUAL_FUNC) && + value->result_type() == item_cmp_type(field->result_type(), + value->result_type())) + + { + tree= new (alloc) SEL_ARG(field, 0, 0); + tree->type= SEL_ARG::IMPOSSIBLE; + } + else + { + /* + TODO: We should return trees of the type SEL_ARG::IMPOSSIBLE + for the cases like int_field > 999999999999999999999999 as well. + */ + tree= 0; + } goto end; } if (err < 0) @@ -10158,14 +10173,13 @@ int QUICK_GROUP_MIN_MAX_SELECT::reset(void) DBUG_ENTER("QUICK_GROUP_MIN_MAX_SELECT::reset"); file->extra(HA_EXTRA_KEYREAD); /* We need only the key attributes */ - result= file->ha_index_init(index, 1); - result= file->index_last(record); - if (result == HA_ERR_END_OF_FILE) - DBUG_RETURN(0); - if (result) + if ((result= file->ha_index_init(index))) DBUG_RETURN(result); if (quick_prefix_select && quick_prefix_select->reset()) DBUG_RETURN(1); + result= file->index_last(record); + if (result == HA_ERR_END_OF_FILE) + DBUG_RETURN(0); /* Save the prefix of the last group. */ key_copy(last_prefix, record, index_info, group_prefix_len); @@ -10214,7 +10228,7 @@ int QUICK_GROUP_MIN_MAX_SELECT::get_next() #else int result; #endif - int is_last_prefix; + int is_last_prefix= 0; DBUG_ENTER("QUICK_GROUP_MIN_MAX_SELECT::get_next"); @@ -10229,13 +10243,18 @@ int QUICK_GROUP_MIN_MAX_SELECT::get_next() Check if this is the last group prefix. Notice that at this point this->record contains the current prefix in record format. */ - is_last_prefix= key_cmp(index_info->key_part, last_prefix, - group_prefix_len); - DBUG_ASSERT(is_last_prefix <= 0); - if (result == HA_ERR_KEY_NOT_FOUND) - continue; - if (result) + if (!result) + { + is_last_prefix= key_cmp(index_info->key_part, last_prefix, + group_prefix_len); + DBUG_ASSERT(is_last_prefix <= 0); + } + else + { + if (result == HA_ERR_KEY_NOT_FOUND) + continue; break; + } if (have_min) { diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index aaffa09b978..bf753c72c83 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1203,25 +1203,30 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) !table->file->is_fatal_error(error, HA_CHECK_DUP_KEY)) { table->file->restore_auto_increment(prev_insert_id); + goto ok_or_after_trg_err; } goto err; - } - info->updated++; - /* - If ON DUP KEY UPDATE updates a row instead of inserting one, it's - like a regular UPDATE statement: it should not affect the value of a - next SELECT LAST_INSERT_ID() or mysql_insert_id(). - Except if LAST_INSERT_ID(#) was in the INSERT query, which is - handled separately by THD::arg_of_last_insert_id_function. - */ - insert_id_for_cur_row= table->file->insert_id_for_cur_row= 0; - if (table->next_number_field) - table->file->adjust_next_insert_id_after_explicit_value(table->next_number_field->val_int()); - trg_error= (table->triggers && - table->triggers->process_triggers(thd, TRG_EVENT_UPDATE, - TRG_ACTION_AFTER, TRUE)); - info->copied++; + } + if ((table->file->table_flags() & HA_PARTIAL_COLUMN_READ) || + compare_record(table, query_id)) + { + info->updated++; + /* + If ON DUP KEY UPDATE updates a row instead of inserting one, it's + like a regular UPDATE statement: it should not affect the value of a + next SELECT LAST_INSERT_ID() or mysql_insert_id(). + Except if LAST_INSERT_ID(#) was in the INSERT query, which is + handled separately by THD::arg_of_last_insert_id_function. + */ + insert_id_for_cur_row= table->file->insert_id_for_cur_row= 0; + if (table->next_number_field) + table->file->adjust_next_insert_id_after_explicit_value(table->next_number_field->val_int()); + trg_error= (table->triggers && + table->triggers->process_triggers(thd, TRG_EVENT_UPDATE, + TRG_ACTION_AFTER, TRUE)); + info->copied++; + } goto ok_or_after_trg_err; } else /* DUP_REPLACE */ diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 35db3e40930..af2929b6268 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1773,7 +1773,6 @@ bool st_lex::can_be_merged() } return (selects_allow_merge && - select_lex.order_list.elements == 0 && select_lex.group_list.elements == 0 && select_lex.having == 0 && select_lex.with_sum_func == 0 && diff --git a/sql/sql_select.cc b/sql/sql_select.cc index ea69eb72b51..711c37bdc86 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1507,7 +1507,7 @@ JOIN::exec() if ((curr_join->select_lex->options & OPTION_SCHEMA_TABLE) && !thd->lex->describe && - get_schema_tables_result(curr_join)) + get_schema_tables_result(curr_join, PROCESSED_BY_JOIN_EXEC)) { DBUG_VOID_RETURN; } @@ -12619,7 +12619,7 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order, /* Fill schema tables with data before filesort if it's necessary */ if ((join->select_lex->options & OPTION_SCHEMA_TABLE) && !thd->lex->describe && - get_schema_tables_result(join)) + get_schema_tables_result(join, PROCESSED_BY_CREATE_SORT_INDEX)) goto err; if (table->s->tmp_table) diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 2ca64b9d5ed..99fb0fd4236 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -5050,13 +5050,15 @@ int make_schema_select(THD *thd, SELECT_LEX *sel, SYNOPSIS get_schema_tables_result() join join which use schema tables + executed_place place where I_S table processed RETURN FALSE success TRUE error */ -bool get_schema_tables_result(JOIN *join) +bool get_schema_tables_result(JOIN *join, + enum enum_schema_table_state executed_place) { JOIN_TAB *tmp_join_tab= join->join_tab+join->tables; THD *thd= join->thd; @@ -5076,14 +5078,24 @@ bool get_schema_tables_result(JOIN *join) bool is_subselect= (&lex->unit != lex->current_select->master_unit() && lex->current_select->master_unit()->item); /* - The schema table is already processed and - the statement is not a subselect. - So we don't need to handle this table again. + If schema table is already processed and + the statement is not a subselect then + we don't need to fill this table again. + If schema table is already processed and + schema_table_state != executed_place then + table is already processed and + we should skip second data processing. */ - if (table_list->is_schema_table_processed && !is_subselect) + if (table_list->schema_table_state && + (!is_subselect || table_list->schema_table_state != executed_place)) continue; - if (is_subselect) // is subselect + /* + if table is used in a subselect and + table has been processed earlier with the same + 'executed_place' value then we should refresh the table. + */ + if (table_list->schema_table_state && is_subselect) { table_list->table->file->extra(HA_EXTRA_NO_CACHE); table_list->table->file->extra(HA_EXTRA_RESET_STATE); @@ -5100,10 +5112,10 @@ bool get_schema_tables_result(JOIN *join) { result= 1; join->error= 1; - table_list->is_schema_table_processed= TRUE; + table_list->schema_table_state= executed_place; break; } - table_list->is_schema_table_processed= TRUE; + table_list->schema_table_state= executed_place; } } thd->no_warnings_for_error= 0; diff --git a/sql/sql_update.cc b/sql/sql_update.cc index baccb3358f7..1205514cfd1 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -26,7 +26,7 @@ /* Return 0 if row hasn't changed */ -static bool compare_record(TABLE *table) +bool compare_record(TABLE *table, query_id_t query_id) { if (table->s->blob_fields + table->s->varchar_fields == 0) return cmp_record(table,record[1]); @@ -1569,6 +1569,15 @@ int multi_update::do_updates(bool from_send_error) if (!can_compare_record || compare_record(table)) { + int error; + if ((error= cur_table->view_check_option(thd, ignore)) != + VIEW_CHECK_OK) + { + if (error == VIEW_CHECK_SKIP) + continue; + else if (error == VIEW_CHECK_ERROR) + goto err; + } if ((local_error=table->file->ha_update_row(table->record[1], table->record[0]))) { diff --git a/sql/sql_view.cc b/sql/sql_view.cc index eb3de565d9f..7675c854b81 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -1272,6 +1272,7 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table, but it will not be included to SELECT_LEX tree, because it will not be executed */ + table->select_lex->order_list.push_back(&lex->select_lex.order_list); goto ok; } diff --git a/sql/table.cc b/sql/table.cc index fca9711115c..ed3cac85214 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -4086,7 +4086,7 @@ void st_table_list::reinit_before_use(THD *thd) */ table= 0; /* Reset is_schema_table_processed value(needed for I_S tables */ - is_schema_table_processed= FALSE; + schema_table_state= NOT_PROCESSED; TABLE_LIST *embedded; /* The table at the current level of nesting. */ TABLE_LIST *parent_embedding= this; /* The parent nested table reference. */ diff --git a/sql/table.h b/sql/table.h index 2923eb1db7b..fc2f25f3aa8 100644 --- a/sql/table.h +++ b/sql/table.h @@ -471,6 +471,12 @@ struct st_table { }; +enum enum_schema_table_state +{ + NOT_PROCESSED= 0, + PROCESSED_BY_CREATE_SORT_INDEX, + PROCESSED_BY_JOIN_EXEC +}; typedef struct st_foreign_key_info { @@ -730,7 +736,6 @@ typedef struct st_table_list st_select_lex_unit *derived; /* SELECT_LEX_UNIT of derived table */ ST_SCHEMA_TABLE *schema_table; /* Information_schema table */ st_select_lex *schema_select_lex; - bool is_schema_table_processed; /* True when the view field translation table is used to convert schema table fields for backwards compatibility with SHOW command. @@ -840,6 +845,7 @@ typedef struct st_table_list */ bool prelocking_placeholder; + enum enum_schema_table_state schema_table_state; void calc_md5(char *buffer); void set_underlying_merge(); int view_check_option(THD *thd, bool ignore_failure); |