summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/client_settings.h8
-rw-r--r--sql/field.cc85
-rw-r--r--sql/field.h9
-rw-r--r--sql/ha_partition.cc33
-rw-r--r--sql/handler.h8
-rw-r--r--sql/item.cc25
-rw-r--r--sql/item.h3
-rw-r--r--sql/item_cmpfunc.cc6
-rw-r--r--sql/item_func.cc52
-rw-r--r--sql/item_func.h1
-rw-r--r--sql/item_sum.cc3
-rw-r--r--sql/log_event.cc22
-rw-r--r--sql/my_decimal.h14
-rw-r--r--sql/opt_range.cc11
-rw-r--r--sql/slave.cc28
-rw-r--r--sql/sql_db.cc7
-rw-r--r--sql/sql_delete.cc4
-rw-r--r--sql/sql_insert.cc52
-rw-r--r--sql/sql_partition.cc3
-rw-r--r--sql/sql_select.cc41
-rw-r--r--sql/sql_show.cc2
-rw-r--r--sql/sql_table.cc83
-rw-r--r--sql/sql_update.cc1
-rw-r--r--sql/sql_yacc.yy12
-rw-r--r--sql/table.cc9
-rw-r--r--sql/table.h6
26 files changed, 313 insertions, 215 deletions
diff --git a/sql/client_settings.h b/sql/client_settings.h
index f0742cd8046..4f06c15a29e 100644
--- a/sql/client_settings.h
+++ b/sql/client_settings.h
@@ -33,3 +33,11 @@
#define mysql_server_init(a,b,c) 0
+#ifdef HAVE_REPLICATION
+C_MODE_START
+void slave_io_thread_detach_vio();
+C_MODE_END
+#else
+#define slave_io_thread_detach_vio()
+#endif
+
diff --git a/sql/field.cc b/sql/field.cc
index 3bfb54fbd15..426effa57cd 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -2485,12 +2485,97 @@ Field_new_decimal::Field_new_decimal(uint32 len_arg,
{
precision= my_decimal_length_to_precision(len_arg, dec_arg, unsigned_arg);
set_if_smaller(precision, DECIMAL_MAX_PRECISION);
+ DBUG_ASSERT(precision >= dec);
DBUG_ASSERT((precision <= DECIMAL_MAX_PRECISION) &&
(dec <= DECIMAL_MAX_SCALE));
bin_size= my_decimal_get_binary_size(precision, dec);
}
+/**
+ Create a field to hold a decimal value from an item.
+
+ @remark The MySQL DECIMAL data type has a characteristic that needs to be
+ taken into account when deducing the type from a Item_decimal.
+
+ But first, let's briefly recap what is the new MySQL DECIMAL type:
+
+ The declaration syntax for a decimal is DECIMAL(M,D), where:
+
+ * M is the maximum number of digits (the precision).
+ It has a range of 1 to 65.
+ * D is the number of digits to the right of the decimal separator (the scale).
+ It has a range of 0 to 30 and must be no larger than M.
+
+ D and M are used to determine the storage requirements for the integer
+ and fractional parts of each value. The integer part is to the left of
+ the decimal separator and to the right is the fractional part. Hence:
+
+ M is the number of digits for the integer and fractional part.
+ D is the number of digits for the fractional part.
+
+ Consequently, M - D is the number of digits for the integer part. For
+ example, a DECIMAL(20,10) column has ten digits on either side of
+ the decimal separator.
+
+ The characteristic that needs to be taken into account is that the
+ backing type for Item_decimal is a my_decimal that has a higher
+ precision (DECIMAL_MAX_POSSIBLE_PRECISION, see my_decimal.h) than
+ DECIMAL.
+
+ Drawing a comparison between my_decimal and DECIMAL:
+
+ * M has a range of 1 to 81.
+ * D has a range of 0 to 81.
+
+ There can be a difference in range if the decimal contains a integer
+ part. This is because the fractional part must always be on a group
+ boundary, leaving at least one group for the integer part. Since each
+ group is 9 (DIG_PER_DEC1) digits and there are 9 (DECIMAL_BUFF_LENGTH)
+ groups, the fractional part is limited to 72 digits if there is at
+ least one digit in the integral part.
+
+ Although the backing type for a DECIMAL is also my_decimal, every
+ time a my_decimal is stored in a DECIMAL field, the precision and
+ scale are explicitly capped at 65 (DECIMAL_MAX_PRECISION) and 30
+ (DECIMAL_MAX_SCALE) digits, following my_decimal truncation procedure
+ (FIX_INTG_FRAC_ERROR).
+*/
+
+Field_new_decimal *
+Field_new_decimal::new_decimal_field(const Item *item)
+{
+ uint32 len;
+ uint intg= item->decimal_int_part(), scale= item->decimals;
+
+ DBUG_ASSERT(item->decimal_precision() >= item->decimals);
+
+ /*
+ Employ a procedure along the lines of the my_decimal truncation process:
+ - If the integer part is equal to or bigger than the maximum precision:
+ Truncate integer part to fit and the fractional becomes zero.
+ - Otherwise:
+ Truncate fractional part to fit.
+ */
+ if (intg >= DECIMAL_MAX_PRECISION)
+ {
+ intg= DECIMAL_MAX_PRECISION;
+ scale= 0;
+ }
+ else
+ {
+ uint room= min(DECIMAL_MAX_PRECISION - intg, DECIMAL_MAX_SCALE);
+ if (scale > room)
+ scale= room;
+ }
+
+ len= my_decimal_precision_to_length(intg + scale, scale, item->unsigned_flag);
+
+ return new Field_new_decimal(len, item->maybe_null, item->name, scale,
+ item->unsigned_flag);
+}
+
+
int Field_new_decimal::reset(void)
{
store_value(&decimal_zero);
diff --git a/sql/field.h b/sql/field.h
index 5136f760fc1..a9299256f88 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -608,6 +608,10 @@ protected:
class Field_num :public Field {
public:
+ /**
+ The scale of the Field's value, i.e. the number of digits to the right
+ of the decimal point.
+ */
const uint8 dec;
bool zerofill,unsigned_flag; // Purify cannot handle bit fields
Field_num(uchar *ptr_arg,uint32 len_arg, uchar *null_ptr_arg,
@@ -766,6 +770,11 @@ public:
Field_new_decimal(uint32 len_arg, bool maybe_null_arg,
const char *field_name_arg, uint8 dec_arg,
bool unsigned_arg);
+ /*
+ Create a field to hold a decimal value from an item.
+ Truncates the precision and/or scale if necessary.
+ */
+ static Field_new_decimal *new_decimal_field(const Item *item);
enum_field_types type() const { return MYSQL_TYPE_NEWDECIMAL;}
enum ha_base_keytype key_type() const { return HA_KEYTYPE_BINARY; }
Item_result result_type () const { return DECIMAL_RESULT; }
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index b345648260c..ac8c46ec4e3 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -4414,17 +4414,6 @@ int ha_partition::handle_unordered_scan_next_partition(uchar * buf)
break;
case partition_index_first:
DBUG_PRINT("info", ("index_first on partition %d", i));
- /* MyISAM engine can fail if we call index_first() when indexes disabled */
- /* that happens if the table is empty. */
- /* Here we use file->stats.records instead of file->records() because */
- /* file->records() is supposed to return an EXACT count, and it can be */
- /* possibly slow. We don't need an exact number, an approximate one- from*/
- /* the last ::info() call - is sufficient. */
- if (file->stats.records == 0)
- {
- error= HA_ERR_END_OF_FILE;
- break;
- }
error= file->index_first(buf);
break;
case partition_index_first_unordered:
@@ -4512,32 +4501,10 @@ int ha_partition::handle_ordered_index_scan(uchar *buf, bool reverse_order)
m_start_key.flag);
break;
case partition_index_first:
- /* MyISAM engine can fail if we call index_first() when indexes disabled */
- /* that happens if the table is empty. */
- /* Here we use file->stats.records instead of file->records() because */
- /* file->records() is supposed to return an EXACT count, and it can be */
- /* possibly slow. We don't need an exact number, an approximate one- from*/
- /* the last ::info() call - is sufficient. */
- if (file->stats.records == 0)
- {
- error= HA_ERR_END_OF_FILE;
- break;
- }
error= file->index_first(rec_buf_ptr);
reverse_order= FALSE;
break;
case partition_index_last:
- /* MyISAM engine can fail if we call index_last() when indexes disabled */
- /* that happens if the table is empty. */
- /* Here we use file->stats.records instead of file->records() because */
- /* file->records() is supposed to return an EXACT count, and it can be */
- /* possibly slow. We don't need an exact number, an approximate one- from*/
- /* the last ::info() call - is sufficient. */
- if (file->stats.records == 0)
- {
- error= HA_ERR_END_OF_FILE;
- break;
- }
error= file->index_last(rec_buf_ptr);
reverse_order= TRUE;
break;
diff --git a/sql/handler.h b/sql/handler.h
index 5d27d3eff6d..f759239d66e 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -895,7 +895,7 @@ class partition_info;
struct st_partition_iter;
#define NOT_A_PARTITION_ID ((uint32)-1)
-enum ha_choice { HA_CHOICE_UNDEF, HA_CHOICE_NO, HA_CHOICE_YES };
+enum enum_ha_unused { HA_CHOICE_UNDEF, HA_CHOICE_NO, HA_CHOICE_YES };
typedef struct st_ha_create_information
{
@@ -918,14 +918,12 @@ typedef struct st_ha_create_information
uint options; /* OR of HA_CREATE_ options */
uint merge_insert_method;
uint extra_size; /* length of extra data segment */
- /** Transactional or not. Unused; reserved for future versions. */
- enum ha_choice transactional;
+ enum enum_ha_unused unused1;
bool table_existed; /* 1 in create if table existed */
bool frm_only; /* 1 if no ha_create_table() */
bool varchar; /* 1 if table has a VARCHAR */
enum ha_storage_media storage_media; /* DEFAULT, DISK or MEMORY */
- /** Per-page checksums or not. Unused; reserved for future versions. */
- enum ha_choice page_checksum;
+ enum enum_ha_unused unused2;
} HA_CREATE_INFO;
diff --git a/sql/item.cc b/sql/item.cc
index 2640b74851b..9551c5feaff 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -435,17 +435,26 @@ Item::Item(THD *thd, Item *item):
}
+/**
+ Decimal precision of the item.
+
+ @remark The precision must not be capped as it can be used in conjunction
+ with Item::decimals to determine the size of the integer part when
+ constructing a decimal data type.
+
+ @see Item::decimal_int_part()
+ @see Item::decimals
+*/
+
uint Item::decimal_precision() const
{
+ uint precision= max_length;
Item_result restype= result_type();
if ((restype == DECIMAL_RESULT) || (restype == INT_RESULT))
- {
- uint prec=
- my_decimal_length_to_precision(max_length, decimals, unsigned_flag);
- return min(prec, DECIMAL_MAX_PRECISION);
- }
- return min(max_length, DECIMAL_MAX_PRECISION);
+ precision= my_decimal_length_to_precision(max_length, decimals, unsigned_flag);
+
+ return precision;
}
@@ -4902,9 +4911,7 @@ Field *Item::tmp_table_field_from_field_type(TABLE *table, bool fixed_length)
switch (field_type()) {
case MYSQL_TYPE_DECIMAL:
case MYSQL_TYPE_NEWDECIMAL:
- field= new Field_new_decimal((uchar*) 0, max_length, null_ptr, 0,
- Field::NONE, name, decimals, 0,
- unsigned_flag);
+ field= Field_new_decimal::new_decimal_field(this);
break;
case MYSQL_TYPE_TINY:
field= new Field_tiny((uchar*) 0, max_length, null_ptr, 0, Field::NONE,
diff --git a/sql/item.h b/sql/item.h
index 3dfcd7c2612..464085cb101 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -755,9 +755,10 @@ public:
virtual cond_result eq_cmp_result() const { return COND_OK; }
inline uint float_length(uint decimals_par) const
{ return decimals != NOT_FIXED_DEC ? (DBL_DIG+2+decimals_par) : DBL_DIG+8;}
+ /** Returns the uncapped decimal precision of this item. */
virtual uint decimal_precision() const;
inline int decimal_int_part() const
- { return my_decimal_int_part(decimal_precision(), decimals); }
+ { return decimal_precision() - decimals; }
/*
Returns true if this is constant (during query execution, i.e. its value
will not change until next fix_fields) and its value is known.
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 1ff9ca6a419..53feb753844 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -2183,7 +2183,7 @@ uint Item_func_ifnull::decimal_precision() const
int arg1_int_part= args[1]->decimal_int_part();
int max_int_part= max(arg0_int_part, arg1_int_part);
int precision= max_int_part + decimals;
- return min(precision, DECIMAL_MAX_PRECISION);
+ return precision;
}
@@ -2367,7 +2367,7 @@ uint Item_func_if::decimal_precision() const
int arg1_prec= args[1]->decimal_int_part();
int arg2_prec= args[2]->decimal_int_part();
int precision=max(arg1_prec,arg2_prec) + decimals;
- return min(precision, DECIMAL_MAX_PRECISION);
+ return precision;
}
@@ -2775,7 +2775,7 @@ uint Item_func_case::decimal_precision() const
if (else_expr_num != -1)
set_if_bigger(max_int_part, args[else_expr_num]->decimal_int_part());
- return min(max_int_part + decimals, DECIMAL_MAX_PRECISION);
+ return max_int_part + decimals;
}
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 55d4b37ddb0..6abc78371db 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -452,45 +452,8 @@ Field *Item_func::tmp_table_field(TABLE *table)
return make_string_field(table);
break;
case DECIMAL_RESULT:
- {
- uint8 dec= decimals;
- uint8 intg= decimal_precision() - dec;
- uint32 len= max_length;
-
- /*
- Trying to put too many digits overall in a DECIMAL(prec,dec)
- will always throw a warning. We must limit dec to
- DECIMAL_MAX_SCALE however to prevent an assert() later.
- */
-
- if (dec > 0)
- {
- int overflow;
-
- dec= min(dec, DECIMAL_MAX_SCALE);
-
- /*
- If the value still overflows the field with the corrected dec,
- we'll throw out decimals rather than integers. This is still
- bad and of course throws a truncation warning.
- */
-
- const int required_length=
- my_decimal_precision_to_length(intg + dec, dec,
- unsigned_flag);
-
- overflow= required_length - len;
-
- if (overflow > 0)
- dec= max(0, dec - overflow); // too long, discard fract
- else
- /* Corrected value fits. */
- len= required_length;
- }
-
- field= new Field_new_decimal(len, maybe_null, name, dec, unsigned_flag);
+ field= Field_new_decimal::new_decimal_field(this);
break;
- }
case ROW_RESULT:
default:
// This case should never be chosen
@@ -4781,6 +4744,19 @@ void Item_func_get_user_var::fix_length_and_dec()
}
+uint Item_func_get_user_var::decimal_precision() const
+{
+ uint precision= max_length;
+ Item_result restype= result_type();
+
+ /* Default to maximum as the precision is unknown a priori. */
+ if ((restype == DECIMAL_RESULT) || (restype == INT_RESULT))
+ precision= DECIMAL_MAX_PRECISION;
+
+ return precision;
+}
+
+
bool Item_func_get_user_var::const_item() const
{
return (!var_entry || current_thd->query_id != var_entry->update_query_id);
diff --git a/sql/item_func.h b/sql/item_func.h
index 025ac12fe07..fdbbff89e60 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -1393,6 +1393,7 @@ public:
table_map used_tables() const
{ return const_item() ? 0 : RAND_TABLE_BIT; }
bool eq(const Item *item, bool binary_cmp) const;
+ uint decimal_precision() const;
private:
bool set_value(THD *thd, sp_rcontext *ctx, Item **it);
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 38251294053..08a48c6ce2f 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -517,8 +517,7 @@ Field *Item_sum::create_tmp_field(bool group, TABLE *table,
name, table->s, collation.collation);
break;
case DECIMAL_RESULT:
- field= new Field_new_decimal(max_length, maybe_null, name,
- decimals, unsigned_flag);
+ field= Field_new_decimal::new_decimal_field(this);
break;
case ROW_RESULT:
default:
diff --git a/sql/log_event.cc b/sql/log_event.cc
index e7cbbaba38e..375f9cf1859 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -2949,6 +2949,8 @@ int Query_log_event::do_apply_event(Relay_log_info const *rli,
{
LEX_STRING new_db;
int expected_error,actual_error= 0;
+ HA_CREATE_INFO db_options;
+
/*
Colleagues: please never free(thd->catalog) in MySQL. This would
lead to bugs as here thd->catalog is a part of an alloced block,
@@ -2960,6 +2962,13 @@ int Query_log_event::do_apply_event(Relay_log_info const *rli,
new_db.length= db_len;
new_db.str= (char *) rpl_filter->get_rewrite_db(db, &new_db.length);
thd->set_db(new_db.str, new_db.length); /* allocates a copy of 'db' */
+
+ /*
+ Setting the character set and collation of the current database thd->db.
+ */
+ load_db_opt_by_name(thd, thd->db, &db_options);
+ if (db_options.default_table_charset)
+ thd->db_charset= db_options.default_table_charset;
thd->variables.auto_increment_increment= auto_increment_increment;
thd->variables.auto_increment_offset= auto_increment_offset;
@@ -3160,7 +3169,7 @@ compare_errors:
/*
If we expected a non-zero error code, and we don't get the same error
- code, and none of them should be ignored.
+ code, and it should be ignored or is related to a concurrency issue.
*/
actual_error= thd->is_error() ? thd->main_da.sql_errno() : 0;
DBUG_PRINT("info",("expected_error: %d sql_errno: %d",
@@ -3183,7 +3192,8 @@ Default database: '%s'. Query: '%s'",
thd->is_slave_error= 1;
}
/*
- If we get the same error code as expected, or they should be ignored.
+ If we get the same error code as expected and it is not a concurrency
+ issue, or should be ignored.
*/
else if ((expected_error == actual_error &&
!concurrency_error_code(expected_error)) ||
@@ -3194,6 +3204,14 @@ Default database: '%s'. Query: '%s'",
thd->killed= THD::NOT_KILLED;
}
/*
+ If we expected a non-zero error code and get nothing and, it is a concurrency
+ issue or should be ignored.
+ */
+ else if (expected_error && !actual_error &&
+ (concurrency_error_code(expected_error) ||
+ ignored_error_code(expected_error)))
+ ha_autocommit_or_rollback(thd, TRUE);
+ /*
Other cases: mostly we expected no error and get one.
*/
else if (thd->is_slave_error || thd->is_fatal_error)
diff --git a/sql/my_decimal.h b/sql/my_decimal.h
index 21669e82c44..b1df1395dcd 100644
--- a/sql/my_decimal.h
+++ b/sql/my_decimal.h
@@ -48,10 +48,12 @@ C_MODE_END
digits * number of decimal digits in one our big digit - number of decimal
digits in one our big digit decreased by 1 (because we always put decimal
point on the border of our big digits))
+
+ This value is 65 due to historical reasons partly due to it being used
+ as the maximum allowed precision and not the actual maximum precision.
*/
#define DECIMAL_MAX_PRECISION (DECIMAL_MAX_POSSIBLE_PRECISION - 8*2)
#define DECIMAL_MAX_SCALE 30
-#define DECIMAL_NOT_SPECIFIED 31
/**
maximum length of string representation (number of maximum decimal
@@ -75,12 +77,6 @@ inline uint my_decimal_size(uint precision, uint scale)
}
-inline int my_decimal_int_part(uint precision, uint decimals)
-{
- return precision - ((decimals == DECIMAL_NOT_SPECIFIED) ? 0 : decimals);
-}
-
-
/**
my_decimal class limits 'decimal_t' type to what we need in MySQL.
@@ -184,7 +180,7 @@ inline uint my_decimal_length_to_precision(uint length, uint scale,
}
inline uint32 my_decimal_precision_to_length_no_truncation(uint precision,
- uint8 scale,
+ uint scale,
bool unsigned_flag)
{
/*
@@ -196,7 +192,7 @@ inline uint32 my_decimal_precision_to_length_no_truncation(uint precision,
(unsigned_flag || !precision ? 0 : 1));
}
-inline uint32 my_decimal_precision_to_length(uint precision, uint8 scale,
+inline uint32 my_decimal_precision_to_length(uint precision, uint scale,
bool unsigned_flag)
{
/*
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index e3aef02637f..47067c03a85 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -8065,7 +8065,10 @@ int QUICK_INDEX_MERGE_SELECT::read_keys_and_merge()
if (cur_quick->file->inited != handler::NONE)
cur_quick->file->ha_index_end();
if (cur_quick->init() || cur_quick->reset())
+ {
+ delete unique;
DBUG_RETURN(1);
+ }
}
if (result)
@@ -8073,13 +8076,17 @@ int QUICK_INDEX_MERGE_SELECT::read_keys_and_merge()
if (result != HA_ERR_END_OF_FILE)
{
cur_quick->range_end();
+ delete unique;
DBUG_RETURN(result);
}
break;
}
if (thd->killed)
+ {
+ delete unique;
DBUG_RETURN(1);
+ }
/* skip row if it will be retrieved by clustered PK scan */
if (pk_quick_select && pk_quick_select->row_in_ranges())
@@ -8088,8 +8095,10 @@ int QUICK_INDEX_MERGE_SELECT::read_keys_and_merge()
cur_quick->file->position(cur_quick->record);
result= unique->unique_add((char*)cur_quick->file->ref);
if (result)
+ {
+ delete unique;
DBUG_RETURN(1);
-
+ }
}
/*
diff --git a/sql/slave.cc b/sql/slave.cc
index 3b64e23ece5..fac9ee214c5 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -2010,9 +2010,6 @@ static int has_temporary_error(THD *thd)
{
DBUG_ENTER("has_temporary_error");
- if (thd->is_fatal_error)
- DBUG_RETURN(0);
-
DBUG_EXECUTE_IF("all_errors_are_temporary_errors",
if (thd->main_da.is_error())
{
@@ -3738,6 +3735,31 @@ void end_relay_log_info(Relay_log_info* rli)
DBUG_VOID_RETURN;
}
+
+/**
+ Hook to detach the active VIO before closing a connection handle.
+
+ The client API might close the connection (and associated data)
+ in case it encounters a unrecoverable (network) error. This hook
+ is called from the client code before the VIO handle is deleted
+ allows the thread to detach the active vio so it does not point
+ to freed memory.
+
+ Other calls to THD::clear_active_vio throughout this module are
+ redundant due to the hook but are left in place for illustrative
+ purposes.
+*/
+
+extern "C" void slave_io_thread_detach_vio()
+{
+#ifdef SIGNAL_WITH_VIO_CLOSE
+ THD *thd= current_thd;
+ if (thd->slave_thread)
+ thd->clear_active_vio();
+#endif
+}
+
+
/*
Try to connect until successful or slave killed
diff --git a/sql/sql_db.cc b/sql/sql_db.cc
index 98d17fdd318..3fca5bd7df6 100644
--- a/sql/sql_db.cc
+++ b/sql/sql_db.cc
@@ -658,10 +658,8 @@ int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info,
}
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_DB_CREATE_EXISTS, ER(ER_DB_CREATE_EXISTS), db);
- if (!silent)
- my_ok(thd);
error= 0;
- goto exit;
+ goto not_silent;
}
else
{
@@ -698,7 +696,8 @@ int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info,
happened. (This is a very unlikely senario)
*/
}
-
+
+not_silent:
if (!silent)
{
char *query;
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index 0d4bf3f0b8f..d2f90fa9288 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -1066,6 +1066,10 @@ bool mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok)
DBUG_ENTER("mysql_truncate");
bzero((char*) &create_info,sizeof(create_info));
+
+ /* Remove tables from the HANDLER's hash. */
+ mysql_ha_rm_tables(thd, table_list, FALSE);
+
/* If it is a temporary table, close and regenerate it */
if (!dont_send_ok && (table= find_temporary_table(thd, table_list)))
{
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index f1a1c2c9033..cda97ffe521 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -3392,25 +3392,6 @@ static TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
bool not_used;
DBUG_ENTER("create_table_from_items");
- DBUG_EXECUTE_IF("sleep_create_select_before_check_if_exists", my_sleep(6000000););
-
- if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
- create_table->table->db_stat)
- {
- /* Table already exists and was open at open_and_lock_tables() stage. */
- if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
- {
- create_info->table_existed= 1; // Mark that table existed
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
- ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
- create_table->table_name);
- DBUG_RETURN(create_table->table);
- }
-
- my_error(ER_TABLE_EXISTS_ERROR, MYF(0), create_table->table_name);
- DBUG_RETURN(0);
- }
-
tmp_table.alias= 0;
tmp_table.timestamp_field= 0;
tmp_table.s= &share;
@@ -3612,10 +3593,35 @@ select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
thd->binlog_start_trans_and_stmt();
}
- if (!(table= create_table_from_items(thd, create_info, create_table,
- alter_info, &values,
- &extra_lock, hook_ptr)))
- DBUG_RETURN(-1); // abort() deletes table
+ DBUG_EXECUTE_IF("sleep_create_select_before_check_if_exists", my_sleep(6000000););
+
+ if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
+ create_table->table->db_stat)
+ {
+ /* Table already exists and was open at open_and_lock_tables() stage. */
+ if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
+ {
+ /* Mark that table existed */
+ create_info->table_existed= 1;
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
+ ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
+ create_table->table_name);
+ if (thd->current_stmt_binlog_row_based)
+ binlog_show_create_table(&(create_table->table), 1);
+ table= create_table->table;
+ }
+ else
+ {
+ my_error(ER_TABLE_EXISTS_ERROR, MYF(0), create_table->table_name);
+ DBUG_RETURN(-1);
+ }
+ }
+ else
+ if (!(table= create_table_from_items(thd, create_info, create_table,
+ alter_info, &values,
+ &extra_lock, hook_ptr)))
+ /* abort() deletes table */
+ DBUG_RETURN(-1);
if (extra_lock)
{
diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc
index a181a6b3f13..61766e5c509 100644
--- a/sql/sql_partition.cc
+++ b/sql/sql_partition.cc
@@ -6077,6 +6077,9 @@ uint fast_alter_partition_table(THD *thd, TABLE *table,
lpt->pack_frm_len= 0;
thd->work_part_info= part_info;
+ /* Never update timestamp columns when alter */
+ table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
+
if (fast_alter_partition & HA_PARTITION_ONE_PHASE)
{
/*
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 5c95f9111ae..0adb38e0838 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -9380,47 +9380,8 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table,
new_field->set_derivation(item->collation.derivation);
break;
case DECIMAL_RESULT:
- {
- uint8 dec= item->decimals;
- uint8 intg= ((Item_decimal *) item)->decimal_precision() - dec;
- uint32 len= item->max_length;
-
- /*
- Trying to put too many digits overall in a DECIMAL(prec,dec)
- will always throw a warning. We must limit dec to
- DECIMAL_MAX_SCALE however to prevent an assert() later.
- */
-
- if (dec > 0)
- {
- signed int overflow;
-
- dec= min(dec, DECIMAL_MAX_SCALE);
-
- /*
- If the value still overflows the field with the corrected dec,
- we'll throw out decimals rather than integers. This is still
- bad and of course throws a truncation warning.
- +1: for decimal point
- */
-
- const int required_length=
- my_decimal_precision_to_length(intg + dec, dec,
- item->unsigned_flag);
-
- overflow= required_length - len;
-
- if (overflow > 0)
- dec= max(0, dec - overflow); // too long, discard fract
- else
- /* Corrected value fits. */
- len= required_length;
- }
-
- new_field= new Field_new_decimal(len, maybe_null, item->name,
- dec, item->unsigned_flag);
+ new_field= Field_new_decimal::new_decimal_field(item);
break;
- }
case ROW_RESULT:
default:
// This case should never be choosen
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index ae75609e2b6..5c2c351652b 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -7071,8 +7071,6 @@ bool show_create_trigger(THD *thd, const sp_name *trg_name)
/* Perform closing actions and return error status. */
}
- DBUG_ASSERT(num_tables == 1);
-
Table_triggers_list *triggers= lst->table->triggers;
if (!triggers)
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 0066c66eb59..81d00f46000 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -3476,6 +3476,41 @@ void sp_prepare_create_field(THD *thd, Create_field *sql_field)
/*
+ Write CREATE TABLE binlog
+
+ SYNOPSIS
+ write_create_table_bin_log()
+ thd Thread object
+ create_info Create information
+ internal_tmp_table Set to 1 if this is an internal temporary table
+
+ DESCRIPTION
+ This function only is called in mysql_create_table_no_lock and
+ mysql_create_table
+
+ RETURN VALUES
+ NONE
+ */
+static inline void write_create_table_bin_log(THD *thd,
+ const HA_CREATE_INFO *create_info,
+ bool internal_tmp_table)
+{
+ /*
+ Don't write statement if:
+ - It is an internal temporary table,
+ - Row-based logging is used and it we are creating a temporary table, or
+ - The binary log is not open.
+ Otherwise, the statement shall be binlogged.
+ */
+ if (!internal_tmp_table &&
+ (!thd->current_stmt_binlog_row_based ||
+ (thd->current_stmt_binlog_row_based &&
+ !(create_info->options & HA_LEX_CREATE_TMP_TABLE))))
+ write_bin_log(thd, TRUE, thd->query, thd->query_length);
+}
+
+
+/*
Create a table
SYNOPSIS
@@ -3738,6 +3773,7 @@ bool mysql_create_table_no_lock(THD *thd,
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
alias);
error= 0;
+ write_create_table_bin_log(thd, create_info, internal_tmp_table);
goto err;
}
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), alias);
@@ -3858,18 +3894,7 @@ bool mysql_create_table_no_lock(THD *thd,
thd->thread_specific_used= TRUE;
}
- /*
- Don't write statement if:
- - It is an internal temporary table,
- - Row-based logging is used and it we are creating a temporary table, or
- - The binary log is not open.
- Otherwise, the statement shall be binlogged.
- */
- if (!internal_tmp_table &&
- (!thd->current_stmt_binlog_row_based ||
- (thd->current_stmt_binlog_row_based &&
- !(create_info->options & HA_LEX_CREATE_TMP_TABLE))))
- write_bin_log(thd, TRUE, thd->query, thd->query_length);
+ write_create_table_bin_log(thd, create_info, internal_tmp_table);
error= FALSE;
unlock_and_end:
VOID(pthread_mutex_unlock(&LOCK_open));
@@ -3885,6 +3910,7 @@ warn:
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
alias);
create_info->table_existed= 1; // Mark that table existed
+ write_create_table_bin_log(thd, create_info, internal_tmp_table);
goto unlock_and_end;
}
@@ -3936,6 +3962,7 @@ bool mysql_create_table(THD *thd, const char *db, const char *table_name,
table_name);
create_info->table_existed= 1;
result= FALSE;
+ write_create_table_bin_log(thd, create_info, internal_tmp_table);
}
else
{
@@ -5276,6 +5303,24 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table,
goto err; /* purecov: inspected */
}
+goto binlog;
+
+table_exists:
+ if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
+ {
+ char warn_buff[MYSQL_ERRMSG_SIZE];
+ my_snprintf(warn_buff, sizeof(warn_buff),
+ ER(ER_TABLE_EXISTS_ERROR), table_name);
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
+ ER_TABLE_EXISTS_ERROR,warn_buff);
+ }
+ else
+ {
+ my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
+ goto err;
+ }
+
+binlog:
DBUG_EXECUTE_IF("sleep_create_like_before_binlogging", my_sleep(6000000););
/*
@@ -5339,20 +5384,6 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table,
write_bin_log(thd, TRUE, thd->query, thd->query_length);
res= FALSE;
- goto err;
-
-table_exists:
- if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
- {
- char warn_buff[MYSQL_ERRMSG_SIZE];
- my_snprintf(warn_buff, sizeof(warn_buff),
- ER(ER_TABLE_EXISTS_ERROR), table_name);
- push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
- ER_TABLE_EXISTS_ERROR,warn_buff);
- res= FALSE;
- }
- else
- my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
err:
if (name_lock)
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 6fa4a29c7d2..d4c1acabe11 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -732,6 +732,7 @@ int mysql_update(THD *thd,
break;
}
}
+ table->auto_increment_field_not_null= FALSE;
dup_key_found= 0;
/*
Caching the killed status to pass as the arg to query event constuctor;
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 320b43c8e5c..4ed9946a334 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -494,7 +494,6 @@ Item* handle_sql2003_note184_exception(THD *thd, Item* left, bool equal,
enum enum_tx_isolation tx_isolation;
enum Cast_target cast_type;
enum Item_udftype udf_type;
- enum ha_choice choice;
CHARSET_INFO *charset;
thr_lock_type lock_type;
interval_type interval, interval_time_st;
@@ -1164,8 +1163,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%type <ulonglong_number>
ulonglong_num real_ulonglong_num size_number
-%type <choice> choice
-
%type <p_elem_value>
part_bit_expr
@@ -3757,8 +3754,8 @@ partitioning:
LEX_STRING partition_name={C_STRING_WITH_LEN("partition")};
if (!plugin_is_ready(&partition_name, MYSQL_STORAGE_ENGINE_PLUGIN))
{
- my_error(ER_FEATURE_DISABLED, MYF(0),
- "partitioning", "--with-partition");
+ my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0),
+ "--skip-partition");
MYSQL_YYABORT;
}
lex->part_info= new partition_info();
@@ -9066,11 +9063,6 @@ dec_num:
| FLOAT_NUM
;
-choice:
- ulong_num { $$= $1 != 0 ? HA_CHOICE_YES : HA_CHOICE_NO; }
- | DEFAULT { $$= HA_CHOICE_UNDEF; }
- ;
-
procedure_clause:
/* empty */
| PROCEDURE ident /* Procedure name */
diff --git a/sql/table.cc b/sql/table.cc
index 61d37a16ef4..4442243ec14 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -913,6 +913,15 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
we unlock the old value of share->db_plugin before
replacing it with a globally locked version of tmp_plugin
*/
+ /* Check if the partitioning engine is ready */
+ if (!plugin_is_ready(&name, MYSQL_STORAGE_ENGINE_PLUGIN))
+ {
+ error= 8;
+ my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0),
+ "--skip-partition");
+ my_free(buff, MYF(0));
+ goto err;
+ }
plugin_unlock(NULL, share->db_plugin);
share->db_plugin= ha_lock_engine(NULL, partition_hton);
DBUG_PRINT("info", ("setting dbtype to '%.*s' (%d)",
diff --git a/sql/table.h b/sql/table.h
index 653d04b149e..40372fa91cf 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -361,10 +361,8 @@ typedef struct st_table_share
}
enum row_type row_type; /* How rows are stored */
enum tmp_table_type tmp_table;
- /** Transactional or not. Unused; reserved for future versions. */
- enum ha_choice transactional;
- /** Per-page checksums or not. Unused; reserved for future versions. */
- enum ha_choice page_checksum;
+ enum enum_ha_unused unused1;
+ enum enum_ha_unused unused2;
uint ref_count; /* How many TABLE objects uses this */
uint open_count; /* Number of tables in open list */