summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorAlexey Kopytov <Alexey.Kopytov@Sun.com>2010-03-20 23:23:42 +0300
committerAlexey Kopytov <Alexey.Kopytov@Sun.com>2010-03-20 23:23:42 +0300
commitacc2b9e3662cd868f5108b1b4ee7257d95582f02 (patch)
tree772f4ae43ad7ce905f024b77bebdd1897d813391 /sql
parent41f23283e54d311155959faf58ae7edf81803ca3 (diff)
parent84917914e01415cbbc2a128cabc344c127e76db1 (diff)
downloadmariadb-git-acc2b9e3662cd868f5108b1b4ee7257d95582f02.tar.gz
Manual merge of mysql-5.1-bugteam to mysql-trunk-merge.
Conflicts: Text conflict in mysql-test/r/partition_innodb.result Text conflict in sql/field.h Text conflict in sql/item.h Text conflict in sql/item_cmpfunc.h Text conflict in sql/item_sum.h Text conflict in sql/log_event_old.cc Text conflict in sql/protocol.cc Text conflict in sql/sql_select.cc Text conflict in sql/sql_yacc.yy
Diffstat (limited to 'sql')
-rw-r--r--sql/field.cc76
-rw-r--r--sql/field.h21
-rw-r--r--sql/ha_partition.cc16
-rw-r--r--sql/item.cc28
-rw-r--r--sql/item.h21
-rw-r--r--sql/item_cmpfunc.cc26
-rw-r--r--sql/item_cmpfunc.h4
-rw-r--r--sql/item_create.cc30
-rw-r--r--sql/item_create.h8
-rw-r--r--sql/item_row.cc4
-rw-r--r--sql/item_row.h4
-rw-r--r--sql/item_subselect.cc8
-rw-r--r--sql/item_sum.cc10
-rw-r--r--sql/item_sum.h4
-rw-r--r--sql/log.cc7
-rw-r--r--sql/log_event.cc10
-rw-r--r--sql/log_event.h10
-rw-r--r--sql/log_event_old.cc72
-rw-r--r--sql/opt_sum.cc96
-rw-r--r--sql/protocol.cc5
-rw-r--r--sql/rpl_utility.cc2
-rw-r--r--sql/rpl_utility.h11
-rw-r--r--sql/sql_partition.cc17
-rw-r--r--sql/sql_plugin.cc2
-rw-r--r--sql/sql_profile.cc12
-rw-r--r--sql/sql_select.cc40
-rw-r--r--sql/sql_table.cc46
-rw-r--r--sql/sql_yacc.yy6
-rw-r--r--sql/table.cc4
29 files changed, 398 insertions, 202 deletions
diff --git a/sql/field.cc b/sql/field.cc
index 5fe031a38b9..ad6b14d4b0a 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -1,4 +1,4 @@
-/* Copyright 2000-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.
+/* Copyright (c) 2000, 2010 Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -1401,12 +1401,14 @@ bool Field::send_binary(Protocol *protocol)
to the size of this field (the slave or destination).
@param field_metadata Encoded size in field metadata
+ @param mflags Flags from the table map event for the table.
@retval 0 if this field's size is < the source field's size
@retval 1 if this field's size is >= the source field's size
*/
int Field::compatible_field_size(uint field_metadata,
- const Relay_log_info *rli_arg __attribute__((unused)))
+ const Relay_log_info *rli_arg __attribute__((unused)),
+ uint16 mflags __attribute__((unused)))
{
uint const source_size= pack_length_from_metadata(field_metadata);
uint const destination_size= row_pack_length();
@@ -2906,7 +2908,8 @@ uint Field_new_decimal::pack_length_from_metadata(uint field_metadata)
@retval 1 if this field's size is >= the source field's size
*/
int Field_new_decimal::compatible_field_size(uint field_metadata,
- const Relay_log_info * __attribute__((unused)))
+ const Relay_log_info * __attribute__((unused)),
+ uint16 mflags __attribute__((unused)))
{
int compatible= 0;
uint const source_precision= (field_metadata >> 8U) & 0x00ff;
@@ -2971,16 +2974,16 @@ Field_new_decimal::unpack(uchar* to,
a decimal and write that to the raw data buffer.
*/
decimal_digit_t dec_buf[DECIMAL_MAX_PRECISION];
- decimal_t dec;
- dec.len= from_precision;
- dec.buf= dec_buf;
+ decimal_t dec_val;
+ dec_val.len= from_precision;
+ dec_val.buf= dec_buf;
/*
Note: bin2decimal does not change the length of the field. So it is
just the first step the resizing operation. The second step does the
resizing using the precision and decimals from the slave.
*/
- bin2decimal((uchar *)from, &dec, from_precision, from_decimal);
- decimal2bin(&dec, to, precision, decimals());
+ bin2decimal((uchar *)from, &dec_val, from_precision, from_decimal);
+ decimal2bin(&dec_val, to, precision, decimals());
}
else
memcpy(to, from, len); // Sizes are the same, just copy the data.
@@ -6361,7 +6364,7 @@ check_string_copy_error(Field_str *field,
SYNOPSIS
Field_longstr::report_if_important_data()
- ptr - Truncated rest of string
+ pstr - Truncated rest of string
end - End of truncated string
count_spaces - Treat traling spaces as important data
@@ -6377,12 +6380,12 @@ check_string_copy_error(Field_str *field,
*/
int
-Field_longstr::report_if_important_data(const char *ptr, const char *end,
+Field_longstr::report_if_important_data(const char *pstr, const char *end,
bool count_spaces)
{
- if ((ptr < end) && table->in_use->count_cuted_fields)
+ if ((pstr < end) && table->in_use->count_cuted_fields)
{
- if (test_if_important_data(field_charset, ptr, end))
+ if (test_if_important_data(field_charset, pstr, end))
{
if (table->in_use->abort_on_warning)
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_DATA_TOO_LONG, 1);
@@ -6675,7 +6678,8 @@ check_field_for_37426(const void *param_arg)
#endif
int Field_string::compatible_field_size(uint field_metadata,
- const Relay_log_info *rli_arg)
+ const Relay_log_info *rli_arg,
+ uint16 mflags __attribute__((unused)))
{
#ifdef HAVE_REPLICATION
const Check_field_param check_param = { this };
@@ -6683,7 +6687,7 @@ int Field_string::compatible_field_size(uint field_metadata,
check_field_for_37426, &check_param))
return FALSE; // Not compatible field sizes
#endif
- return Field::compatible_field_size(field_metadata, rli_arg);
+ return Field::compatible_field_size(field_metadata, rli_arg, mflags);
}
@@ -7027,9 +7031,8 @@ const uint Field_varstring::MAX_SIZE= UINT_MAX16;
*/
int Field_varstring::do_save_field_metadata(uchar *metadata_ptr)
{
- char *ptr= (char *)metadata_ptr;
DBUG_ASSERT(field_length <= 65535);
- int2store(ptr, field_length);
+ int2store((char*)metadata_ptr, field_length);
return 2;
}
@@ -9265,8 +9268,13 @@ uint Field_bit::get_key_image(uchar *buff, uint length, imagetype type_arg)
*/
int Field_bit::do_save_field_metadata(uchar *metadata_ptr)
{
- *metadata_ptr= bit_len;
- *(metadata_ptr + 1)= bytes_in_rec;
+ /*
+ Since this class and Field_bit_as_char have different ideas of
+ what should be stored here, we compute the values of the metadata
+ explicitly using the field_length.
+ */
+ metadata_ptr[0]= field_length % 8;
+ metadata_ptr[1]= field_length / 8;
return 2;
}
@@ -9306,20 +9314,26 @@ uint Field_bit::pack_length_from_metadata(uint field_metadata)
@retval 1 if this field's size is >= the source field's size
*/
int Field_bit::compatible_field_size(uint field_metadata,
- const Relay_log_info * __attribute__((unused)))
+ const Relay_log_info * __attribute__((unused)),
+ uint16 mflags)
{
- int compatible= 0;
- uint const source_size= pack_length_from_metadata(field_metadata);
- uint const destination_size= row_pack_length();
- uint const from_bit_len= field_metadata & 0x00ff;
- uint const from_len= (field_metadata >> 8U) & 0x00ff;
- if ((bit_len == 0) || (from_bit_len == 0))
- compatible= (source_size <= destination_size);
- else if (from_bit_len > bit_len)
- compatible= (from_len < bytes_in_rec);
- else
- compatible= ((from_bit_len <= bit_len) && (from_len <= bytes_in_rec));
- return (compatible);
+ uint from_bit_len= 8 * (field_metadata >> 8) + (field_metadata & 0xff);
+ uint to_bit_len= max_display_length();
+
+ /*
+ If the bit length exact flag is clear, we are dealing with an old
+ master, so we allow some less strict behaviour if replicating by
+ moving both bit lengths to an even multiple of 8.
+
+ We do this by computing the number of bytes to store the field
+ instead, and then compare the result.
+ */
+ if (!(mflags & Table_map_log_event::TM_BIT_LEN_EXACT_F)) {
+ from_bit_len= (from_bit_len + 7) / 8;
+ to_bit_len= (to_bit_len + 7) / 8;
+ }
+
+ return from_bit_len <= to_bit_len;
}
diff --git a/sql/field.h b/sql/field.h
index 8cfed9647f7..6cffbd2be57 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -1,7 +1,7 @@
#ifndef FIELD_INCLUDED
#define FIELD_INCLUDED
-/* Copyright 2000-2008 MySQL AB, 2008, 2009 Sun Microsystems, Inc.
+/* Copyright (c) 2000, 2010 Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -14,7 +14,7 @@
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
/*
Because of the function new_field() all field classes that have static
@@ -58,7 +58,11 @@ public:
static void operator delete(void *ptr_arg, size_t size) { TRASH(ptr_arg, size); }
uchar *ptr; // Position to field in record
- uchar *null_ptr; // Byte where null_bit is
+ /**
+ Byte where the @c NULL bit is stored inside a record. If this Field is a
+ @c NOT @c NULL field, this member is @c NULL.
+ */
+ uchar *null_ptr;
/*
Note that you can use table->in_use as replacement for current_thd member
only inside of val_*() and store() members (e.g. you can't use it in cons)
@@ -168,7 +172,7 @@ public:
*/
virtual uint32 pack_length_in_rec() const { return pack_length(); }
virtual int compatible_field_size(uint field_metadata,
- const Relay_log_info *);
+ const Relay_log_info *, uint16 mflags);
virtual uint pack_length_from_metadata(uint field_metadata)
{ return field_metadata; }
/*
@@ -264,6 +268,9 @@ public:
inline void set_notnull(my_ptrdiff_t row_offset= 0)
{ if (null_ptr) null_ptr[row_offset]&= (uchar) ~null_bit; }
inline bool maybe_null(void) { return null_ptr != 0 || table->maybe_null; }
+ /**
+ Signals that this field is NULL-able.
+ */
inline bool real_maybe_null(void) { return null_ptr != 0; }
enum {
@@ -806,7 +813,7 @@ public:
uint pack_length_from_metadata(uint field_metadata);
uint row_pack_length() { return pack_length(); }
int compatible_field_size(uint field_metadata,
- const Relay_log_info *rli);
+ const Relay_log_info *rli, uint16 mflags);
uint is_equal(Create_field *new_field);
virtual const uchar *unpack(uchar* to, const uchar *from,
uint param_data, bool low_byte_first);
@@ -1502,7 +1509,7 @@ public:
return (((field_metadata >> 4) & 0x300) ^ 0x300) + (field_metadata & 0x00ff);
}
int compatible_field_size(uint field_metadata,
- const Relay_log_info *rli);
+ const Relay_log_info *rli, uint16 mflags);
uint row_pack_length() { return (field_length + 1); }
int pack_cmp(const uchar *a,const uchar *b,uint key_length,
my_bool insert_or_update);
@@ -1974,7 +1981,7 @@ public:
uint row_pack_length()
{ return (bytes_in_rec + ((bit_len > 0) ? 1 : 0)); }
int compatible_field_size(uint field_metadata,
- const Relay_log_info *rli);
+ const Relay_log_info *rli, uint16 mflags);
void sql_type(String &str) const;
virtual uchar *pack(uchar *to, const uchar *from,
uint max_length, bool low_byte_first);
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index b287128471a..d8bf78f16cb 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -5240,6 +5240,7 @@ int ha_partition::info(uint flag)
file= m_file[handler_instance];
file->info(HA_STATUS_CONST);
+ stats.block_size= file->stats.block_size;
stats.create_time= file->stats.create_time;
ref_length= m_ref_length;
}
@@ -6606,9 +6607,22 @@ void ha_partition::release_auto_increment()
ulonglong next_auto_inc_val;
lock_auto_increment();
next_auto_inc_val= ha_data->next_auto_inc_val;
+ /*
+ If the current auto_increment values is lower than the reserved
+ value, and the reserved value was reserved by this thread,
+ we can lower the reserved value.
+ */
if (next_insert_id < next_auto_inc_val &&
auto_inc_interval_for_cur_row.maximum() >= next_auto_inc_val)
- ha_data->next_auto_inc_val= next_insert_id;
+ {
+ THD *thd= ha_thd();
+ /*
+ Check that we do not lower the value because of a failed insert
+ with SET INSERT_ID, i.e. forced/non generated values.
+ */
+ if (thd->auto_inc_intervals_forced.maximum() < next_insert_id)
+ ha_data->next_auto_inc_val= next_insert_id;
+ }
DBUG_PRINT("info", ("ha_data->next_auto_inc_val: %lu",
(ulong) ha_data->next_auto_inc_val));
diff --git a/sql/item.cc b/sql/item.cc
index 921976d75a4..a2a7d77e853 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -557,6 +557,18 @@ Item_ident::Item_ident(Name_resolution_context *context_arg,
}
+Item_ident::Item_ident(TABLE_LIST *view_arg, const char *field_name_arg)
+ :orig_db_name(NullS), orig_table_name(view_arg->table_name),
+ orig_field_name(field_name_arg), context(&view_arg->view->select_lex.context),
+ db_name(NullS), table_name(view_arg->alias),
+ field_name(field_name_arg),
+ alias_name_used(FALSE), cached_field_index(NO_CACHED_FIELD_INDEX),
+ cached_table(NULL), depended_from(NULL)
+{
+ name = (char*) field_name_arg;
+}
+
+
/**
Constructor used by Item_field & Item_*_ref (see Item comment)
*/
@@ -5885,6 +5897,20 @@ Item_ref::Item_ref(Name_resolution_context *context_arg,
}
+Item_ref::Item_ref(TABLE_LIST *view_arg, Item **item,
+ const char *field_name_arg, bool alias_name_used_arg)
+ :Item_ident(view_arg, field_name_arg),
+ result_field(NULL), ref(item)
+{
+ alias_name_used= alias_name_used_arg;
+ /*
+ This constructor is used to create some internal references over fixed items
+ */
+ if (ref && *ref && (*ref)->fixed)
+ set_properties();
+}
+
+
/**
Resolve the name of a reference to a column reference.
@@ -7297,7 +7323,7 @@ double Item_cache_decimal::val_real()
DBUG_ASSERT(fixed);
double res;
if (!value_cached && !cache_value())
- return NULL;
+ return 0.0;
my_decimal2double(E_DEC_FATAL_ERROR, &decimal_value, &res);
return res;
}
diff --git a/sql/item.h b/sql/item.h
index 31c8238a32e..9ca94064bd7 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -1,7 +1,7 @@
#ifndef ITEM_INCLUDED
#define ITEM_INCLUDED
-/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc.
+/* Copyright (c) 2000, 2010 Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -1419,6 +1419,7 @@ public:
const char *db_name_arg, const char *table_name_arg,
const char *field_name_arg);
Item_ident(THD *thd, Item_ident *item);
+ Item_ident(TABLE_LIST *view_arg, const char *field_name_arg);
const char *full_name() const;
void cleanup();
bool remove_dependence_processor(uchar * arg);
@@ -2260,6 +2261,8 @@ public:
Item_ref(Name_resolution_context *context_arg, Item **item,
const char *table_name_arg, const char *field_name_arg,
bool alias_name_used_arg= FALSE);
+ Item_ref(TABLE_LIST *view_arg, Item **item,
+ const char *field_name_arg, bool alias_name_used_arg= FALSE);
/* Constructor need to process subselect with temporary tables (see Item) */
Item_ref(THD *thd, Item_ref *item)
@@ -2355,6 +2358,11 @@ public:
if (ref && result_type() == ROW_RESULT)
(*ref)->bring_value();
}
+ bool get_time(MYSQL_TIME *ltime)
+ {
+ DBUG_ASSERT(fixed);
+ return (*ref)->get_time(ltime);
+ }
};
@@ -2375,6 +2383,12 @@ public:
{}
/* Constructor need to process subselect with temporary tables (see Item) */
Item_direct_ref(THD *thd, Item_direct_ref *item) : Item_ref(thd, item) {}
+ Item_direct_ref(TABLE_LIST *view_arg, Item **item,
+ const char *field_name_arg,
+ bool alias_name_used_arg= FALSE)
+ :Item_ref(view_arg, item, field_name_arg,
+ alias_name_used_arg)
+ {}
double val_real();
longlong val_int();
@@ -2400,6 +2414,10 @@ public:
/* Constructor need to process subselect with temporary tables (see Item) */
Item_direct_view_ref(THD *thd, Item_direct_ref *item)
:Item_direct_ref(thd, item) {}
+ Item_direct_view_ref(TABLE_LIST *view_arg, Item **item,
+ const char *field_name_arg)
+ :Item_direct_ref(view_arg, item, field_name_arg)
+ {}
bool fix_fields(THD *, Item **);
bool eq(const Item *item, bool binary_cmp) const;
@@ -3053,6 +3071,7 @@ public:
Item_cache_int(enum_field_types field_type_arg):
Item_cache(field_type_arg), value(0) {}
+ virtual void store(Item *item){ Item_cache::store(item); }
void store(Item *item, longlong val_arg);
double val_real();
longlong val_int();
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 1d33e369af0..cd3f18fe1eb 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000-2006 MySQL AB
+/* Copyright (c) 2000, 2010 Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -1022,12 +1022,12 @@ bool Arg_comparator::try_year_cmp_func(Item_result type)
@return cache item or original value.
*/
-Item** Arg_comparator::cache_converted_constant(THD *thd, Item **value,
+Item** Arg_comparator::cache_converted_constant(THD *thd_arg, Item **value,
Item **cache_item,
Item_result type)
{
/* Don't need cache if doing context analysis only. */
- if (!thd->is_context_analysis_only() &&
+ if (!thd_arg->is_context_analysis_only() &&
(*value)->const_item() && type != (*value)->result_type())
{
Item_cache *cache= Item_cache::get_cache(*value, type);
@@ -1368,12 +1368,12 @@ int Arg_comparator::compare_real()
int Arg_comparator::compare_decimal()
{
- my_decimal value1;
- my_decimal *val1= (*a)->val_decimal(&value1);
+ my_decimal decimal1;
+ my_decimal *val1= (*a)->val_decimal(&decimal1);
if (!(*a)->null_value)
{
- my_decimal value2;
- my_decimal *val2= (*b)->val_decimal(&value2);
+ my_decimal decimal2;
+ my_decimal *val2= (*b)->val_decimal(&decimal2);
if (!(*b)->null_value)
{
if (set_null)
@@ -1397,9 +1397,9 @@ int Arg_comparator::compare_e_real()
int Arg_comparator::compare_e_decimal()
{
- my_decimal value1, value2;
- my_decimal *val1= (*a)->val_decimal(&value1);
- my_decimal *val2= (*b)->val_decimal(&value2);
+ my_decimal decimal1, decimal2;
+ my_decimal *val1= (*a)->val_decimal(&decimal1);
+ my_decimal *val2= (*b)->val_decimal(&decimal2);
if ((*a)->null_value || (*b)->null_value)
return test((*a)->null_value && (*b)->null_value);
return test(my_decimal_cmp(val1, val2) == 0);
@@ -5402,11 +5402,11 @@ void Item_equal::merge(Item_equal *item)
members follow in a wrong order they are swapped. This is performed
again and again until we get all members in a right order.
- @param cmp function to compare field item
+ @param compare function to compare field item
@param arg context extra parameter for the cmp function
*/
-void Item_equal::sort(Item_field_cmpfunc cmp, void *arg)
+void Item_equal::sort(Item_field_cmpfunc compare, void *arg)
{
bool swap;
List_iterator<Item_field> it(fields);
@@ -5420,7 +5420,7 @@ void Item_equal::sort(Item_field_cmpfunc cmp, void *arg)
while ((item2= it++))
{
Item_field **ref2= it.ref();
- if (cmp(item1, item2, arg) < 0)
+ if (compare(item1, item2, arg) < 0)
{
Item_field *item= *ref1;
*ref1= *ref2;
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index c3afeebb577..7cfc5b5396f 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -1,7 +1,7 @@
#ifndef ITEM_CMPFUNC_INCLUDED
#define ITEM_CMPFUNC_INCLUDED
-/* Copyright (C) 2000-2003 MySQL AB
+/* Copyright (c) 2000, 2010 Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -1619,7 +1619,7 @@ public:
longlong val_int();
const char *func_name() const { return "multiple equal"; }
optimize_type select_optimize() const { return OPTIMIZE_EQUAL; }
- void sort(Item_field_cmpfunc cmp, void *arg);
+ void sort(Item_field_cmpfunc compare, void *arg);
friend class Item_equal_iterator;
void fix_length_and_dec();
bool fix_fields(THD *thd, Item **ref);
diff --git a/sql/item_create.cc b/sql/item_create.cc
index cdd87af4c37..2b63e869d46 100644
--- a/sql/item_create.cc
+++ b/sql/item_create.cc
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000-2003 MySQL AB
+/* Copyright (c) 2000, 2010 Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -42,7 +42,7 @@
class Create_native_func : public Create_func
{
public:
- virtual Item *create(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item *create_func(THD *thd, LEX_STRING name, List<Item> *item_list);
/**
Builder method, with no arguments.
@@ -69,7 +69,7 @@ protected:
class Create_func_arg0 : public Create_func
{
public:
- virtual Item *create(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item *create_func(THD *thd, LEX_STRING name, List<Item> *item_list);
/**
Builder method, with no arguments.
@@ -93,7 +93,7 @@ protected:
class Create_func_arg1 : public Create_func
{
public:
- virtual Item *create(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item *create_func(THD *thd, LEX_STRING name, List<Item> *item_list);
/**
Builder method, with one argument.
@@ -118,7 +118,7 @@ protected:
class Create_func_arg2 : public Create_func
{
public:
- virtual Item *create(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item *create_func(THD *thd, LEX_STRING name, List<Item> *item_list);
/**
Builder method, with two arguments.
@@ -144,7 +144,7 @@ protected:
class Create_func_arg3 : public Create_func
{
public:
- virtual Item *create(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item *create_func(THD *thd, LEX_STRING name, List<Item> *item_list);
/**
Builder method, with three arguments.
@@ -194,7 +194,7 @@ protected:
class Create_func_no_geom : public Create_func
{
public:
- virtual Item *create(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item *create_func(THD *thd, LEX_STRING name, List<Item> *item_list);
/** Singleton. */
static Create_func_no_geom s_singleton;
@@ -2327,7 +2327,7 @@ static bool has_named_parameters(List<Item> *params)
Create_func_no_geom Create_func_no_geom::s_singleton;
Item*
-Create_func_no_geom::create(THD * /* unused */,
+Create_func_no_geom::create_func(THD * /* unused */,
LEX_STRING /* unused */,
List<Item> * /* unused */)
{
@@ -2340,7 +2340,7 @@ Create_func_no_geom::create(THD * /* unused */,
Item*
-Create_qfunc::create(THD *thd, LEX_STRING name, List<Item> *item_list)
+Create_qfunc::create_func(THD *thd, LEX_STRING name, List<Item> *item_list)
{
LEX_STRING db;
@@ -2373,7 +2373,7 @@ Create_qfunc::create(THD *thd, LEX_STRING name, List<Item> *item_list)
Create_udf_func Create_udf_func::s_singleton;
Item*
-Create_udf_func::create(THD *thd, LEX_STRING name, List<Item> *item_list)
+Create_udf_func::create_func(THD *thd, LEX_STRING name, List<Item> *item_list)
{
udf_func *udf= find_udf(name.str, name.length);
DBUG_ASSERT(udf);
@@ -2524,7 +2524,7 @@ Create_sp_func::create(THD *thd, LEX_STRING db, LEX_STRING name,
Item*
-Create_native_func::create(THD *thd, LEX_STRING name, List<Item> *item_list)
+Create_native_func::create_func(THD *thd, LEX_STRING name, List<Item> *item_list)
{
if (has_named_parameters(item_list))
{
@@ -2537,7 +2537,7 @@ Create_native_func::create(THD *thd, LEX_STRING name, List<Item> *item_list)
Item*
-Create_func_arg0::create(THD *thd, LEX_STRING name, List<Item> *item_list)
+Create_func_arg0::create_func(THD *thd, LEX_STRING name, List<Item> *item_list)
{
int arg_count= 0;
@@ -2555,7 +2555,7 @@ Create_func_arg0::create(THD *thd, LEX_STRING name, List<Item> *item_list)
Item*
-Create_func_arg1::create(THD *thd, LEX_STRING name, List<Item> *item_list)
+Create_func_arg1::create_func(THD *thd, LEX_STRING name, List<Item> *item_list)
{
int arg_count= 0;
@@ -2581,7 +2581,7 @@ Create_func_arg1::create(THD *thd, LEX_STRING name, List<Item> *item_list)
Item*
-Create_func_arg2::create(THD *thd, LEX_STRING name, List<Item> *item_list)
+Create_func_arg2::create_func(THD *thd, LEX_STRING name, List<Item> *item_list)
{
int arg_count= 0;
@@ -2609,7 +2609,7 @@ Create_func_arg2::create(THD *thd, LEX_STRING name, List<Item> *item_list)
Item*
-Create_func_arg3::create(THD *thd, LEX_STRING name, List<Item> *item_list)
+Create_func_arg3::create_func(THD *thd, LEX_STRING name, List<Item> *item_list)
{
int arg_count= 0;
diff --git a/sql/item_create.h b/sql/item_create.h
index a3ba6bd26a6..d84c764a3d9 100644
--- a/sql/item_create.h
+++ b/sql/item_create.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000-2006 MySQL AB
+/* Copyright (c) 2000, 2010 Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -53,7 +53,7 @@ public:
@param item_list The list of arguments to the function, can be NULL
@return An item representing the parsed function call, or NULL
*/
- virtual Item *create(THD *thd, LEX_STRING name, List<Item> *item_list) = 0;
+ virtual Item *create_func(THD *thd, LEX_STRING name, List<Item> *item_list) = 0;
protected:
/** Constructor */
@@ -80,7 +80,7 @@ public:
@param item_list The list of arguments to the function, can be NULL
@return An item representing the parsed function call
*/
- virtual Item *create(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item *create_func(THD *thd, LEX_STRING name, List<Item> *item_list);
/**
The builder create method, for qualified functions.
@@ -127,7 +127,7 @@ extern Create_qfunc * find_qualified_function_builder(THD *thd);
class Create_udf_func : public Create_func
{
public:
- virtual Item *create(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item *create_func(THD *thd, LEX_STRING name, List<Item> *item_list);
/**
The builder create method, for User Defined Functions.
diff --git a/sql/item_row.cc b/sql/item_row.cc
index 29b37eb2bc0..7535c1fa80b 100644
--- a/sql/item_row.cc
+++ b/sql/item_row.cc
@@ -30,7 +30,8 @@
*/
Item_row::Item_row(List<Item> &arg):
- Item(), used_tables_cache(0), const_item_cache(1), with_null(0)
+ Item(), used_tables_cache(0), not_null_tables_cache(0),
+ const_item_cache(1), with_null(0)
{
//TODO: think placing 2-3 component items in item (as it done for function)
@@ -71,6 +72,7 @@ bool Item_row::fix_fields(THD *thd, Item **ref)
Item *item= *arg;
used_tables_cache |= item->used_tables();
const_item_cache&= item->const_item() && !with_null;
+ not_null_tables_cache|= item->not_null_tables();
/*
Some subqueries transformations aren't done in the view_prepare_mode thus
is_null() will fail. So we skip is_null() calculation for CREATE VIEW as
diff --git a/sql/item_row.h b/sql/item_row.h
index 7c08c5888e0..87988e718ca 100644
--- a/sql/item_row.h
+++ b/sql/item_row.h
@@ -19,7 +19,7 @@
class Item_row: public Item
{
Item **items;
- table_map used_tables_cache;
+ table_map used_tables_cache, not_null_tables_cache;
uint arg_count;
bool const_item_cache;
bool with_null;
@@ -29,6 +29,7 @@ public:
Item(),
items(item->items),
used_tables_cache(item->used_tables_cache),
+ not_null_tables_cache(0),
arg_count(item->arg_count),
const_item_cache(item->const_item_cache),
with_null(0)
@@ -68,6 +69,7 @@ public:
bool const_item() const { return const_item_cache; };
enum Item_result result_type() const { return ROW_RESULT; }
void update_used_tables();
+ table_map not_null_tables() const { return not_null_tables_cache; }
virtual void print(String *str, enum_query_type query_type);
bool walk(Item_processor processor, bool walk_subquery, uchar *arg);
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index a6499b9584c..502faacdf76 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -249,9 +249,13 @@ bool Item_subselect::exec()
{
int res;
- if (thd->is_error())
- /* Do not execute subselect in case of a fatal error */
+ /*
+ Do not execute subselect in case of a fatal error
+ or if the query has been killed.
+ */
+ if (thd->is_error() || thd->killed)
return 1;
+
/*
Simulate a failure in sub-query execution. Used to test e.g.
out of memory or query being killed conditions.
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index c6ac8a05150..6aa90fda759 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000-2003 MySQL AB
+/* Copyright (c) 2000, 2010 Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -1157,7 +1157,7 @@ Item_sum_hybrid::fix_fields(THD *thd, Item **ref)
default:
DBUG_ASSERT(0);
};
- setup(args[0], NULL);
+ setup_hybrid(args[0], NULL);
/* MIN/MAX can return NULL for empty set indepedent of the used column */
maybe_null= 1;
unsigned_flag=item->unsigned_flag;
@@ -1191,7 +1191,7 @@ Item_sum_hybrid::fix_fields(THD *thd, Item **ref)
of the original MIN/MAX object and it is saved in this object's cache.
*/
-void Item_sum_hybrid::setup(Item *item, Item *value_arg)
+void Item_sum_hybrid::setup_hybrid(Item *item, Item *value_arg)
{
value= Item_cache::get_cache(item);
value->setup(item);
@@ -1952,7 +1952,7 @@ void Item_sum_hybrid::no_rows_in_result()
Item *Item_sum_min::copy_or_same(THD* thd)
{
Item_sum_min *item= new (thd->mem_root) Item_sum_min(thd, this);
- item->setup(args[0], value);
+ item->setup_hybrid(args[0], value);
return item;
}
@@ -1975,7 +1975,7 @@ bool Item_sum_min::add()
Item *Item_sum_max::copy_or_same(THD* thd)
{
Item_sum_max *item= new (thd->mem_root) Item_sum_max(thd, this);
- item->setup(args[0], value);
+ item->setup_hybrid(args[0], value);
return item;
}
diff --git a/sql/item_sum.h b/sql/item_sum.h
index 88be83137cb..da3a1f639e0 100644
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@ -1,7 +1,7 @@
#ifndef ITEM_SUM_INCLUDED
#define ITEM_SUM_INCLUDED
-/* Copyright (C) 2000-2006 MySQL AB
+/* Copyright (c) 2000, 2010 Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -986,7 +986,7 @@ protected:
was_values(item->was_values)
{ }
bool fix_fields(THD *, Item **);
- void setup(Item *item, Item *value_arg);
+ void setup_hybrid(Item *item, Item *value_arg);
void clear();
double val_real();
longlong val_int();
diff --git a/sql/log.cc b/sql/log.cc
index 491a9a0ac43..8da05d1c4ad 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -4083,11 +4083,8 @@ int THD::binlog_write_table_map(TABLE *table, bool is_trans)
DBUG_ASSERT(current_stmt_binlog_row_based && mysql_bin_log.is_open());
DBUG_ASSERT(table->s->table_map_id != ULONG_MAX);
- Table_map_log_event::flag_set const
- flags= Table_map_log_event::TM_NO_FLAGS;
-
Table_map_log_event
- the_event(this, table, table->s->table_map_id, is_trans, flags);
+ the_event(this, table, table->s->table_map_id, is_trans);
if (is_trans && binlog_table_maps == 0)
binlog_start_trans_and_stmt();
@@ -4708,7 +4705,7 @@ int query_error_code(THD *thd, bool not_killed)
{
int error;
- if (not_killed)
+ if (not_killed || (thd->killed == THD::KILL_BAD_DATA))
{
error= thd->is_error() ? thd->stmt_da->sql_errno() : 0;
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 600c033fcc6..7a1462974a2 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -7902,7 +7902,7 @@ int Table_map_log_event::save_field_metadata()
*/
#if !defined(MYSQL_CLIENT)
Table_map_log_event::Table_map_log_event(THD *thd, TABLE *tbl, ulong tid,
- bool is_transactional, uint16 flags)
+ bool is_transactional)
: Log_event(thd, 0, true),
m_table(tbl),
m_dbnam(tbl->s->db.str),
@@ -7912,7 +7912,7 @@ Table_map_log_event::Table_map_log_event(THD *thd, TABLE *tbl, ulong tid,
m_colcnt(tbl->s->fields),
m_memory(NULL),
m_table_id(tid),
- m_flags(flags),
+ m_flags(TM_BIT_LEN_EXACT_F),
m_data_size(0),
m_field_metadata(0),
m_field_metadata_size(0),
@@ -8170,8 +8170,10 @@ int Table_map_log_event::do_apply_event(Relay_log_info const *rli)
inside Relay_log_info::clear_tables_to_lock() by calling the
table_def destructor explicitly.
*/
- new (&table_list->m_tabledef) table_def(m_coltype, m_colcnt,
- m_field_metadata, m_field_metadata_size, m_null_bits);
+ new (&table_list->m_tabledef)
+ table_def(m_coltype, m_colcnt,
+ m_field_metadata, m_field_metadata_size,
+ m_null_bits, m_flags);
table_list->m_tabledef_valid= TRUE;
/*
diff --git a/sql/log_event.h b/sql/log_event.h
index 0dcc5ebc71f..8776023b445 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -3319,16 +3319,14 @@ public:
/* Special constants representing sets of flags */
enum
{
- TM_NO_FLAGS = 0U
+ TM_NO_FLAGS = 0U,
+ TM_BIT_LEN_EXACT_F = (1U << 0)
};
- void set_flags(flag_set flag) { m_flags |= flag; }
- void clear_flags(flag_set flag) { m_flags &= ~flag; }
flag_set get_flags(flag_set flag) const { return m_flags & flag; }
#ifndef MYSQL_CLIENT
- Table_map_log_event(THD *thd, TABLE *tbl, ulong tid,
- bool is_transactional, uint16 flags);
+ Table_map_log_event(THD *thd, TABLE *tbl, ulong tid, bool is_transactional);
#endif
#ifdef HAVE_REPLICATION
Table_map_log_event(const char *buf, uint event_len,
@@ -3341,7 +3339,7 @@ public:
table_def *create_table_def()
{
return new table_def(m_coltype, m_colcnt, m_field_metadata,
- m_field_metadata_size, m_null_bits);
+ m_field_metadata_size, m_null_bits, m_flags);
}
ulong get_table_id() const { return m_table_id; }
const char *get_table_name() const { return m_tblnam; }
diff --git a/sql/log_event_old.cc b/sql/log_event_old.cc
index a91e2f251b1..b7b7be221b5 100644
--- a/sql/log_event_old.cc
+++ b/sql/log_event_old.cc
@@ -15,7 +15,7 @@ Old_rows_log_event::do_apply_event(Old_rows_log_event *ev, const Relay_log_info
{
DBUG_ENTER("Old_rows_log_event::do_apply_event(st_relay_log_info*)");
int error= 0;
- THD *thd= ev->thd;
+ THD *ev_thd= ev->thd;
uchar const *row_start= ev->m_rows_buf;
/*
@@ -33,17 +33,17 @@ Old_rows_log_event::do_apply_event(Old_rows_log_event *ev, const Relay_log_info
DBUG_ASSERT(ev->get_flags(Old_rows_log_event::STMT_END_F));
const_cast<Relay_log_info*>(rli)->clear_tables_to_lock();
- close_thread_tables(thd);
- thd->clear_error();
+ close_thread_tables(ev_thd);
+ ev_thd->clear_error();
DBUG_RETURN(0);
}
/*
- 'thd' has been set by exec_relay_log_event(), just before calling
+ 'ev_thd' has been set by exec_relay_log_event(), just before calling
do_apply_event(). We still check here to prevent future coding
errors.
*/
- DBUG_ASSERT(rli->sql_thd == thd);
+ DBUG_ASSERT(rli->sql_thd == ev_thd);
/*
If there is no locks taken, this is the first binrow event seen
@@ -51,10 +51,10 @@ Old_rows_log_event::do_apply_event(Old_rows_log_event *ev, const Relay_log_info
used in the transaction and proceed with execution of the actual
event.
*/
- if (!thd->lock)
+ if (!ev_thd->lock)
{
/*
- Lock_tables() reads the contents of thd->lex, so they must be
+ Lock_tables() reads the contents of ev_thd->lex, so they must be
initialized.
We also call the mysql_reset_thd_for_next_command(), since this
@@ -62,24 +62,24 @@ Old_rows_log_event::do_apply_event(Old_rows_log_event *ev, const Relay_log_info
call might reset the value of current_stmt_binlog_row_based, so
we need to do any changes to that value after this function.
*/
- lex_start(thd);
- mysql_reset_thd_for_next_command(thd);
+ lex_start(ev_thd);
+ mysql_reset_thd_for_next_command(ev_thd);
/*
Check if the slave is set to use SBR. If so, it should switch
to using RBR until the end of the "statement", i.e., next
STMT_END_F or next error.
*/
- if (!thd->current_stmt_binlog_row_based &&
- mysql_bin_log.is_open() && (thd->options & OPTION_BIN_LOG))
+ if (!ev_thd->current_stmt_binlog_row_based &&
+ mysql_bin_log.is_open() && (ev_thd->options & OPTION_BIN_LOG))
{
- thd->set_current_stmt_binlog_row_based();
+ ev_thd->set_current_stmt_binlog_row_based();
}
- if (simple_open_n_lock_tables(thd, rli->tables_to_lock))
+ if (simple_open_n_lock_tables(ev_thd, rli->tables_to_lock))
{
- uint actual_error= thd->stmt_da->sql_errno();
- if (thd->is_slave_error || thd->is_fatal_error)
+ uint actual_error= ev_thd->stmt_da->sql_errno();
+ if (ev_thd->is_slave_error || ev_thd->is_fatal_error)
{
/*
Error reporting borrowed from Query_log_event with many excessive
@@ -87,9 +87,9 @@ Old_rows_log_event::do_apply_event(Old_rows_log_event *ev, const Relay_log_info
*/
rli->report(ERROR_LEVEL, actual_error,
"Error '%s' on opening tables",
- (actual_error ? thd->stmt_da->message() :
+ (actual_error ? ev_thd->stmt_da->message() :
"unexpected success or fatal error"));
- thd->is_slave_error= 1;
+ ev_thd->is_slave_error= 1;
}
const_cast<Relay_log_info*>(rli)->clear_tables_to_lock();
DBUG_RETURN(actual_error);
@@ -109,9 +109,9 @@ Old_rows_log_event::do_apply_event(Old_rows_log_event *ev, const Relay_log_info
{
if (ptr->m_tabledef.compatible_with(rli, ptr->table))
{
- mysql_unlock_tables(thd, thd->lock);
- thd->lock= 0;
- thd->is_slave_error= 1;
+ mysql_unlock_tables(ev_thd, ev_thd->lock);
+ ev_thd->lock= 0;
+ ev_thd->is_slave_error= 1;
const_cast<Relay_log_info*>(rli)->clear_tables_to_lock();
DBUG_RETURN(Old_rows_log_event::ERR_BAD_TABLE_DEF);
}
@@ -159,23 +159,23 @@ Old_rows_log_event::do_apply_event(Old_rows_log_event *ev, const Relay_log_info
TIMESTAMP column to a table with one.
So we call set_time(), like in SBR. Presently it changes nothing.
*/
- thd->set_time((time_t)ev->when);
+ ev_thd->set_time((time_t)ev->when);
/*
There are a few flags that are replicated with each row event.
Make sure to set/clear them before executing the main body of
the event.
*/
if (ev->get_flags(Old_rows_log_event::NO_FOREIGN_KEY_CHECKS_F))
- thd->options|= OPTION_NO_FOREIGN_KEY_CHECKS;
+ ev_thd->options|= OPTION_NO_FOREIGN_KEY_CHECKS;
else
- thd->options&= ~OPTION_NO_FOREIGN_KEY_CHECKS;
+ ev_thd->options&= ~OPTION_NO_FOREIGN_KEY_CHECKS;
if (ev->get_flags(Old_rows_log_event::RELAXED_UNIQUE_CHECKS_F))
- thd->options|= OPTION_RELAXED_UNIQUE_CHECKS;
+ ev_thd->options|= OPTION_RELAXED_UNIQUE_CHECKS;
else
- thd->options&= ~OPTION_RELAXED_UNIQUE_CHECKS;
+ ev_thd->options&= ~OPTION_RELAXED_UNIQUE_CHECKS;
/* A small test to verify that objects have consistent types */
- DBUG_ASSERT(sizeof(thd->options) == sizeof(OPTION_RELAXED_UNIQUE_CHECKS));
+ DBUG_ASSERT(sizeof(ev_thd->options) == sizeof(OPTION_RELAXED_UNIQUE_CHECKS));
/*
Now we are in a statement and will stay in a statement until we
@@ -192,7 +192,7 @@ Old_rows_log_event::do_apply_event(Old_rows_log_event *ev, const Relay_log_info
while (error == 0 && row_start < ev->m_rows_end)
{
uchar const *row_end= NULL;
- if ((error= do_prepare_row(thd, rli, table, row_start, &row_end)))
+ if ((error= do_prepare_row(ev_thd, rli, table, row_start, &row_end)))
break; // We should perform the after-row operation even in
// the case of error
@@ -202,7 +202,7 @@ Old_rows_log_event::do_apply_event(Old_rows_log_event *ev, const Relay_log_info
/* in_use can have been set to NULL in close_tables_for_reopen */
THD* old_thd= table->in_use;
if (!table->in_use)
- table->in_use= thd;
+ table->in_use= ev_thd;
error= do_exec_row(table);
table->in_use = old_thd;
switch (error)
@@ -216,10 +216,10 @@ Old_rows_log_event::do_apply_event(Old_rows_log_event *ev, const Relay_log_info
break;
default:
- rli->report(ERROR_LEVEL, thd->stmt_da->sql_errno(),
+ rli->report(ERROR_LEVEL, ev_thd->stmt_da->sql_errno(),
"Error in %s event: row application failed. %s",
ev->get_type_str(),
- thd->is_error() ? thd->stmt_da->message() : "");
+ ev_thd->is_error() ? ev_thd->stmt_da->message() : "");
thd->is_slave_error= 1;
break;
}
@@ -232,7 +232,7 @@ Old_rows_log_event::do_apply_event(Old_rows_log_event *ev, const Relay_log_info
if (!ev->cache_stmt)
{
DBUG_PRINT("info", ("Marked that we need to keep log"));
- thd->options|= OPTION_KEEP_LOG;
+ ev_thd->options|= OPTION_KEEP_LOG;
}
}
@@ -245,12 +245,12 @@ Old_rows_log_event::do_apply_event(Old_rows_log_event *ev, const Relay_log_info
if (error)
{ /* error has occured during the transaction */
- rli->report(ERROR_LEVEL, thd->stmt_da->sql_errno(),
+ rli->report(ERROR_LEVEL, ev_thd->stmt_da->sql_errno(),
"Error in %s event: error during transaction execution "
"on table %s.%s. %s",
ev->get_type_str(), table->s->db.str,
table->s->table_name.str,
- thd->is_error() ? thd->stmt_da->message() : "");
+ ev_thd->is_error() ? ev_thd->stmt_da->message() : "");
/*
If one day we honour --skip-slave-errors in row-based replication, and
@@ -263,9 +263,9 @@ Old_rows_log_event::do_apply_event(Old_rows_log_event *ev, const Relay_log_info
thread is certainly going to stop.
rollback at the caller along with sbr.
*/
- thd->reset_current_stmt_binlog_row_based();
- const_cast<Relay_log_info*>(rli)->cleanup_context(thd, error);
- thd->is_slave_error= 1;
+ ev_thd->reset_current_stmt_binlog_row_based();
+ const_cast<Relay_log_info*>(rli)->cleanup_context(ev_thd, error);
+ ev_thd->is_slave_error= 1;
DBUG_RETURN(error);
}
diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc
index 1bd137836e8..634d3134324 100644
--- a/sql/opt_sum.cc
+++ b/sql/opt_sum.cc
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000-2003 MySQL AB
+/* Copyright (c) 2000, 2010 Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -11,7 +11,7 @@
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
/**
@@ -96,7 +96,7 @@ static ulonglong get_exact_record_count(TABLE_LIST *tables)
@param conds WHERE clause
@note
- This function is only called for queries with sum functions and no
+ This function is only called for queries with aggregate functions and no
GROUP BY part. This means that the result set shall contain a single
row only
@@ -565,31 +565,57 @@ bool simple_pred(Item_func *func_item, Item **args, bool *inv_order)
/**
Check whether a condition matches a key to get {MAX|MIN}(field):.
- For the index specified by the keyinfo parameter, index that
- contains field as its component (field_part), the function
- checks whether the condition cond is a conjunction and all its
- conjuncts referring to the columns of the same table as column
- field are one of the following forms:
- - f_i= const_i or const_i= f_i or f_i is null,
- where f_i is part of the index
- - field {<|<=|>=|>|=} const or const {<|<=|>=|>|=} field
- - field between const1 and const2
-
- @param[in] max_fl Set to 1 if we are optimising MAX()
- @param[in,out] ref Reference to the structure we store the key
- value
- @param[in] keyinfo Reference to the key info
- @param[in] field_part Pointer to the key part for the field
- @param[in] cond WHERE condition
- @param[in,out] key_part_used Map of matchings parts
- @param[in,out] range_fl Says whether including key will be used
- @param[out] prefix_len Length of common key part for the range
- where MAX/MIN is searched for
+ For the index specified by the keyinfo parameter and an index that
+ contains the field as its component (field_part), the function
+ checks whether
+
+ - the condition cond is a conjunction,
+ - all of its conjuncts refer to columns of the same table, and
+ - each conjunct is on one of the following forms:
+ - f_i = const_i or const_i = f_i or f_i IS NULL,
+ where f_i is part of the index
+ - field {<|<=|>=|>|=} const
+ - const {<|<=|>=|>|=} field
+ - field BETWEEN const_1 AND const_2
+
+ As a side-effect, the key value to be used for looking up the MIN/MAX value
+ is actually stored inside the Field object. An interesting feature is that
+ the function will find the most restrictive endpoint by over-eager
+ evaluation of the @c WHERE condition. It continually stores the current
+ endpoint inside the Field object. For a query such as
+
+ @code
+ SELECT MIN(a) FROM t1 WHERE a > 3 AND a > 5;
+ @endcode
+
+ the algorithm will recurse over the conjuction, storing first a 3 in the
+ field. In the next recursive invocation the expression a > 5 is evaluated
+ as 3 > 5 (Due to the dual nature of Field objects as value carriers and
+ field identifiers), which will obviously fail, leading to 5 being stored in
+ the Field object.
+
+ @param[in] max_fl Set to true if we are optimizing MAX(),
+ false means we are optimizing %MIN()
+ @param[in, out] ref Reference to the structure where the function
+ stores the key value
+ @param[in] keyinfo Reference to the key info
+ @param[in] field_part Pointer to the key part for the field
+ @param[in] cond WHERE condition
+ @param[in,out] key_part_used Map of matchings parts. The function will output
+ the set of key parts actually being matched in
+ this set, yet it relies on the caller to
+ initialize the value to zero. This is due
+ to the fact that this value is passed
+ recursively.
+ @param[in,out] range_fl Says whether endpoints use strict greater/less
+ than.
+ @param[out] prefix_len Length of common key part for the range
+ where MAX/MIN is searched for
@retval
- 0 Index can't be used.
+ false Index can't be used.
@retval
- 1 We can use index to get MIN/MAX value
+ true We can use the index to get MIN/MAX value
*/
static bool matching_cond(bool max_fl, TABLE_REF *ref, KEY *keyinfo,
@@ -626,17 +652,20 @@ static bool matching_cond(bool max_fl, TABLE_REF *ref, KEY *keyinfo,
return 0; // Not operator, can't optimize
bool eq_type= 0; // =, <=> or IS NULL
+ bool is_null_safe_eq= FALSE; // The operator is NULL safe, e.g. <=>
bool noeq_type= 0; // < or >
bool less_fl= 0; // < or <=
- bool is_null= 0;
- bool between= 0;
+ bool is_null= 0; // IS NULL
+ bool between= 0; // BETWEEN ... AND ...
switch (((Item_func*) cond)->functype()) {
case Item_func::ISNULL_FUNC:
is_null= 1; /* fall through */
case Item_func::EQ_FUNC:
+ eq_type= TRUE;
+ break;
case Item_func::EQUAL_FUNC:
- eq_type= 1;
+ eq_type= is_null_safe_eq= TRUE;
break;
case Item_func::LT_FUNC:
noeq_type= 1; /* fall through */
@@ -664,6 +693,10 @@ static bool matching_cond(bool max_fl, TABLE_REF *ref, KEY *keyinfo,
if (!simple_pred((Item_func*) cond, args, &inv))
return 0;
+ if (!is_null_safe_eq && !is_null &&
+ (args[1]->is_null() || (between && args[2]->is_null())))
+ return FALSE;
+
if (inv && !eq_type)
less_fl= 1-less_fl; // Convert '<' -> '>' (etc)
@@ -714,15 +747,16 @@ static bool matching_cond(bool max_fl, TABLE_REF *ref, KEY *keyinfo,
- field {>|>=} const, when searching for MIN
*/
- if (is_null)
+ if (is_null || (is_null_safe_eq && args[1]->is_null()))
{
part->field->set_null();
*key_ptr= (uchar) 1;
}
else
{
- store_val_in_field(part->field, args[between && max_fl ? 2 : 1],
- CHECK_FIELD_IGNORE);
+ /* Update endpoints for MAX/MIN, see function comment. */
+ Item *value= args[between && max_fl ? 2 : 1];
+ store_val_in_field(part->field, value, CHECK_FIELD_IGNORE);
if (part->null_bit)
*key_ptr++= (uchar) test(part->field->is_null());
part->field->get_key_image(key_ptr, part->length, Field::itRAW);
diff --git a/sql/protocol.cc b/sql/protocol.cc
index ca6aa3a6052..fb125c215f5 100644
--- a/sql/protocol.cc
+++ b/sql/protocol.cc
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000-2003 MySQL AB
+/* Copyright (c) 2000, 2010 Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -645,8 +645,7 @@ void Protocol::init(THD *thd_arg)
void Protocol::end_partial_result_set(THD *thd_arg)
{
- net_send_eof(thd_arg, thd_arg->server_status,
- 0 /* no warnings, we're inside SP */);
+ net_send_eof(thd_arg, thd_arg->server_status, 0 /* no warnings, we're inside SP */);
}
diff --git a/sql/rpl_utility.cc b/sql/rpl_utility.cc
index e34f8561051..6058c473e9f 100644
--- a/sql/rpl_utility.cc
+++ b/sql/rpl_utility.cc
@@ -206,7 +206,7 @@ table_def::compatible_with(Relay_log_info const *rli_arg, TABLE *table)
Check the slave's field size against that of the master.
*/
if (!error &&
- !field->compatible_field_size(field_metadata(col), rli_arg))
+ !field->compatible_field_size(field_metadata(col), rli_arg, m_flags))
{
error= 1;
char buf[256];
diff --git a/sql/rpl_utility.h b/sql/rpl_utility.h
index d011e9aade8..b209c9140d1 100644
--- a/sql/rpl_utility.h
+++ b/sql/rpl_utility.h
@@ -32,12 +32,6 @@ class Relay_log_info;
- Extract and decode table definition data from the table map event
- Check if table definition in table map is compatible with table
definition on slave
-
- Currently, the only field type data available is an array of the
- type operators that are present in the table map event.
-
- @todo Add type operands to this structure to allow detection of
- difference between, e.g., BIT(5) and BIT(10).
*/
class table_def
@@ -59,9 +53,9 @@ public:
@param null_bitmap The bitmap of fields that can be null
*/
table_def(field_type *types, ulong size, uchar *field_metadata,
- int metadata_size, uchar *null_bitmap)
+ int metadata_size, uchar *null_bitmap, uint16 flags)
: m_size(size), m_type(0), m_field_metadata_size(metadata_size),
- m_field_metadata(0), m_null_bits(0), m_memory(NULL)
+ m_field_metadata(0), m_null_bits(0), m_flags(flags), m_memory(NULL)
{
m_memory= (uchar *)my_multi_malloc(MYF(MY_WME),
&m_type, size,
@@ -247,6 +241,7 @@ private:
uint m_field_metadata_size;
uint16 *m_field_metadata;
uchar *m_null_bits;
+ uint16 m_flags; // Table flags
uchar *m_memory;
};
diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc
index 534a6162d87..f9c7cde36c8 100644
--- a/sql/sql_partition.cc
+++ b/sql/sql_partition.cc
@@ -3324,6 +3324,7 @@ int get_partition_id_range(partition_info *part_info,
*func_value= part_func_value;
if (unsigned_flag)
part_func_value-= 0x8000000000000000ULL;
+ /* Search for the partition containing part_func_value */
while (max_part_id > min_part_id)
{
loc_part_id= (max_part_id + min_part_id) / 2;
@@ -3463,11 +3464,17 @@ uint32 get_partition_id_range_for_endpoint(partition_info *part_info,
part_end_val= range_array[loc_part_id];
if (left_endpoint)
{
+ DBUG_ASSERT(part_func_value > part_end_val ?
+ (loc_part_id == max_partition &&
+ !part_info->defined_max_value) :
+ 1);
/*
In case of PARTITION p VALUES LESS THAN MAXVALUE
- the maximum value is in the current partition.
+ the maximum value is in the current (last) partition.
+ If value is equal or greater than the endpoint,
+ the range starts from the next partition.
*/
- if (part_func_value == part_end_val &&
+ if (part_func_value >= part_end_val &&
(loc_part_id < max_partition || !part_info->defined_max_value))
loc_part_id++;
}
@@ -4536,6 +4543,12 @@ uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info,
{
DBUG_ENTER("prep_alter_part_table");
+ /* Foreign keys on partitioned tables are not supported, waits for WL#148 */
+ if (table->part_info && (alter_info->flags & ALTER_FOREIGN_KEY))
+ {
+ my_error(ER_FOREIGN_KEY_ON_PARTITIONED, MYF(0));
+ DBUG_RETURN(TRUE);
+ }
/*
We are going to manipulate the partition info on the table object
so we need to ensure that the data structure of the table object
diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc
index 2382fc8ab5e..c15cc6df4f5 100644
--- a/sql/sql_plugin.cc
+++ b/sql/sql_plugin.cc
@@ -1743,6 +1743,8 @@ bool mysql_uninstall_plugin(THD *thd, const LEX_STRING *name)
bzero(&tables, sizeof(tables));
tables.db= (char *)"mysql";
tables.table_name= tables.alias= (char *)"plugin";
+ if (check_table_access(thd, DELETE_ACL, &tables, FALSE, 1, FALSE))
+ DBUG_RETURN(TRUE);
/* need to open before acquiring LOCK_plugin or it will deadlock */
if (! (table= open_ltable(thd, &tables, TL_WRITE, 0)))
diff --git a/sql/sql_profile.cc b/sql/sql_profile.cc
index 69e5bc3cbb4..f152124d466 100644
--- a/sql/sql_profile.cc
+++ b/sql/sql_profile.cc
@@ -1,4 +1,4 @@
-/* Copyright (C) 2007 MySQL AB
+/* Copyright (c) 2007, 2010 Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -485,7 +485,7 @@ void PROFILING::set_query_source(char *query_source_arg, uint query_length_arg)
There are two ways to get to this function: Selecting from the information
schema, and a SHOW command.
*/
-int PROFILING::fill_statistics_info(THD *thd, TABLE_LIST *tables, Item *cond)
+int PROFILING::fill_statistics_info(THD *thd_arg, TABLE_LIST *tables, Item *cond)
{
DBUG_ENTER("PROFILING::fill_statistics_info");
TABLE *table= tables->table;
@@ -520,7 +520,7 @@ int PROFILING::fill_statistics_info(THD *thd, TABLE_LIST *tables, Item *cond)
/* Skip the first. We count spans of fence, not fence-posts. */
if (previous == NULL) continue;
- if (thd->lex->sql_command == SQLCOM_SHOW_PROFILE)
+ if (thd_arg->lex->sql_command == SQLCOM_SHOW_PROFILE)
{
/*
We got here via a SHOW command. That means that we stored
@@ -533,14 +533,14 @@ int PROFILING::fill_statistics_info(THD *thd, TABLE_LIST *tables, Item *cond)
struct where and having conditions at the SQL layer, then this
condition should be ripped out.
*/
- if (thd->lex->profile_query_id == 0) /* 0 == show final query */
+ if (thd_arg->lex->profile_query_id == 0) /* 0 == show final query */
{
if (query != last)
continue;
}
else
{
- if (thd->lex->profile_query_id != query->profiling_query_id)
+ if (thd_arg->lex->profile_query_id != query->profiling_query_id)
continue;
}
}
@@ -661,7 +661,7 @@ int PROFILING::fill_statistics_info(THD *thd, TABLE_LIST *tables, Item *cond)
table->field[17]->set_notnull();
}
- if (schema_table_store_record(thd, table))
+ if (schema_table_store_record(thd_arg, table))
DBUG_RETURN(1);
}
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index b56f2e2e378..9880f8f4a69 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1,4 +1,4 @@
-/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc.
+/* Copyright (c) 2000, 2010 Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -1116,6 +1116,31 @@ JOIN::optimize()
{
conds=new Item_int((longlong) 0,1); // Always false
}
+
+ /*
+ It's necessary to check const part of HAVING cond as
+ there is a chance that some cond parts may become
+ const items after make_join_statisctics(for example
+ when Item is a reference to cost table field from
+ outer join).
+ This check is performed only for those conditions
+ which do not use aggregate functions. In such case
+ temporary table may not be used and const condition
+ elements may be lost during further having
+ condition transformation in JOIN::exec.
+ */
+ if (having && !having->with_sum_func)
+ {
+ COND *const_cond= make_cond_for_table(having, const_table_map, 0);
+ DBUG_EXECUTE("where", print_where(const_cond, "const_having_cond",
+ QT_ORDINARY););
+ if (const_cond && !const_cond->val_int())
+ {
+ zero_result_cause= "Impossible HAVING noticed after reading const tables";
+ DBUG_RETURN(0);
+ }
+ }
+
if (make_join_select(this, select, conds))
{
zero_result_cause=
@@ -2970,7 +2995,8 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables_arg, COND *conds,
s->quick=select->quick;
s->needed_reg=select->needed_reg;
select->quick=0;
- if (records == 0 && s->table->reginfo.impossible_range)
+ if (records == 0 && s->table->reginfo.impossible_range &&
+ (s->table->file->ha_table_flags() & HA_STATS_RECORDS_IS_EXACT))
{
/*
Impossible WHERE or ON expression
@@ -5953,7 +5979,7 @@ store_val_in_field(Field *field, Item *item, enum_check_fields check_flag)
@retval TRUE error occurred
*/
bool
-JOIN::make_simple_join(JOIN *parent, TABLE *tmp_table)
+JOIN::make_simple_join(JOIN *parent, TABLE *temp_table)
{
DBUG_ENTER("JOIN::make_simple_join");
@@ -5966,7 +5992,7 @@ JOIN::make_simple_join(JOIN *parent, TABLE *tmp_table)
DBUG_RETURN(TRUE); /* purecov: inspected */
join_tab= parent->join_tab_reexec;
- parent->table_reexec[0]= tmp_table;
+ parent->table_reexec[0]= temp_table;
tables= 1;
const_tables= 0;
const_table_map= 0;
@@ -5986,7 +6012,7 @@ JOIN::make_simple_join(JOIN *parent, TABLE *tmp_table)
do_send_rows= row_limit ? 1 : 0;
join_tab->cache.buff=0; /* No caching */
- join_tab->table=tmp_table;
+ join_tab->table=temp_table;
join_tab->select=0;
join_tab->select_cond=0;
join_tab->quick=0;
@@ -6003,8 +6029,8 @@ JOIN::make_simple_join(JOIN *parent, TABLE *tmp_table)
join_tab->join= this;
join_tab->ref.key_parts= 0;
bzero((char*) &join_tab->read_record,sizeof(join_tab->read_record));
- tmp_table->status=0;
- tmp_table->null_row=0;
+ temp_table->status=0;
+ temp_table->null_row=0;
DBUG_RETURN(FALSE);
}
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index b6d9fd353a1..947f71815c6 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -5624,6 +5624,45 @@ err:
DBUG_RETURN(-1);
}
+/**
+ @brief Check if both DROP and CREATE are present for an index in ALTER TABLE
+
+ @details Checks if any index is being modified (present as both DROP INDEX
+ and ADD INDEX) in the current ALTER TABLE statement. Needed for disabling
+ online ALTER TABLE.
+
+ @param table The table being altered
+ @param alter_info The ALTER TABLE structure
+ @return presence of index being altered
+ @retval FALSE No such index
+ @retval TRUE Have at least 1 index modified
+*/
+
+static bool
+is_index_maintenance_unique (TABLE *table, Alter_info *alter_info)
+{
+ List_iterator<Key> key_it(alter_info->key_list);
+ List_iterator<Alter_drop> drop_it(alter_info->drop_list);
+ Key *key;
+
+ while ((key= key_it++))
+ {
+ if (key->name.str)
+ {
+ Alter_drop *drop;
+
+ drop_it.rewind();
+ while ((drop= drop_it++))
+ {
+ if (drop->type == Alter_drop::KEY &&
+ !my_strcasecmp(system_charset_info, key->name.str, drop->name))
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
+}
+
/*
SYNOPSIS
@@ -5712,6 +5751,7 @@ compare_tables(TABLE *table,
*/
Alter_info tmp_alter_info(*alter_info, thd->mem_root);
uint db_options= 0; /* not used */
+
/* Create the prepared information. */
if (mysql_prepare_create_table(thd, create_info,
&tmp_alter_info,
@@ -6910,10 +6950,14 @@ view_err:
*/
new_db_type= create_info->db_type;
+ if (is_index_maintenance_unique (table, alter_info))
+ need_copy_table= ALTER_TABLE_DATA_CHANGED;
+
if (mysql_prepare_alter_table(thd, table, create_info, alter_info))
goto err;
- need_copy_table= alter_info->change_level;
+ if (need_copy_table == ALTER_TABLE_METADATA_ONLY)
+ need_copy_table= alter_info->change_level;
set_table_default_charset(thd, create_info, db);
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 36a910b7a99..56220c7e047 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -1,4 +1,4 @@
-/* Copyright 2000-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.
+/* Copyright (c) 2000, 2010 Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -8378,7 +8378,7 @@ function_call_generic:
builder= find_native_function_builder(thd, $1);
if (builder)
{
- item= builder->create(thd, $1, $4);
+ item= builder->create_func(thd, $1, $4);
}
else
{
@@ -8400,7 +8400,7 @@ function_call_generic:
{
builder= find_qualified_function_builder(thd);
DBUG_ASSERT(builder);
- item= builder->create(thd, $1, $4);
+ item= builder->create_func(thd, $1, $4);
}
}
diff --git a/sql/table.cc b/sql/table.cc
index 5397e03add2..6bd7e7bd59f 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -4028,9 +4028,7 @@ Item *create_view_field(THD *thd, TABLE_LIST *view, Item **field_ref,
{
DBUG_RETURN(field);
}
- Item *item= new Item_direct_view_ref(&view->view->select_lex.context,
- field_ref, view->alias,
- name);
+ Item *item= new Item_direct_view_ref(view, field_ref, name);
DBUG_RETURN(item);
}