summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorigor@olga.mysql.com <>2007-02-13 01:34:36 -0800
committerigor@olga.mysql.com <>2007-02-13 01:34:36 -0800
commitfb9e0ad3be786c69ffe24a5a60fc70dc53675c8d (patch)
tree0ebadd1cbf0ccf30ae7b01d82842db102e6a9fb3 /sql
parent4aab8494e9dab70f7ccd70f3033122580c729ffe (diff)
parent30614d22c195f25d7b59fb2651cfaca15697002c (diff)
downloadmariadb-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.h4
-rw-r--r--sql/field_conv.cc15
-rw-r--r--sql/item.cc20
-rw-r--r--sql/item_cmpfunc.cc8
-rw-r--r--sql/item_cmpfunc.h1
-rw-r--r--sql/mysql_priv.h4
-rw-r--r--sql/opt_range.cc45
-rw-r--r--sql/sql_insert.cc37
-rw-r--r--sql/sql_lex.cc1
-rw-r--r--sql/sql_select.cc4
-rw-r--r--sql/sql_show.cc28
-rw-r--r--sql/sql_update.cc11
-rw-r--r--sql/sql_view.cc1
-rw-r--r--sql/table.cc2
-rw-r--r--sql/table.h8
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);