summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/derror.cc4
-rw-r--r--sql/event_scheduler.cc5
-rw-r--r--sql/field.cc5
-rw-r--r--sql/handler.cc52
-rw-r--r--sql/handler.h5
-rw-r--r--sql/item.cc12
-rw-r--r--sql/item.h106
-rw-r--r--sql/item_func.cc61
-rw-r--r--sql/item_func.h21
-rw-r--r--sql/item_geofunc.cc3
-rw-r--r--sql/item_strfunc.cc1
-rw-r--r--sql/item_subselect.cc307
-rw-r--r--sql/item_subselect.h5
-rw-r--r--sql/item_timefunc.cc37
-rw-r--r--sql/item_xmlfunc.cc2
-rw-r--r--sql/lex.h1
-rw-r--r--sql/log.cc10
-rw-r--r--sql/log_event.cc36
-rw-r--r--sql/mysqld.cc49
-rw-r--r--sql/mysqld.h1
-rw-r--r--sql/opt_sum.cc2
-rw-r--r--sql/sql_base.cc39
-rw-r--r--sql/sql_class.h30
-rw-r--r--sql/sql_insert.cc58
-rw-r--r--sql/sql_join_cache.cc7
-rw-r--r--sql/sql_parse.cc50
-rw-r--r--sql/sql_select.cc33
-rw-r--r--sql/sql_select.h2
-rw-r--r--sql/sql_state.c2
-rw-r--r--sql/sql_table.cc4
-rw-r--r--sql/sql_time.cc69
-rw-r--r--sql/sql_time.h2
-rw-r--r--sql/sql_trigger.cc3
-rw-r--r--sql/sql_update.cc2
-rw-r--r--sql/sql_yacc.yy16
-rw-r--r--sql/sys_vars.cc15
-rw-r--r--sql/table.cc22
-rw-r--r--sql/table.h12
-rw-r--r--sql/tztime.cc4
39 files changed, 644 insertions, 451 deletions
diff --git a/sql/derror.cc b/sql/derror.cc
index baf7163790d..33835992258 100644
--- a/sql/derror.cc
+++ b/sql/derror.cc
@@ -177,8 +177,8 @@ bool read_texts(const char *file_name, const char *language,
O_RDONLY | O_SHARE | O_BINARY,
MYF(0))) < 0)
goto err;
- sql_print_error("An old style --language value with language specific part detected: %s", lc_messages_dir);
- sql_print_error("Use --lc-messages-dir without language specific part instead.");
+ sql_print_warning("An old style --language or -lc-message-dir value with language specific part detected: %s", lc_messages_dir);
+ sql_print_warning("Use --lc-messages-dir without language specific part instead.");
}
funktpos=1;
diff --git a/sql/event_scheduler.cc b/sql/event_scheduler.cc
index 55a3f6b36c4..b41c9e2cda0 100644
--- a/sql/event_scheduler.cc
+++ b/sql/event_scheduler.cc
@@ -42,7 +42,7 @@
cond_wait(mythd, abstime, msg, SCHED_FUNC, __LINE__)
extern pthread_attr_t connection_attrib;
-
+extern ulong event_executed;
Event_db_repository *Event_worker_thread::db_repository;
@@ -557,7 +557,8 @@ Event_scheduler::execute_top(Event_queue_element_for_exec *event_name)
event_name)))
goto error;
- ++started_events;
+ started_events++;
+ executed_events++; // For SHOW STATUS
DBUG_PRINT("info", ("Event is in THD: 0x%lx", (long) new_thd));
DBUG_RETURN(FALSE);
diff --git a/sql/field.cc b/sql/field.cc
index f20d9ba87fc..a3d3d951887 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -5677,7 +5677,7 @@ bool Field_newdate::get_date(MYSQL_TIME *ltime,ulonglong fuzzydate)
if (!tmp)
return fuzzydate & TIME_NO_ZERO_DATE;
if (!ltime->month || !ltime->day)
- return !(fuzzydate & TIME_FUZZY_DATE);
+ return fuzzydate & TIME_NO_ZERO_IN_DATE;
return 0;
}
@@ -9395,9 +9395,12 @@ Field *make_field(TABLE_SHARE *share, uchar *ptr, uint32 field_length,
#ifdef HAVE_SPATIAL
if (f_is_geom(pack_flag))
+ {
+ status_var_increment(current_thd->status_var.feature_gis);
return new Field_geom(ptr,null_pos,null_bit,
unireg_check, field_name, share,
pack_length, geom_type);
+ }
#endif
if (f_is_blob(pack_flag))
return new Field_blob(ptr,null_pos,null_bit,
diff --git a/sql/handler.cc b/sql/handler.cc
index 3f201b266f0..5b22712e595 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -2552,6 +2552,8 @@ int handler::update_auto_increment()
bool append= FALSE;
THD *thd= table->in_use;
struct system_variables *variables= &thd->variables;
+ int result=0, tmp;
+ enum enum_check_fields save_count_cuted_fields;
DBUG_ENTER("handler::update_auto_increment");
/*
@@ -2569,8 +2571,10 @@ int handler::update_auto_increment()
statement (case of INSERT VALUES(null),(3763),(null):
the last NULL needs to insert 3764, not the value of the first NULL plus
1).
+ Ignore negative values.
*/
- adjust_next_insert_id_after_explicit_value(nr);
+ if ((longlong) nr > 0 || (table->next_number_field->flags & UNSIGNED_FLAG))
+ adjust_next_insert_id_after_explicit_value(nr);
insert_id_for_cur_row= 0; // didn't generate anything
DBUG_RETURN(0);
}
@@ -2629,7 +2633,6 @@ int handler::update_auto_increment()
else
nb_desired_values= AUTO_INC_DEFAULT_NB_MAX;
}
- /* This call ignores all its parameters but nr, currently */
get_auto_increment(variables->auto_increment_offset,
variables->auto_increment_increment,
nb_desired_values, &nr,
@@ -2666,29 +2669,23 @@ int handler::update_auto_increment()
}
if (unlikely(nr == ULONGLONG_MAX))
- DBUG_RETURN(HA_ERR_AUTOINC_ERANGE);
+ DBUG_RETURN(HA_ERR_AUTOINC_ERANGE);
DBUG_PRINT("info",("auto_increment: %lu", (ulong) nr));
- if (unlikely(table->next_number_field->store((longlong) nr, TRUE)))
- {
- /*
- first test if the query was aborted due to strict mode constraints
- */
- if (killed_mask_hard(thd->killed) == KILL_BAD_DATA)
- DBUG_RETURN(HA_ERR_AUTOINC_ERANGE);
+ /* Store field without warning (Warning will be printed by insert) */
+ save_count_cuted_fields= thd->count_cuted_fields;
+ thd->count_cuted_fields= CHECK_FIELD_IGNORE;
+ tmp= table->next_number_field->store((longlong) nr, TRUE);
+ thd->count_cuted_fields= save_count_cuted_fields;
+ if (unlikely(tmp)) // Out of range value in store
+ {
/*
- field refused this value (overflow) and truncated it, use the result of
- the truncation (which is going to be inserted); however we try to
- decrease it to honour auto_increment_* variables.
- That will shift the left bound of the reserved interval, we don't
- bother shifting the right bound (anyway any other value from this
- interval will cause a duplicate key).
+ It's better to return an error here than getting a confusing
+ 'duplicate key error' later.
*/
- nr= prev_insert_id(table->next_number_field->val_int(), variables);
- if (unlikely(table->next_number_field->store((longlong) nr, TRUE)))
- nr= table->next_number_field->val_int();
+ result= HA_ERR_AUTOINC_ERANGE;
}
if (append)
{
@@ -2710,6 +2707,10 @@ int handler::update_auto_increment()
already set.
*/
insert_id_for_cur_row= nr;
+
+ if (result) // overflow
+ DBUG_RETURN(result);
+
/*
Set next insert id to point to next auto-increment value to be able to
handle multi-row statements.
@@ -2833,7 +2834,7 @@ void handler::ha_release_auto_increment()
}
-void handler::print_keydup_error(uint key_nr, const char *msg)
+void handler::print_keydup_error(uint key_nr, const char *msg, myf errflag)
{
/* Write the duplicated key in the error message */
char key[MAX_KEY_LENGTH];
@@ -2843,7 +2844,7 @@ void handler::print_keydup_error(uint key_nr, const char *msg)
{
/* Key is unknown */
str.copy("", 0, system_charset_info);
- my_printf_error(ER_DUP_ENTRY, msg, MYF(0), str.c_ptr(), "*UNKNOWN*");
+ my_printf_error(ER_DUP_ENTRY, msg, errflag, str.c_ptr(), "*UNKNOWN*");
}
else
{
@@ -2856,7 +2857,7 @@ void handler::print_keydup_error(uint key_nr, const char *msg)
str.append(STRING_WITH_LEN("..."));
}
my_printf_error(ER_DUP_ENTRY, msg,
- MYF(0), str.c_ptr_safe(), table->key_info[key_nr].name);
+ errflag, str.c_ptr_safe(), table->key_info[key_nr].name);
}
}
@@ -2924,7 +2925,7 @@ void handler::print_error(int error, myf errflag)
uint key_nr=get_dup_key(error);
if ((int) key_nr >= 0)
{
- print_keydup_error(key_nr, ER(ER_DUP_ENTRY_WITH_KEY_NAME));
+ print_keydup_error(key_nr, ER(ER_DUP_ENTRY_WITH_KEY_NAME), errflag);
DBUG_VOID_RETURN;
}
}
@@ -3087,7 +3088,10 @@ void handler::print_error(int error, myf errflag)
textno= ER_AUTOINC_READ_FAILED;
break;
case HA_ERR_AUTOINC_ERANGE:
- textno= ER_WARN_DATA_OUT_OF_RANGE;
+ textno= error;
+ my_error(textno, errflag, table->next_number_field->field_name,
+ table->in_use->warning_info->current_row_for_warning());
+ DBUG_VOID_RETURN;
break;
case HA_ERR_TOO_MANY_CONCURRENT_TRXS:
textno= ER_TOO_MANY_CONCURRENT_TRXS;
diff --git a/sql/handler.h b/sql/handler.h
index b6052412069..874e0de210c 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -1997,7 +1997,7 @@ public:
void adjust_next_insert_id_after_explicit_value(ulonglong nr);
int update_auto_increment();
- void print_keydup_error(uint key_nr, const char *msg);
+ void print_keydup_error(uint key_nr, const char *msg, myf errflag);
virtual void print_error(int error, myf errflag);
virtual bool get_error_message(int error, String *buf);
uint get_dup_key(int error);
@@ -2046,7 +2046,8 @@ public:
if (!error ||
((flags & HA_CHECK_DUP_KEY) &&
(error == HA_ERR_FOUND_DUPP_KEY ||
- error == HA_ERR_FOUND_DUPP_UNIQUE)))
+ error == HA_ERR_FOUND_DUPP_UNIQUE)) ||
+ error == HA_ERR_AUTOINC_ERANGE)
return FALSE;
return TRUE;
}
diff --git a/sql/item.cc b/sql/item.cc
index ac54e1925b7..4d80a153785 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -503,8 +503,8 @@ Item::Item(THD *thd, Item *item):
orig_name(item->orig_name),
max_length(item->max_length),
name_length(item->name_length),
- marker(item->marker),
decimals(item->decimals),
+ marker(item->marker),
maybe_null(item->maybe_null),
in_rollup(item->in_rollup),
null_value(item->null_value),
@@ -7759,6 +7759,13 @@ Item* Item_cache_wrapper::get_tmp_table_item(THD *thd_arg)
}
+bool Item_direct_view_ref::send(Protocol *protocol, String *buffer)
+{
+ if (check_null_ref())
+ return protocol->store_null();
+ return Item_direct_ref::send(protocol, buffer);
+}
+
/**
Prepare referenced field then call usual Item_direct_ref::fix_fields .
@@ -7773,6 +7780,7 @@ Item* Item_cache_wrapper::get_tmp_table_item(THD *thd_arg)
bool Item_direct_view_ref::fix_fields(THD *thd, Item **reference)
{
+ DBUG_ASSERT(1);
/* view fild reference must be defined */
DBUG_ASSERT(*ref);
/* (*ref)->check_cols() will be made in Item_direct_ref::fix_fields */
@@ -9285,7 +9293,7 @@ bool Item_type_holder::join_types(THD *thd, Item *item)
item->max_length, item->decimals));
fld_type= Field::field_type_merge(fld_type, get_real_type(item));
{
- int item_decimals= item->decimals;
+ uint item_decimals= item->decimals;
/* fix variable decimals which always is NOT_FIXED_DEC */
if (Field::result_merge_type(fld_type) == INT_RESULT)
item_decimals= 0;
diff --git a/sql/item.h b/sql/item.h
index 8855996b76c..3136bb00394 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -618,8 +618,8 @@ public:
calls.
*/
uint name_length; /* Length of name */
+ uint decimals;
int8 marker;
- uint8 decimals;
bool maybe_null; /* If item may be null */
bool in_rollup; /* If used in GROUP BY list
of a query with ROLLUP */
@@ -3161,20 +3161,29 @@ class Item_direct_view_ref :public Item_direct_ref
{
Item_equal *item_equal;
TABLE_LIST *view;
+ TABLE *null_ref_table;
+
+ bool check_null_ref()
+ {
+ if (null_ref_table == NULL)
+ {
+ null_ref_table= view->get_real_join_table();
+ }
+ if (null_ref_table->null_row)
+ {
+ null_value= 1;
+ return TRUE;
+ }
+ return FALSE;
+ }
public:
Item_direct_view_ref(Name_resolution_context *context_arg, Item **item,
const char *table_name_arg,
const char *field_name_arg,
TABLE_LIST *view_arg)
:Item_direct_ref(context_arg, item, table_name_arg, field_name_arg),
- item_equal(0), view(view_arg) {}
- /* 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_equal(0) {}
- Item_direct_view_ref(TABLE_LIST *view_arg, Item **item,
- const char *field_name_arg)
- :Item_direct_ref(view_arg, item, field_name_arg), item_equal(0)
- {}
+ item_equal(0), view(view_arg),
+ null_ref_table(NULL) {}
bool fix_fields(THD *, Item **);
bool eq(const Item *item, bool binary_cmp) const;
@@ -3205,6 +3214,85 @@ public:
view_arg->view_used_tables|= (*ref)->used_tables();
return 0;
}
+ void save_val(Field *to)
+ {
+ if (check_null_ref())
+ to->set_null();
+ else
+ Item_direct_ref::save_val(to);
+ }
+ double val_real()
+ {
+ if (check_null_ref())
+ return 0;
+ else
+ return Item_direct_ref::val_real();
+ }
+ longlong val_int()
+ {
+ if (check_null_ref())
+ return 0;
+ else
+ return Item_direct_ref::val_int();
+ }
+ String *val_str(String* tmp)
+ {
+ if (check_null_ref())
+ return NULL;
+ else
+ return Item_direct_ref::val_str(tmp);
+ }
+ my_decimal *val_decimal(my_decimal *tmp)
+ {
+ if (check_null_ref())
+ return NULL;
+ else
+ return Item_direct_ref::val_decimal(tmp);
+ }
+ bool val_bool()
+ {
+ if (check_null_ref())
+ return 0;
+ else
+ return Item_direct_ref::val_bool();
+ }
+ bool is_null()
+ {
+ if (check_null_ref())
+ return 1;
+ else
+ return Item_direct_ref::is_null();
+ }
+ bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
+ {
+ if (check_null_ref())
+ {
+ bzero((char*) ltime,sizeof(*ltime));
+ return 1;
+ }
+ return Item_direct_ref::get_date(ltime, fuzzydate);
+ }
+ bool send(Protocol *protocol, String *buffer);
+ void save_org_in_field(Field *field)
+ {
+ if (check_null_ref())
+ field->set_null();
+ else
+ Item_direct_ref::save_val(field);
+ }
+ void save_in_result_field(bool no_conversions)
+ {
+ if (check_null_ref())
+ result_field->set_null();
+ else
+ Item_direct_ref::save_in_result_field(no_conversions);
+ }
+
+ void cleanup()
+ {
+ null_ref_table= NULL;
+ Item_direct_ref::cleanup();
+ }
};
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 7a7cdd4ba02..441eb37d701 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -6046,6 +6046,8 @@ bool Item_func_match::fix_fields(THD *thd, Item **ref)
DBUG_ASSERT(fixed == 0);
Item *UNINIT_VAR(item); // Safe as arg_count is > 1
+ status_var_increment(thd->status_var.feature_fulltext);
+
maybe_null=1;
join_key=0;
@@ -6816,3 +6818,62 @@ longlong Item_func_uuid_short::val_int()
mysql_mutex_unlock(&LOCK_short_uuid_generator);
return (longlong) val;
}
+
+
+/**
+ Last_value - return last argument.
+*/
+
+void Item_func_last_value::evaluate_sideeffects()
+{
+ DBUG_ASSERT(fixed == 1 && arg_count > 0);
+ for (uint i= 0; i < arg_count-1 ; i++)
+ args[i]->val_int();
+}
+
+String *Item_func_last_value::val_str(String *str)
+{
+ String *tmp;
+ evaluate_sideeffects();
+ tmp= last_value->val_str(str);
+ null_value= last_value->null_value;
+ return tmp;
+}
+
+longlong Item_func_last_value::val_int()
+{
+ longlong tmp;
+ evaluate_sideeffects();
+ tmp= last_value->val_int();
+ null_value= last_value->null_value;
+ return tmp;
+}
+
+double Item_func_last_value::val_real()
+{
+ double tmp;
+ evaluate_sideeffects();
+ tmp= last_value->val_real();
+ null_value= last_value->null_value;
+ return tmp;
+}
+
+my_decimal *Item_func_last_value::val_decimal(my_decimal *decimal_value)
+{
+ my_decimal *tmp;
+ evaluate_sideeffects();
+ tmp= last_value->val_decimal(decimal_value);
+ null_value= last_value->null_value;
+ return tmp;
+}
+
+
+void Item_func_last_value::fix_length_and_dec()
+{
+ last_value= args[arg_count -1];
+ decimals= last_value->decimals;
+ max_length= last_value->max_length;
+ collation.set(last_value->collation.collation);
+ maybe_null= last_value->maybe_null;
+ unsigned_flag= last_value->unsigned_flag;
+}
diff --git a/sql/item_func.h b/sql/item_func.h
index 111479c8e52..586444e0e4e 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -2003,6 +2003,27 @@ public:
}
};
+
+class Item_func_last_value :public Item_func
+{
+protected:
+ Item *last_value;
+public:
+ Item_func_last_value(List<Item> &list) :Item_func(list) {}
+ double val_real();
+ longlong val_int();
+ String *val_str(String *);
+ my_decimal *val_decimal(my_decimal *);
+ void fix_length_and_dec();
+ enum Item_result result_type () const { return last_value->result_type(); }
+ const char *func_name() const { return "last_value"; }
+ table_map not_null_tables() const { return 0; }
+ enum_field_types field_type() const { return last_value->field_type(); }
+ bool const_item() const { return 0; }
+ void evaluate_sideeffects();
+};
+
+
Item *get_system_var(THD *thd, enum_var_type var_type, LEX_STRING name,
LEX_STRING component);
extern bool check_reserved_words(LEX_STRING *name);
diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc
index 3648b10af3f..bc89a6c14b3 100644
--- a/sql/item_geofunc.cc
+++ b/sql/item_geofunc.cc
@@ -1695,7 +1695,8 @@ count_distance:
for (dist_point= collector.get_first(); dist_point; dist_point= dist_point->get_next())
{
/* We only check vertices of object 2 */
- if (dist_point->shape < obj2_si)
+ if (dist_point->type != Gcalc_heap::nt_shape_node ||
+ dist_point->shape < obj2_si)
continue;
/* if we have an edge to check */
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index c5d1edbe475..ebfca684ccb 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -3774,6 +3774,7 @@ bool Item_func_dyncol_create::fix_fields(THD *thd, Item **ref)
(arg_count / 2));
nums= (uint *) alloc_root(thd->mem_root,
sizeof(uint) * (arg_count / 2));
+ status_var_increment(thd->status_var.feature_dynamic_columns);
return res || vals == 0 || nums == 0;
}
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index c10b75c154b..efc058763c0 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -220,6 +220,8 @@ bool Item_subselect::fix_fields(THD *thd_param, Item **ref)
uint8 uncacheable;
bool res;
+ status_var_increment(thd->status_var.feature_subquery);
+
DBUG_ASSERT(fixed == 0);
engine->set_thd((thd= thd_param));
if (!done_first_fix_fields)
@@ -733,6 +735,19 @@ bool Item_subselect::expr_cache_is_needed(THD *thd)
/**
+ Check if the left IN argument contains NULL values.
+
+ @retval TRUE there are NULLs
+ @retval FALSE otherwise
+*/
+
+inline bool Item_in_subselect::left_expr_has_null()
+{
+ return (*(optimizer->get_cache()))->null_value;
+}
+
+
+/**
Check if an expression cache is needed for this subquery
@param thd Thread handle
@@ -3283,161 +3298,51 @@ int subselect_uniquesubquery_engine::scan_table()
}
-/*
- Copy ref key and check for null parts in it
-
- SYNOPSIS
- subselect_uniquesubquery_engine::copy_ref_key()
-
- DESCRIPTION
- Copy ref key and check for null parts in it.
- Depending on the nullability and conversion problems this function
- recognizes and processes the following states :
- 1. Partial match on top level. This means IN has a value of FALSE
- regardless of the data in the subquery table.
- Detected by finding a NULL in the left IN operand of a top level
- expression.
- We may actually skip reading the subquery, so return TRUE to skip
- the table scan in subselect_uniquesubquery_engine::exec and make
- the value of the IN predicate a NULL (that is equal to FALSE on
- top level).
- 2. No exact match when IN is nested inside another predicate.
- Detected by finding a NULL in the left IN operand when IN is not
- a top level predicate.
- We cannot have an exact match. But we must proceed further with a
- table scan to find out if it's a partial match (and IN has a value
- of NULL) or no match (and IN has a value of FALSE).
- So we return FALSE to continue with the scan and see if there are
- any record that would constitute a partial match (as we cannot
- determine that from the index).
- 3. Error converting the left IN operand to the column type of the
- right IN operand. This counts as no match (and IN has the value of
- FALSE). We mark the subquery table cursor as having no more rows
- (to ensure that the processing that follows will not find a match)
- and return FALSE, so IN is not treated as returning NULL.
+/**
+ Copy ref key for index access into the only subquery table.
+ @details
+ Copy ref key and check for conversion problems.
+ If there is an error converting the left IN operand to the column type of
+ the right IN operand count it as no match. In this case IN has the value of
+ FALSE. We mark the subquery table cursor as having no more rows (to ensure
+ that the processing that follows will not find a match) and return FALSE,
+ so IN is not treated as returning NULL.
- RETURN
- FALSE - The value of the IN predicate is not known. Proceed to find the
- value of the IN predicate using the determined values of
- null_keypart and table->status.
- TRUE - IN predicate has a value of NULL. Stop the processing right there
- and return NULL to the outer predicates.
+ @returns
+ @retval FALSE The outer ref was copied into an index lookup key.
+ @retval TRUE The outer ref cannot possibly match any row, IN is FALSE.
*/
-bool subselect_uniquesubquery_engine::copy_ref_key()
+bool subselect_uniquesubquery_engine::copy_ref_key(bool skip_constants)
{
DBUG_ENTER("subselect_uniquesubquery_engine::copy_ref_key");
for (store_key **copy= tab->ref.key_copy ; *copy ; copy++)
{
- if ((*copy)->store_key_is_const())
- continue;
- tab->ref.key_err= (*copy)->copy();
-
- /*
- When there is a NULL part in the key we don't need to make index
- lookup for such key thus we don't need to copy whole key.
- If we later should do a sequential scan return OK. Fail otherwise.
-
- See also the comment for the subselect_uniquesubquery_engine::exec()
- function.
- */
- null_keypart= (*copy)->null_key;
- if (null_keypart)
- {
- bool top_level= ((Item_in_subselect *) item)->is_top_level_item();
- if (top_level)
- {
- /* Partial match on top level */
- DBUG_RETURN(1);
- }
- else
- {
- /* No exact match when IN is nested inside another predicate */
- break;
- }
- }
-
- /*
- Check if the error is equal to STORE_KEY_FATAL. This is not expressed
- using the store_key::store_key_result enum because ref.key_err is a
- boolean and we want to detect both TRUE and STORE_KEY_FATAL from the
- space of the union of the values of [TRUE, FALSE] and
- store_key::store_key_result.
- TODO: fix the variable an return types.
- */
- if (tab->ref.key_err & 1)
- {
- /*
- Error converting the left IN operand to the column type of the right
- IN operand.
- */
- tab->table->status= STATUS_NOT_FOUND;
- break;
- }
- }
- DBUG_RETURN(0);
-}
-
-
-/*
- @retval 1 A NULL was found in the outer reference, index lookup is
- not applicable, the outer ref is unsusable as a lookup key,
- use some other method to find a match.
- @retval 0 The outer ref was copied into an index lookup key.
- @retval -1 The outer ref cannot possibly match any row, IN is FALSE.
-*/
-/* TIMOUR: this method is a variant of copy_ref_key(), needs refactoring. */
-
-int subselect_uniquesubquery_engine::copy_ref_key_simple()
-{
- for (store_key **copy= tab->ref.key_copy ; *copy ; copy++)
- {
enum store_key::store_key_result store_res;
+ if (skip_constants && (*copy)->store_key_is_const())
+ continue;
store_res= (*copy)->copy();
tab->ref.key_err= store_res;
- /*
- When there is a NULL part in the key we don't need to make index
- lookup for such key thus we don't need to copy whole key.
- If we later should do a sequential scan return OK. Fail otherwise.
-
- See also the comment for the subselect_uniquesubquery_engine::exec()
- function.
- */
- null_keypart= (*copy)->null_key;
- if (null_keypart)
- return 1;
-
- /*
- Check if the error is equal to STORE_KEY_FATAL. This is not expressed
- using the store_key::store_key_result enum because ref.key_err is a
- boolean and we want to detect both TRUE and STORE_KEY_FATAL from the
- space of the union of the values of [TRUE, FALSE] and
- store_key::store_key_result.
- TODO: fix the variable an return types.
- */
if (store_res == store_key::STORE_KEY_FATAL)
{
/*
Error converting the left IN operand to the column type of the right
IN operand.
*/
- return -1;
+ DBUG_RETURN(true);
}
}
- return 0;
+ DBUG_RETURN(false);
}
-/*
- Execute subselect
-
- SYNOPSIS
- subselect_uniquesubquery_engine::exec()
+/**
+ Execute subselect via unique index lookup
- DESCRIPTION
+ @details
Find rows corresponding to the ref key using index access.
If some part of the lookup key is NULL, then we're evaluating
NULL IN (SELECT ... )
@@ -3454,11 +3359,11 @@ int subselect_uniquesubquery_engine::copy_ref_key_simple()
The result of this function (info about whether a row was found) is
stored in this->empty_result_set.
- NOTE
- RETURN
- FALSE - ok
- TRUE - an error occured while scanning
+ @returns
+ @retval 0 OK
+ @retval 1 notify caller to call Item_subselect::reset(),
+ in most cases reset() sets the result to NULL
*/
int subselect_uniquesubquery_engine::exec()
@@ -3468,32 +3373,30 @@ int subselect_uniquesubquery_engine::exec()
TABLE *table= tab->table;
empty_result_set= TRUE;
table->status= 0;
+ Item_in_subselect *in_subs= (Item_in_subselect *) item;
+
+ if (!tab->preread_init_done && tab->preread_init())
+ DBUG_RETURN(1);
- /* TODO: change to use of 'full_scan' here? */
- if (copy_ref_key())
+ if (in_subs->left_expr_has_null())
{
/*
- TIMOUR: copy_ref_key() == 1 means NULL result, not error, why return 1?
- Check who reiles on this result.
+ The case when all values in left_expr are NULL is handled by
+ Item_in_optimizer::val_int().
*/
- DBUG_RETURN(1);
+ if (in_subs->is_top_level_item())
+ DBUG_RETURN(1); /* notify caller to call reset() and set NULL value. */
+ else
+ DBUG_RETURN(scan_table());
}
- if (table->status)
+
+ if (copy_ref_key(true))
{
- /*
- We know that there will be no rows even if we scan.
- Can be set in copy_ref_key.
- */
- ((Item_in_subselect *) item)->value= 0;
+ /* We know that there will be no rows even if we scan. */
+ in_subs->value= 0;
DBUG_RETURN(0);
}
- if (!tab->preread_init_done && tab->preread_init())
- DBUG_RETURN(1);
-
- if (null_keypart)
- DBUG_RETURN(scan_table());
-
if (!table->file->inited)
table->file->ha_index_init(tab->ref.key, 0);
error= table->file->ha_index_read_map(table->record[0],
@@ -3569,14 +3472,10 @@ subselect_uniquesubquery_engine::~subselect_uniquesubquery_engine()
}
-/*
- Index-lookup subselect 'engine' - run the subquery
-
- SYNOPSIS
- subselect_indexsubquery_engine:exec()
- full_scan
+/**
+ Execute subselect via unique index lookup
- DESCRIPTION
+ @details
The engine is used to resolve subqueries in form
oe IN (SELECT key FROM tbl WHERE subq_where)
@@ -3591,7 +3490,7 @@ subselect_uniquesubquery_engine::~subselect_uniquesubquery_engine()
row that satisfies subq_where. If found, return NULL, otherwise
return FALSE.
- TODO
+ @todo
The step #1 can be optimized further when the index has several key
parts. Consider a subquery:
@@ -3616,9 +3515,10 @@ subselect_uniquesubquery_engine::~subselect_uniquesubquery_engine()
cheaper. We can use index statistics to quickly check whether "ref" scan
will be cheaper than full table scan.
- RETURN
- 0
- 1
+ @returns
+ @retval 0 OK
+ @retval 1 notify caller to call Item_subselect::reset(),
+ in most cases reset() sets the result to NULL
*/
int subselect_indexsubquery_engine::exec()
@@ -3627,10 +3527,10 @@ int subselect_indexsubquery_engine::exec()
int error;
bool null_finding= 0;
TABLE *table= tab->table;
+ Item_in_subselect *in_subs= (Item_in_subselect *) item;
((Item_in_subselect *) item)->value= 0;
empty_result_set= TRUE;
- null_keypart= 0;
table->status= 0;
if (check_null)
@@ -3640,25 +3540,27 @@ int subselect_indexsubquery_engine::exec()
((Item_in_subselect *) item)->was_null= 0;
}
- /* Copy the ref key and check for nulls... */
- if (copy_ref_key())
+ if (!tab->preread_init_done && tab->preread_init())
DBUG_RETURN(1);
- if (table->status)
+ if (in_subs->left_expr_has_null())
{
- /*
- We know that there will be no rows even if we scan.
- Can be set in copy_ref_key.
+ /*
+ The case when all values in left_expr are NULL is handled by
+ Item_in_optimizer::val_int().
*/
- ((Item_in_subselect *) item)->value= 0;
- DBUG_RETURN(0);
+ if (in_subs->is_top_level_item())
+ DBUG_RETURN(1); /* notify caller to call reset() and set NULL value. */
+ else
+ DBUG_RETURN(scan_table());
}
- if (!tab->preread_init_done && tab->preread_init())
- DBUG_RETURN(1);
-
- if (null_keypart)
- DBUG_RETURN(scan_table());
+ if (copy_ref_key(true))
+ {
+ /* We know that there will be no rows even if we scan. */
+ in_subs->value= 0;
+ DBUG_RETURN(0);
+ }
if (!table->file->inited)
table->file->ha_index_init(tab->ref.key, 1);
@@ -5429,37 +5331,42 @@ subselect_partial_match_engine::subselect_partial_match_engine(
int subselect_partial_match_engine::exec()
{
Item_in_subselect *item_in= (Item_in_subselect *) item;
- int copy_res, lookup_res;
+ int lookup_res;
- /* Try to find a matching row by index lookup. */
- copy_res= lookup_engine->copy_ref_key_simple();
- if (copy_res == -1)
- {
- /* The result is FALSE based on the outer reference. */
- item_in->value= 0;
- item_in->null_value= 0;
- return 0;
- }
- else if (copy_res == 0)
+ DBUG_ASSERT(!(item_in->left_expr_has_null() &&
+ item_in->is_top_level_item()));
+
+ if (!item_in->left_expr_has_null())
{
- /* Search for a complete match. */
- if ((lookup_res= lookup_engine->index_lookup()))
+ /* Try to find a matching row by index lookup. */
+ if (lookup_engine->copy_ref_key(false))
{
- /* An error occured during lookup(). */
+ /* The result is FALSE based on the outer reference. */
item_in->value= 0;
item_in->null_value= 0;
- return lookup_res;
+ return 0;
}
- else if (item_in->value || !count_columns_with_nulls)
+ else
{
- /*
- A complete match was found, the result of IN is TRUE.
- If no match was found, and there are no NULLs in the materialized
- subquery, then the result is guaranteed to be false because this
- branch is executed when the outer reference has no NULLs as well.
- Notice: (this->item == lookup_engine->item)
- */
- return 0;
+ /* Search for a complete match. */
+ if ((lookup_res= lookup_engine->index_lookup()))
+ {
+ /* An error occured during lookup(). */
+ item_in->value= 0;
+ item_in->null_value= 0;
+ return lookup_res;
+ }
+ else if (item_in->value || !count_columns_with_nulls)
+ {
+ /*
+ A complete match was found, the result of IN is TRUE.
+ If no match was found, and there are no NULLs in the materialized
+ subquery, then the result is guaranteed to be false because this
+ branch is executed when the outer reference has no NULLs as well.
+ Notice: (this->item == lookup_engine->item)
+ */
+ return 0;
+ }
}
}
diff --git a/sql/item_subselect.h b/sql/item_subselect.h
index 05c4528490f..2a64c63a1be 100644
--- a/sql/item_subselect.h
+++ b/sql/item_subselect.h
@@ -591,6 +591,7 @@ public:
/* Inform 'this' that it was computed, and contains a valid result. */
void set_first_execution() { if (first_execution) first_execution= FALSE; }
bool expr_cache_is_needed(THD *thd);
+ inline bool left_expr_has_null();
int optimize(double *out_rows, double *cost);
/*
@@ -869,7 +870,6 @@ protected:
expression is NULL.
*/
bool empty_result_set;
- bool null_keypart; /* TRUE <=> constructed search tuple has a NULL */
public:
// constructor can assign THD because it will be called after JOIN::prepare
@@ -893,8 +893,7 @@ public:
bool no_tables();
int index_lookup(); /* TIMOUR: this method needs refactoring. */
int scan_table();
- bool copy_ref_key();
- int copy_ref_key_simple(); /* TIMOUR: this method needs refactoring. */
+ bool copy_ref_key(bool skip_constants);
bool no_rows() { return empty_result_set; }
virtual enum_engine_type engine_type() { return UNIQUESUBQUERY_ENGINE; }
};
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index 857d9bc2080..117276e488b 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -361,9 +361,8 @@ static bool extract_date_time(DATE_TIME_FORMAT *format,
{
uint days;
days= calc_daynr(l_time->year,1,1) + yearday - 1;
- if (days <= 0 || days > MAX_DAY_NUMBER)
+ if (get_date_from_daynr(days,&l_time->year,&l_time->month,&l_time->day))
goto err;
- get_date_from_daynr(days,&l_time->year,&l_time->month,&l_time->day);
}
if (week_number >= 0 && weekday)
@@ -408,9 +407,8 @@ static bool extract_date_time(DATE_TIME_FORMAT *format,
(weekday - 1);
}
- if (days <= 0 || days > MAX_DAY_NUMBER)
+ if (get_date_from_daynr(days,&l_time->year,&l_time->month,&l_time->day))
goto err;
- get_date_from_daynr(days,&l_time->year,&l_time->month,&l_time->day);
}
if (l_time->month > 12 || l_time->day > 31 || l_time->hour > 23 ||
@@ -768,7 +766,7 @@ longlong Item_func_to_days::val_int()
{
DBUG_ASSERT(fixed == 1);
MYSQL_TIME ltime;
- if (get_arg0_date(&ltime, TIME_NO_ZERO_DATE))
+ if (get_arg0_date(&ltime, TIME_NO_ZERO_DATE | TIME_NO_ZERO_IN_DATE))
return 0;
return (longlong) calc_daynr(ltime.year,ltime.month,ltime.day);
}
@@ -808,7 +806,7 @@ longlong Item_func_to_seconds::val_int()
MYSQL_TIME ltime;
longlong seconds;
longlong days;
- if (get_arg0_date(&ltime, TIME_NO_ZERO_DATE))
+ if (get_arg0_date(&ltime, TIME_NO_ZERO_DATE | TIME_NO_ZERO_IN_DATE))
return 0;
seconds= ltime.hour * 3600L + ltime.minute * 60 + ltime.second;
seconds=ltime.neg ? -seconds : seconds;
@@ -1501,10 +1499,11 @@ bool Item_func_from_days::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date)
if ((fuzzy_date & TIME_NO_ZERO_DATE) && value == 0)
return (null_value= 1);
bzero(ltime, sizeof(MYSQL_TIME));
- get_date_from_daynr((long) value, &ltime->year, &ltime->month, &ltime->day);
+ if (get_date_from_daynr((long) value, &ltime->year, &ltime->month,
+ &ltime->day))
+ return (null_value= 1);
- if ((fuzzy_date & TIME_NO_ZERO_DATE) &&
- (ltime->year == 0 || ltime->month == 0 || ltime->day == 0))
+ if ((fuzzy_date & TIME_NO_ZERO_DATE) && ltime->year == 0)
return (null_value= 1);
ltime->time_type= MYSQL_TIMESTAMP_DATE;
@@ -2043,7 +2042,7 @@ bool Item_date_add_interval::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date)
{
INTERVAL interval;
- if (args[0]->get_date(ltime, TIME_NO_ZERO_DATE | TIME_FUZZY_DATE) ||
+ if (args[0]->get_date(ltime, TIME_NO_ZERO_DATE | TIME_FUZZY_DATE | TIME_NO_ZERO_IN_DATE) ||
get_interval_value(args[1], int_type, &interval))
return (null_value=1);
@@ -2514,14 +2513,12 @@ bool Item_func_makedate::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date)
year= year_2000_handling(year);
days= calc_daynr(year,1,1) + daynr - 1;
- /* Day number from year 0 to 9999-12-31 */
- if (days >= 0 && days <= MAX_DAY_NUMBER)
- {
- bzero(ltime, sizeof(*ltime));
- ltime->time_type= MYSQL_TIMESTAMP_DATE;
- get_date_from_daynr(days, &ltime->year, &ltime->month, &ltime->day);
- return (null_value= 0);
- }
+ if (get_date_from_daynr(days, &ltime->year, &ltime->month, &ltime->day))
+ goto err;
+ ltime->time_type= MYSQL_TIMESTAMP_DATE;
+ ltime->neg= 0;
+ ltime->hour= ltime->minute= ltime->second= ltime->second_part= 0;
+ return (null_value= 0);
err:
return (null_value= 1);
@@ -2615,8 +2612,8 @@ bool Item_func_add_time::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date)
if (!is_time)
{
- get_date_from_daynr(days,&ltime->year,&ltime->month,&ltime->day);
- if (!ltime->day)
+ if (get_date_from_daynr(days,&ltime->year,&ltime->month,&ltime->day) ||
+ !ltime->day)
return (null_value= 1);
return (null_value= 0);
}
diff --git a/sql/item_xmlfunc.cc b/sql/item_xmlfunc.cc
index 0fa2d39aea9..ae0a74c5ba6 100644
--- a/sql/item_xmlfunc.cc
+++ b/sql/item_xmlfunc.cc
@@ -2601,6 +2601,8 @@ void Item_xml_str_func::fix_length_and_dec()
MY_XPATH xpath;
int rc;
+ status_var_increment(current_thd->status_var.feature_xml);
+
nodeset_func= 0;
if (agg_arg_charsets_for_comparison(collation, args, arg_count))
diff --git a/sql/lex.h b/sql/lex.h
index 9f4369630a0..9bf4c439cb6 100644
--- a/sql/lex.h
+++ b/sql/lex.h
@@ -302,6 +302,7 @@ static SYMBOL symbols[] = {
{ "KILL", SYM(KILL_SYM)},
{ "LANGUAGE", SYM(LANGUAGE_SYM)},
{ "LAST", SYM(LAST_SYM)},
+ { "LAST_VALUE", SYM(LAST_VALUE)},
{ "LEADING", SYM(LEADING)},
{ "LEAVE", SYM(LEAVE_SYM)},
{ "LEAVES", SYM(LEAVES)},
diff --git a/sql/log.cc b/sql/log.cc
index 50c66135f24..e4db7b2eb0f 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -3277,7 +3277,7 @@ bool MYSQL_BIN_LOG::open(const char *log_name,
bytes_written+= description_event_for_queue->data_written;
}
if (flush_io_cache(&log_file) ||
- mysql_file_sync(log_file.file, MYF(MY_WME)))
+ mysql_file_sync(log_file.file, MYF(MY_WME|MY_SYNC_FILESIZE)))
goto err;
mysql_mutex_lock(&LOCK_commit_ordered);
strmake(last_commit_pos_file, log_file_name,
@@ -3307,7 +3307,7 @@ bool MYSQL_BIN_LOG::open(const char *log_name,
strlen(log_file_name)) ||
my_b_write(&index_file, (uchar*) "\n", 1) ||
flush_io_cache(&index_file) ||
- mysql_file_sync(index_file.file, MYF(MY_WME)))
+ mysql_file_sync(index_file.file, MYF(MY_WME|MY_SYNC_FILESIZE)))
goto err;
#ifdef HAVE_REPLICATION
@@ -3416,7 +3416,7 @@ static bool copy_up_file_and_fill(IO_CACHE *index_file, my_off_t offset)
}
/* The following will either truncate the file or fill the end with \n' */
if (mysql_file_chsize(file, offset - init_offset, '\n', MYF(MY_WME)) ||
- mysql_file_sync(file, MYF(MY_WME)))
+ mysql_file_sync(file, MYF(MY_WME|MY_SYNC_FILESIZE)))
goto err;
/* Reset data in old index cache */
@@ -4136,7 +4136,7 @@ int MYSQL_BIN_LOG::sync_purge_index_file()
DBUG_ENTER("MYSQL_BIN_LOG::sync_purge_index_file");
if ((error= flush_io_cache(&purge_index_file)) ||
- (error= my_sync(purge_index_file.file, MYF(MY_WME))))
+ (error= my_sync(purge_index_file.file, MYF(MY_WME|MY_SYNC_FILESIZE))))
DBUG_RETURN(error);
DBUG_RETURN(error);
@@ -4753,7 +4753,7 @@ bool MYSQL_BIN_LOG::flush_and_sync(bool *synced)
if (sync_period && ++sync_counter >= sync_period)
{
sync_counter= 0;
- err= mysql_file_sync(fd, MYF(MY_WME));
+ err= mysql_file_sync(fd, MYF(MY_WME|MY_SYNC_FILESIZE));
if (synced)
*synced= 1;
#ifndef DBUG_OFF
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 25ab7b7c870..132f778ee08 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -1087,6 +1087,9 @@ bool Log_event::write_header(IO_CACHE* file, ulong event_data_length)
ulong now;
bool ret;
DBUG_ENTER("Log_event::write_header");
+ DBUG_PRINT("enter", ("filepos: %lld length: %lu type: %d",
+ (longlong) my_b_tell(file), event_data_length,
+ (int) get_type_code()));
/* Store number of bytes that will be written by this event */
data_written= event_data_length + sizeof(header);
@@ -3625,6 +3628,34 @@ int Query_log_event::do_apply_event(Relay_log_info const *rli)
return do_apply_event(rli, query, q_len);
}
+/**
+ Compare if two errors should be regarded as equal.
+ This is to handle the case when you can get slightly different errors
+ on master and slave for the same thing.
+ @param
+ expected_error Error we got on master
+ actual_error Error we got on slave
+
+ @return
+ 1 Errors are equal
+ 0 Errors are different
+*/
+
+bool test_if_equal_repl_errors(int expected_error, int actual_error)
+{
+ if (expected_error == actual_error)
+ return 1;
+ switch (expected_error) {
+ case ER_DUP_ENTRY:
+ case ER_AUTOINC_READ_FAILED:
+ return (actual_error == ER_AUTOINC_READ_FAILED ||
+ actual_error == HA_ERR_AUTOINC_ERANGE);
+ default:
+ break;
+ }
+ return 0;
+}
+
/**
@todo
@@ -3937,7 +3968,8 @@ compare_errors:
DBUG_PRINT("info",("expected_error: %d sql_errno: %d",
expected_error, actual_error));
- if ((expected_error && expected_error != actual_error &&
+ if ((expected_error &&
+ !test_if_equal_repl_errors(expected_error, actual_error) &&
!concurrency_error_code(expected_error)) &&
!ignored_error_code(actual_error) &&
!ignored_error_code(expected_error))
@@ -3959,7 +3991,7 @@ Default database: '%s'. Query: '%s'",
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 &&
+ else if ((test_if_equal_repl_errors(expected_error, actual_error) &&
!concurrency_error_code(expected_error)) ||
ignored_error_code(actual_error))
{
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index fa6b085c3ad..96ea789edd7 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -360,7 +360,7 @@ static DYNAMIC_ARRAY all_options;
/* Global variables */
-bool opt_bin_log, opt_ignore_builtin_innodb= 0;
+bool opt_bin_log, opt_bin_log_used=0, opt_ignore_builtin_innodb= 0;
my_bool opt_log, opt_slow_log, debug_assert_if_crashed_table= 0, opt_help= 0, opt_abort;
ulonglong log_output_options;
my_bool opt_userstat_running;
@@ -482,6 +482,7 @@ ulonglong binlog_stmt_cache_size=0;
ulonglong max_binlog_stmt_cache_size=0;
ulonglong query_cache_size=0;
ulong refresh_version; /* Increments on each reload */
+ulong executed_events=0;
query_id_t global_query_id;
my_atomic_rwlock_t global_query_id_lock;
my_atomic_rwlock_t thread_running_lock;
@@ -579,7 +580,7 @@ char mysql_real_data_home[FN_REFLEN],
lc_messages_dir[FN_REFLEN], reg_ext[FN_EXTLEN],
mysql_charsets_dir[FN_REFLEN],
*opt_init_file, *opt_tc_log_file;
-char *lc_messages_dir_ptr, *log_error_file_ptr;
+char *lc_messages_dir_ptr= lc_messages_dir, *log_error_file_ptr;
char mysql_unpacked_real_data_home[FN_REFLEN];
int mysql_unpacked_real_data_home_len;
uint mysql_real_data_home_len, mysql_data_home_len= 1;
@@ -2028,13 +2029,19 @@ static struct passwd *check_user(const char *user)
if (!(tmp_user_info= getpwuid(atoi(user))))
goto err;
}
+
return tmp_user_info;
/* purecov: end */
err:
sql_print_error("Fatal error: Can't change to run as user '%s' ; Please check that the user exists!\n",user);
unireg_abort(1);
+#endif
+ return NULL;
+}
+static inline void allow_coredumps()
+{
#ifdef PR_SET_DUMPABLE
if (test_flags & TEST_CORE_ON_SIGNAL)
{
@@ -2042,11 +2049,9 @@ err:
(void) prctl(PR_SET_DUMPABLE, 1);
}
#endif
-
-#endif
- return NULL;
}
+
static void set_user(const char *user, struct passwd *user_info_arg)
{
/* purecov: begin tested */
@@ -2073,6 +2078,7 @@ static void set_user(const char *user, struct passwd *user_info_arg)
sql_perror("setuid");
unireg_abort(1);
}
+ allow_coredumps();
#endif
/* purecov: end */
}
@@ -2092,6 +2098,7 @@ static void set_effective_user(struct passwd *user_info_arg)
sql_perror("setreuid");
unireg_abort(1);
}
+ allow_coredumps();
#endif
}
@@ -4168,14 +4175,15 @@ static int init_server_components()
unireg_abort(1);
/* need to configure logging before initializing storage engines */
- if (opt_log_slave_updates && !opt_bin_log)
+ if (!opt_bin_log_used)
{
- sql_print_warning("You need to use --log-bin to make "
- "--log-slave-updates work.");
+ if (opt_log_slave_updates)
+ sql_print_warning("You need to use --log-bin to make "
+ "--log-slave-updates work.");
+ if (binlog_format_used)
+ sql_print_warning("You need to use --log-bin to make "
+ "--binlog-format work.");
}
- if (!opt_bin_log && binlog_format_used)
- sql_print_warning("You need to use --log-bin to make "
- "--binlog-format work.");
/* Check that we have not let the format to unspecified at this point */
DBUG_ASSERT((uint)global_system_variables.binlog_format <=
@@ -6222,7 +6230,7 @@ struct my_option my_long_options[]=
{"language", 'L',
"Client error messages in given language. May be given as a full path. "
"Deprecated. Use --lc-messages-dir instead.",
- &lc_messages_dir_ptr, &lc_messages_dir_ptr, 0,
+ 0, 0, 0,
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"lc-messages", 0,
"Set the language used for the error messages.",
@@ -6943,6 +6951,16 @@ SHOW_VAR status_vars[]= {
{"Delayed_insert_threads", (char*) &delayed_insert_threads, SHOW_LONG_NOFLUSH},
{"Delayed_writes", (char*) &delayed_insert_writes, SHOW_LONG},
{"Empty_queries", (char*) offsetof(STATUS_VAR, empty_queries), SHOW_LONG_STATUS},
+ {"Executed_events", (char*) &executed_events, SHOW_LONG_NOFLUSH },
+ {"Executed_triggers", (char*) offsetof(STATUS_VAR, executed_triggers), SHOW_LONG_STATUS},
+ {"Feature_dynamic_columns", (char*) offsetof(STATUS_VAR, feature_dynamic_columns), SHOW_LONG_STATUS},
+ {"Feature_fulltext", (char*) offsetof(STATUS_VAR, feature_fulltext), SHOW_LONG_STATUS},
+ {"Feature_gis", (char*) offsetof(STATUS_VAR, feature_gis), SHOW_LONG_STATUS},
+ {"Feature_locale", (char*) offsetof(STATUS_VAR, feature_locale), SHOW_LONG_STATUS},
+ {"Feature_subquery", (char*) offsetof(STATUS_VAR, feature_subquery), SHOW_LONG_STATUS},
+ {"Feature_timezone", (char*) offsetof(STATUS_VAR, feature_timezone), SHOW_LONG_STATUS},
+ {"Feature_trigger", (char*) offsetof(STATUS_VAR, feature_trigger), SHOW_LONG_STATUS},
+ {"Feature_xml", (char*) offsetof(STATUS_VAR, feature_xml), SHOW_LONG_STATUS},
{"Flush_commands", (char*) &refresh_version, SHOW_LONG_NOFLUSH},
{"Handler_commit", (char*) offsetof(STATUS_VAR, ha_commit_count), SHOW_LONG_STATUS},
{"Handler_delete", (char*) offsetof(STATUS_VAR, ha_delete_count), SHOW_LONG_STATUS},
@@ -6982,6 +7000,7 @@ SHOW_VAR status_vars[]= {
{"Opened_files", (char*) &my_file_total_opened, SHOW_LONG_NOFLUSH},
{"Opened_tables", (char*) offsetof(STATUS_VAR, opened_tables), SHOW_LONG_STATUS},
{"Opened_table_definitions", (char*) offsetof(STATUS_VAR, opened_shares), SHOW_LONG_STATUS},
+ {"Opened_views", (char*) offsetof(STATUS_VAR, opened_views), SHOW_LONG_STATUS},
{"Prepared_stmt_count", (char*) &show_prepared_stmt_count, SHOW_FUNC},
{"Rows_sent", (char*) offsetof(STATUS_VAR, rows_sent), SHOW_LONGLONG_STATUS},
{"Rows_read", (char*) offsetof(STATUS_VAR, rows_read), SHOW_LONGLONG_STATUS},
@@ -7214,7 +7233,7 @@ static int mysql_init_variables(void)
myisam_test_invalid_symlink= test_if_data_home_dir;
#endif
opt_log= opt_slow_log= 0;
- opt_bin_log= 0;
+ opt_bin_log= opt_bin_log_used= 0;
opt_disable_networking= opt_skip_show_db=0;
opt_skip_name_resolve= 0;
opt_ignore_builtin_innodb= 0;
@@ -7266,10 +7285,10 @@ static int mysql_init_variables(void)
mysql_home_ptr= mysql_home;
pidfile_name_ptr= pidfile_name;
log_error_file_ptr= log_error_file;
- lc_messages_dir_ptr= lc_messages_dir;
protocol_version= PROTOCOL_VERSION;
what_to_log= ~ (1L << (uint) COM_TIME);
refresh_version= 1L; /* Increments on each reload */
+ executed_events= 0;
global_query_id= thread_id= 1L;
my_atomic_rwlock_init(&global_query_id_lock);
my_atomic_rwlock_init(&thread_running_lock);
@@ -7455,7 +7474,6 @@ mysqld_get_one_option(int optid,
break;
case 'L':
strmake(lc_messages_dir, argument, sizeof(lc_messages_dir)-1);
- lc_messages_dir_ptr= lc_messages_dir;
break;
case OPT_BINLOG_FORMAT:
binlog_format_used= true;
@@ -7484,6 +7502,7 @@ mysqld_get_one_option(int optid,
break;
case (int) OPT_BIN_LOG:
opt_bin_log= test(argument != disabled_my_option);
+ opt_bin_log_used= 1;
break;
case (int) OPT_LOG_BASENAME:
{
diff --git a/sql/mysqld.h b/sql/mysqld.h
index 62d2426d692..7a24b56dcb7 100644
--- a/sql/mysqld.h
+++ b/sql/mysqld.h
@@ -175,6 +175,7 @@ extern ulong opt_binlog_rows_event_max_size;
extern ulong rpl_recovery_rank, thread_cache_size;
extern ulong stored_program_cache_size;
extern ulong back_log;
+extern ulong executed_events;
extern char language[FN_REFLEN];
extern "C" MYSQL_PLUGIN_IMPORT ulong server_id;
extern ulong concurrency;
diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc
index cbec039b3e4..fa3a07b72c5 100644
--- a/sql/opt_sum.cc
+++ b/sql/opt_sum.cc
@@ -791,7 +791,7 @@ static bool matching_cond(bool max_fl, TABLE_REF *ref, KEY *keyinfo,
{
/* 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);
+ value->save_in_field_no_warnings(part->field, 1);
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/sql_base.cc b/sql/sql_base.cc
index 52569f193aa..85e9227c154 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -3893,34 +3893,22 @@ static bool open_table_entry_fini(THD *thd, TABLE_SHARE *share, TABLE *entry)
{
char query_buf[2*FN_REFLEN + 21];
String query(query_buf, sizeof(query_buf), system_charset_info);
+
query.length(0);
- if (query.ptr())
- {
- /* this DELETE FROM is needed even with row-based binlogging */
- query.append("DELETE FROM ");
- append_identifier(thd, &query, share->db.str, share->db.length);
- query.append(".");
- append_identifier(thd, &query, share->table_name.str,
+ query.append("DELETE FROM ");
+ append_identifier(thd, &query, share->db.str, share->db.length);
+ query.append(".");
+ append_identifier(thd, &query, share->table_name.str,
share->table_name.length);
- int errcode= query_error_code(thd, TRUE);
- if (thd->binlog_query(THD::STMT_QUERY_TYPE,
- query.ptr(), query.length(),
- FALSE, FALSE, FALSE, errcode))
- return TRUE;
- }
- else
- {
- /*
- As replication is maybe going to be corrupted, we need to warn the
- DBA on top of warning the client (which will automatically be done
- because of MYF(MY_WME) in my_malloc() above).
- */
- sql_print_error("When opening HEAP table, could not allocate memory "
- "to write 'DELETE FROM %`s.%`s' to the binary log",
- share->db.str, share->table_name.str);
- delete entry->triggers;
+
+ /*
+ we bypass thd->binlog_query() here,
+ as it does a lot of extra work, that is simply wrong in this case
+ */
+ Query_log_event qinfo(thd, query.ptr(), query.length(),
+ FALSE, TRUE, TRUE, 0);
+ if (mysql_bin_log.write(&qinfo))
return TRUE;
- }
}
}
return FALSE;
@@ -9433,6 +9421,7 @@ open_new_frm(THD *thd, TABLE_SHARE *share, const char *alias,
if (mysql_make_view(thd, parser, table_desc,
(prgflag & OPEN_VIEW_NO_PARSE)))
goto err;
+ status_var_increment(thd->status_var.opened_views);
}
else
{
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 4943a39f491..3aa0c5ae9c7 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -617,25 +617,17 @@ typedef struct system_status_var
ulong ha_savepoint_count;
ulong ha_savepoint_rollback_count;
-#if 0
- /* KEY_CACHE parts. These are copies of the original */
- ulong key_blocks_changed;
- ulong key_blocks_used;
- ulong key_cache_r_requests;
- ulong key_cache_read;
- ulong key_cache_w_requests;
- ulong key_cache_write;
- /* END OF KEY_CACHE parts */
-#endif
-
ulong net_big_packet_count;
ulong opened_tables;
ulong opened_shares;
+ ulong opened_views; /* +1 opening a view */
+
ulong select_full_join_count;
ulong select_full_range_join_count;
ulong select_range_count;
ulong select_range_check_count;
ulong select_scan_count;
+ ulong executed_triggers;
ulong long_query_count;
ulong filesort_merge_passes;
ulong filesort_range_count;
@@ -650,6 +642,16 @@ typedef struct system_status_var
ulong com_stmt_reset;
ulong com_stmt_close;
+ /* Features used */
+ ulong feature_dynamic_columns; /* +1 when creating a dynamic column */
+ ulong feature_fulltext; /* +1 when MATCH is used */
+ ulong feature_gis; /* +1 opening a table with GIS features */
+ ulong feature_locale; /* +1 when LOCALE is set */
+ ulong feature_subquery; /* +1 when subqueries are used */
+ ulong feature_timezone; /* +1 when XPATH is used */
+ ulong feature_trigger; /* +1 opening a table with triggers */
+ ulong feature_xml; /* +1 when XPATH is used */
+
ulong empty_queries;
ulong access_denied_errors;
ulong lost_connections;
@@ -1680,7 +1682,7 @@ public:
my_hrtime_t user_time;
// track down slow pthread_create
ulonglong prior_thr_create_utime, thr_create_utime;
- ulonglong start_utime, utime_after_lock;
+ ulonglong start_utime, utime_after_lock, utime_after_query;
// Process indicator
struct {
@@ -2483,8 +2485,8 @@ public:
*/
void update_server_status()
{
- ulonglong end_utime_of_query= current_utime();
- if (end_utime_of_query > utime_after_lock + variables.long_query_time)
+ utime_after_query= current_utime();
+ if (utime_after_query > utime_after_lock + variables.long_query_time)
server_status|= SERVER_QUERY_WAS_SLOW;
}
inline ulonglong found_rows(void)
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index e0d0d4c4223..3c3b9f85727 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -329,7 +329,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list,
/*
- Check update fields for the timestamp field.
+ Check update fields for the timestamp and auto_increment fields.
SYNOPSIS
check_update_fields()
@@ -342,6 +342,9 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list,
If the update fields include the timestamp field,
remove TIMESTAMP_AUTO_SET_ON_UPDATE from table->timestamp_field_type.
+ If the update fields include an autoinc field, set the
+ table->next_number_field_updated flag.
+
RETURN
0 OK
-1 Error
@@ -353,7 +356,9 @@ static int check_update_fields(THD *thd, TABLE_LIST *insert_table_list,
{
TABLE *table= insert_table_list->table;
my_bool timestamp_mark;
+ my_bool autoinc_mark;
LINT_INIT(timestamp_mark);
+ LINT_INIT(autoinc_mark);
if (table->timestamp_field)
{
@@ -365,6 +370,19 @@ static int check_update_fields(THD *thd, TABLE_LIST *insert_table_list,
table->timestamp_field->field_index);
}
+ table->next_number_field_updated= FALSE;
+
+ if (table->found_next_number_field)
+ {
+ /*
+ Unmark the auto_increment field so that we can check if this is modified
+ by update_fields
+ */
+ autoinc_mark= bitmap_test_and_clear(table->write_set,
+ table->found_next_number_field->
+ field_index);
+ }
+
/* Check the fields we are going to modify */
if (setup_fields(thd, 0, update_fields, MARK_COLUMNS_WRITE, 0, 0))
return -1;
@@ -386,6 +404,18 @@ static int check_update_fields(THD *thd, TABLE_LIST *insert_table_list,
bitmap_set_bit(table->write_set,
table->timestamp_field->field_index);
}
+
+ if (table->found_next_number_field)
+ {
+ if (bitmap_is_set(table->write_set,
+ table->found_next_number_field->field_index))
+ table->next_number_field_updated= TRUE;
+
+ if (autoinc_mark)
+ bitmap_set_bit(table->write_set,
+ table->found_next_number_field->field_index);
+ }
+
return 0;
}
@@ -1563,6 +1593,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
MY_BITMAP *save_read_set, *save_write_set;
ulonglong prev_insert_id= table->file->next_insert_id;
ulonglong insert_id_for_cur_row= 0;
+ ulonglong prev_insert_id_for_cur_row= 0;
DBUG_ENTER("write_record");
info->records++;
@@ -1598,7 +1629,10 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
report error as usual. We will not do any duplicate key processing.
*/
if (info->ignore)
+ {
+ table->file->print_error(error, MYF(ME_JUST_WARNING));
goto ok_or_after_trg_err; /* Ignoring a not fatal error, return 0 */
+ }
goto err;
}
if ((int) (key_nr = table->file->get_dup_key(error)) < 0)
@@ -1688,6 +1722,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
if (info->ignore &&
!table->file->is_fatal_error(error, HA_CHECK_DUP_KEY))
{
+ table->file->print_error(error, MYF(ME_JUST_WARNING));
goto ok_or_after_trg_err;
}
goto err;
@@ -1705,6 +1740,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
INSERT query, which is handled separately by
THD::arg_of_last_insert_id_function.
*/
+ prev_insert_id_for_cur_row= table->file->insert_id_for_cur_row;
insert_id_for_cur_row= table->file->insert_id_for_cur_row= 0;
trg_error= (table->triggers &&
table->triggers->process_triggers(thd, TRG_EVENT_UPDATE,
@@ -1712,9 +1748,22 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
info->copied++;
}
- if (table->next_number_field)
- table->file->adjust_next_insert_id_after_explicit_value(
- table->next_number_field->val_int());
+ /*
+ Only update next_insert_id if the AUTO_INCREMENT value was explicitly
+ updated, so we don't update next_insert_id with the value from the
+ row being updated. Otherwise reset next_insert_id to what it was
+ before the duplicate key error, since that value is unused.
+ */
+ if (table->next_number_field_updated)
+ {
+ DBUG_ASSERT(table->next_number_field != NULL);
+
+ table->file->adjust_next_insert_id_after_explicit_value(table->next_number_field->val_int());
+ }
+ else
+ {
+ table->file->restore_auto_increment(prev_insert_id_for_cur_row);
+ }
goto ok_or_after_trg_err;
}
else /* DUP_REPLACE */
@@ -1803,6 +1852,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
if (!info->ignore ||
table->file->is_fatal_error(error, HA_CHECK_DUP))
goto err;
+ table->file->print_error(error, MYF(ME_JUST_WARNING));
table->file->restore_auto_increment(prev_insert_id);
goto ok_or_after_trg_err;
}
diff --git a/sql/sql_join_cache.cc b/sql/sql_join_cache.cc
index f953cf4df57..91a98d8c6f1 100644
--- a/sql/sql_join_cache.cc
+++ b/sql/sql_join_cache.cc
@@ -3876,8 +3876,9 @@ int JOIN_TAB_SCAN_MRR::next()
If a record in in an incremental cache contains no fields then the
association for the last record in cache will be equal to cache->end_pos
*/
- DBUG_ASSERT(cache->buff <= (uchar *) (*ptr) &&
- (uchar *) (*ptr) <= cache->end_pos);
+ DBUG_ASSERT((!(mrr_mode & HA_MRR_NO_ASSOCIATION))?
+ (cache->buff <= (uchar *) (*ptr) &&
+ (uchar *) (*ptr) <= cache->end_pos): TRUE);
if (join_tab->table->vfield)
update_virtual_fields(join->thd, join_tab->table);
}
@@ -4543,7 +4544,7 @@ bool JOIN_CACHE_BKAH::prepare_look_for_matches(bool skip_last)
{
last_matching_rec_ref_ptr= next_matching_rec_ref_ptr= 0;
if (no_association &&
- (curr_matching_chain= get_matching_chain_by_join_key()))
+ !(curr_matching_chain= get_matching_chain_by_join_key()))
return 1;
last_matching_rec_ref_ptr= get_next_rec_ref(curr_matching_chain);
return 0;
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 91bdad3da62..175c2c1d672 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -1438,6 +1438,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
(thd->open_tables == NULL ||
(thd->locked_tables_mode == LTM_LOCK_TABLES)));
+ thd_proc_info(thd, "updating status");
/* Finalize server status flags after executing a command. */
thd->update_server_status();
thd->protocol->end_statement();
@@ -1495,38 +1496,30 @@ void log_slow_statement(THD *thd)
DBUG_VOID_RETURN; // Don't set time for sub stmt
/* Follow the slow log filter configuration. */
- if (!(thd->variables.log_slow_filter & thd->query_plan_flags))
+ if (!thd->enable_slow_log ||
+ !(thd->variables.log_slow_filter & thd->query_plan_flags))
DBUG_VOID_RETURN;
- /*
- If rate limiting of slow log writes is enabled, decide whether to log
- this query to the log or not.
- */
- if (thd->variables.log_slow_rate_limit > 1 &&
- (global_query_id % thd->variables.log_slow_rate_limit) != 0)
- DBUG_VOID_RETURN;
+ if (((thd->server_status & SERVER_QUERY_WAS_SLOW) ||
+ ((thd->server_status &
+ (SERVER_QUERY_NO_INDEX_USED | SERVER_QUERY_NO_GOOD_INDEX_USED)) &&
+ opt_log_queries_not_using_indexes &&
+ !(sql_command_flags[thd->lex->sql_command] & CF_STATUS_COMMAND))) &&
+ thd->examined_row_count >= thd->variables.min_examined_row_limit)
+ {
+ thd->status_var.long_query_count++;
+ /*
+ If rate limiting of slow log writes is enabled, decide whether to log
+ this query to the log or not.
+ */
+ if (thd->variables.log_slow_rate_limit > 1 &&
+ (global_query_id % thd->variables.log_slow_rate_limit) != 0)
+ DBUG_VOID_RETURN;
- /*
- Do not log administrative statements unless the appropriate option is
- set.
- */
- if (thd->enable_slow_log)
- {
- ulonglong end_utime_of_query= thd->current_utime();
thd_proc_info(thd, "logging slow query");
-
- if (((thd->server_status & SERVER_QUERY_WAS_SLOW) ||
- ((thd->server_status &
- (SERVER_QUERY_NO_INDEX_USED | SERVER_QUERY_NO_GOOD_INDEX_USED)) &&
- opt_log_queries_not_using_indexes &&
- !(sql_command_flags[thd->lex->sql_command] & CF_STATUS_COMMAND))) &&
- thd->examined_row_count >= thd->variables.min_examined_row_limit)
- {
- thd_proc_info(thd, "logging slow query");
- thd->status_var.long_query_count++;
- slow_log_print(thd, thd->query(), thd->query_length(),
- end_utime_of_query);
- }
+ slow_log_print(thd, thd->query(), thd->query_length(),
+ thd->utime_after_query);
+ thd_proc_info(thd, 0);
}
DBUG_VOID_RETURN;
}
@@ -2974,6 +2967,7 @@ end_with_restore_list:
DBUG_ASSERT(!debug_sync_set_action(thd,
STRING_WITH_LEN(act2)));
};);
+ DEBUG_SYNC(thd, "after_mysql_insert");
break;
}
case SQLCOM_REPLACE_SELECT:
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 264ff6552db..f0c786dea86 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -8072,37 +8072,6 @@ get_store_key(THD *thd, KEYUSE *keyuse, table_map used_tables,
}
/**
- This function is only called for const items on fields which are keys.
-
- @return
- returns 1 if there was some conversion made when the field was stored.
-*/
-
-bool
-store_val_in_field(Field *field, Item *item, enum_check_fields check_flag)
-{
- bool error;
- TABLE *table= field->table;
- THD *thd= table->in_use;
- ha_rows cuted_fields=thd->cuted_fields;
- my_bitmap_map *old_map= dbug_tmp_use_all_columns(table,
- table->write_set);
-
- /*
- we should restore old value of count_cuted_fields because
- store_val_in_field can be called from mysql_insert
- with select_insert, which make count_cuted_fields= 1
- */
- enum_check_fields old_count_cuted_fields= thd->count_cuted_fields;
- thd->count_cuted_fields= check_flag;
- error= item->save_in_field(field, 1);
- thd->count_cuted_fields= old_count_cuted_fields;
- dbug_tmp_restore_column_map(table->write_set, old_map);
- return error || cuted_fields != thd->cuted_fields;
-}
-
-
-/**
@details Initialize a JOIN as a query execution plan
that accesses a single table via a table scan.
@@ -17760,7 +17729,7 @@ bool test_if_ref(Item *root_cond, Item_field *left_item,Item *right_item)
field->real_type() != MYSQL_TYPE_VARCHAR &&
(field->type() != MYSQL_TYPE_FLOAT || field->decimals() == 0))
{
- return !store_val_in_field(field, right_item, CHECK_FIELD_WARN);
+ return !right_item->save_in_field_no_warnings(field, 1);
}
}
}
diff --git a/sql/sql_select.h b/sql/sql_select.h
index be5f523a7e2..118a684ab62 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -1430,7 +1430,6 @@ typedef struct st_select_check {
extern const char *join_type_str[];
/* Extern functions in sql_select.cc */
-bool store_val_in_field(Field *field, Item *val, enum_check_fields check_flag);
void count_field_types(SELECT_LEX *select_lex, TMP_TABLE_PARAM *param,
List<Item> &fields, bool reset_with_sum_func);
bool setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param,
@@ -1504,6 +1503,7 @@ public:
enum_check_fields saved_count_cuted_fields= thd->count_cuted_fields;
ulonglong sql_mode= thd->variables.sql_mode;
thd->variables.sql_mode&= ~(MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE);
+ thd->variables.sql_mode|= MODE_INVALID_DATES;
thd->count_cuted_fields= CHECK_FIELD_IGNORE;
diff --git a/sql/sql_state.c b/sql/sql_state.c
index 511dc65917b..5acf97f16cc 100644
--- a/sql/sql_state.c
+++ b/sql/sql_state.c
@@ -17,6 +17,7 @@
#include <my_global.h>
#include <mysqld_error.h>
+#include <my_base.h>
struct st_map_errno_to_sqlstate
{
@@ -27,6 +28,7 @@ struct st_map_errno_to_sqlstate
struct st_map_errno_to_sqlstate sqlstate_map[]=
{
+#include <handler_state.h>
#include <sql_state.h>
};
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 06ec9a733c6..5a6090e5d9a 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -1828,6 +1828,7 @@ int write_bin_log(THD *thd, bool clear_error,
if (mysql_bin_log.is_open())
{
int errcode= 0;
+ thd_proc_info(thd, "Writing to binlog");
if (clear_error)
thd->clear_error();
else
@@ -1835,6 +1836,7 @@ int write_bin_log(THD *thd, bool clear_error,
error= thd->binlog_query(THD::STMT_QUERY_TYPE,
query, query_length, is_trans, FALSE, FALSE,
errcode);
+ thd_proc_info(thd, 0);
}
return error;
}
@@ -7476,7 +7478,7 @@ copy_data_between_tables(THD *thd, TABLE *from,TABLE *to,
(to->key_info[0].key_part[0].field->flags &
AUTO_INCREMENT_FLAG))
err_msg= ER(ER_DUP_ENTRY_AUTOINCREMENT_CASE);
- to->file->print_keydup_error(key_nr, err_msg);
+ to->file->print_keydup_error(key_nr, err_msg, MYF(0));
break;
}
}
diff --git a/sql/sql_time.cc b/sql/sql_time.cc
index 5972c8918ba..5c0471fdfaa 100644
--- a/sql/sql_time.cc
+++ b/sql/sql_time.cc
@@ -25,9 +25,9 @@
#include <m_ctype.h>
- /* Some functions to calculate dates */
+#define MAX_DAY_NUMBER 3652424L
-#ifndef TESTTIME
+ /* Some functions to calculate dates */
/*
Name description of interval names used in statements.
@@ -147,46 +147,42 @@ uint calc_week(MYSQL_TIME *l_time, uint week_behaviour, uint *year)
/* Change a daynr to year, month and day */
/* Daynr 0 is returned as date 00.00.00 */
-void get_date_from_daynr(long daynr,uint *ret_year,uint *ret_month,
+bool get_date_from_daynr(long daynr,uint *ret_year,uint *ret_month,
uint *ret_day)
{
uint year,temp,leap_day,day_of_year,days_in_year;
uchar *month_pos;
DBUG_ENTER("get_date_from_daynr");
- if (daynr <= 365L || daynr >= 3652500)
- { /* Fix if wrong daynr */
- *ret_year= *ret_month = *ret_day =0;
+ if (daynr < 365 || daynr > MAX_DAY_NUMBER)
+ DBUG_RETURN(1);
+
+ year= (uint) (daynr*100 / 36525L);
+ temp=(((year-1)/100+1)*3)/4;
+ day_of_year=(uint) (daynr - (long) year * 365L) - (year-1)/4 +temp;
+ while (day_of_year > (days_in_year= calc_days_in_year(year)))
+ {
+ day_of_year-=days_in_year;
+ (year)++;
}
- else
+ leap_day=0;
+ if (days_in_year == 366)
{
- year= (uint) (daynr*100 / 36525L);
- temp=(((year-1)/100+1)*3)/4;
- day_of_year=(uint) (daynr - (long) year * 365L) - (year-1)/4 +temp;
- while (day_of_year > (days_in_year= calc_days_in_year(year)))
+ if (day_of_year > 31+28)
{
- day_of_year-=days_in_year;
- (year)++;
+ day_of_year--;
+ if (day_of_year == 31+28)
+ leap_day=1; /* Handle leapyears leapday */
}
- leap_day=0;
- if (days_in_year == 366)
- {
- if (day_of_year > 31+28)
- {
- day_of_year--;
- if (day_of_year == 31+28)
- leap_day=1; /* Handle leapyears leapday */
- }
- }
- *ret_month=1;
- for (month_pos= days_in_month ;
- day_of_year > (uint) *month_pos ;
- day_of_year-= *(month_pos++), (*ret_month)++)
- ;
- *ret_year=year;
- *ret_day=day_of_year+leap_day;
}
- DBUG_VOID_RETURN;
+ *ret_month=1;
+ for (month_pos= days_in_month ;
+ day_of_year > (uint) *month_pos ;
+ day_of_year-= *(month_pos++), (*ret_month)++)
+ ;
+ *ret_year=year;
+ *ret_day=day_of_year+leap_day;
+ DBUG_RETURN(0);
}
/* Functions to handle periods */
@@ -842,7 +838,6 @@ void make_truncated_value_warning(THD *thd,
/* Daynumber from year 0 to 9999-12-31 */
-#define MAX_DAY_NUMBER 3652424L
#define COMBINE(X) \
(((((X)->day * 24LL + (X)->hour) * 60LL + \
(X)->minute) * 60LL + (X)->second)*1000000LL + \
@@ -909,19 +904,18 @@ bool date_add_interval(MYSQL_TIME *ltime, interval_type int_type,
daynr= usec;
/* Day number from year 0 to 9999-12-31 */
- if ((ulonglong) daynr > MAX_DAY_NUMBER)
+ if (get_date_from_daynr((long) daynr, &ltime->year, &ltime->month,
+ &ltime->day))
goto invalid_date;
- get_date_from_daynr((long) daynr, &ltime->year, &ltime->month,
- &ltime->day);
break;
}
case INTERVAL_WEEK:
period= (calc_daynr(ltime->year,ltime->month,ltime->day) +
sign * (long) interval.day);
/* Daynumber from year 0 to 9999-12-31 */
- if ((ulong) period > MAX_DAY_NUMBER)
+ if (get_date_from_daynr((long) period,&ltime->year,&ltime->month,
+ &ltime->day))
goto invalid_date;
- get_date_from_daynr((long) period,&ltime->year,&ltime->month,&ltime->day);
break;
case INTERVAL_YEAR:
ltime->year+= sign * (long) interval.year;
@@ -1071,4 +1065,3 @@ int my_time_compare(MYSQL_TIME *a, MYSQL_TIME *b)
return 0;
}
-#endif
diff --git a/sql/sql_time.h b/sql/sql_time.h
index 026a15cb796..c1a75bb2ad3 100644
--- a/sql/sql_time.h
+++ b/sql/sql_time.h
@@ -33,7 +33,7 @@ typedef struct st_known_date_time_format KNOWN_DATE_TIME_FORMAT;
ulong convert_period_to_month(ulong period);
ulong convert_month_to_period(ulong month);
-void get_date_from_daynr(long daynr,uint *year, uint *month, uint *day);
+bool get_date_from_daynr(long daynr,uint *year, uint *month, uint *day);
my_time_t TIME_to_timestamp(THD *thd, const MYSQL_TIME *t, uint *error_code);
bool str_to_time_with_warn(CHARSET_INFO *cs, const char *str, uint length,
MYSQL_TIME *l_time, ulonglong fuzzydate);
diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc
index 1b942ecc93b..aff00f9fcf4 100644
--- a/sql/sql_trigger.cc
+++ b/sql/sql_trigger.cc
@@ -1334,6 +1334,7 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
triggers->definitions_list.elements);
table->triggers= triggers;
+ status_var_increment(thd->status_var.feature_trigger);
/*
TODO: This could be avoided if there is no triggers
@@ -2116,6 +2117,8 @@ bool Table_triggers_list::process_triggers(THD *thd,
if (sp_trigger == NULL)
return FALSE;
+ status_var_increment(thd->status_var.executed_triggers);
+
if (old_row_is_record1)
{
old_field= record1_field;
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index bf261bffec3..fb0951410a4 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -406,7 +406,7 @@ int mysql_update(THD *thd,
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
select= make_select(table, 0, 0, conds, 0, &error);
- if (error || !limit ||
+ if (error || !limit || thd->is_error() ||
(select && select->check_quick(thd, safe_update, limit)))
{
delete select;
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 8ef59fafb98..555efaf366d 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -1064,6 +1064,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token KILL_SYM
%token LANGUAGE_SYM /* SQL-2003-R */
%token LAST_SYM /* SQL-2003-N */
+%token LAST_VALUE
%token LE /* OPERATOR */
%token LEADING /* SQL-2003-R */
%token LEAVES
@@ -5872,9 +5873,9 @@ attribute:
NULL_SYM { Lex->type&= ~ NOT_NULL_FLAG; }
| not NULL_SYM { Lex->type|= NOT_NULL_FLAG; }
| DEFAULT now_or_signed_literal { Lex->default_value=$2; }
- | ON UPDATE_SYM NOW_SYM opt_time_precision
+ | ON UPDATE_SYM NOW_SYM optional_braces
{
- Item *item= new (YYTHD->mem_root) Item_func_now_local($4);
+ Item *item= new (YYTHD->mem_root) Item_func_now_local(6);
if (item == NULL)
MYSQL_YYABORT;
Lex->on_update_value= item;
@@ -5966,9 +5967,9 @@ type_with_opt_collate:
now_or_signed_literal:
- NOW_SYM opt_time_precision
+ NOW_SYM optional_braces
{
- $$= new (YYTHD->mem_root) Item_func_now_local($2);
+ $$= new (YYTHD->mem_root) Item_func_now_local(6);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -8890,6 +8891,12 @@ function_call_conflict:
if ($$ == NULL)
MYSQL_YYABORT;
}
+ | LAST_VALUE '(' expr_list ')'
+ {
+ $$= new (YYTHD->mem_root) Item_func_last_value(* $3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
| MICROSECOND_SYM '(' expr ')'
{
$$= new (YYTHD->mem_root) Item_func_microsecond($3);
@@ -13088,6 +13095,7 @@ keyword_sp:
| ISSUER_SYM {}
| INSERT_METHOD {}
| KEY_BLOCK_SIZE {}
+ | LAST_VALUE {}
| LAST_SYM {}
| LEAVES {}
| LESS_SYM {}
diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc
index fe48f953c28..4a003a89a7e 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -3578,22 +3578,25 @@ static bool check_locale(sys_var *self, THD *thd, set_var *var)
if (!locale->errmsgs->errmsgs)
{
+ bool res;
mysql_mutex_lock(&LOCK_error_messages);
- if (!locale->errmsgs->errmsgs &&
- read_texts(ERRMSG_FILE, locale->errmsgs->language,
- &locale->errmsgs->errmsgs,
- ER_ERROR_LAST - ER_ERROR_FIRST + 1))
+ res= (!locale->errmsgs->errmsgs &&
+ read_texts(ERRMSG_FILE, locale->errmsgs->language,
+ &locale->errmsgs->errmsgs,
+ ER_ERROR_LAST - ER_ERROR_FIRST + 1));
+ mysql_mutex_unlock(&LOCK_error_messages);
+ if (res)
{
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
"Can't process error message file for locale '%s'",
locale->name);
- mysql_mutex_unlock(&LOCK_error_messages);
return true;
}
- mysql_mutex_unlock(&LOCK_error_messages);
}
+ status_var_increment(thd->status_var.feature_locale);
return false;
}
+
static Sys_var_struct Sys_lc_messages(
"lc_messages", "Set the language used for the error messages",
SESSION_VAR(lc_messages), NO_CMD_LINE,
diff --git a/sql/table.cc b/sql/table.cc
index d733c5ada62..47b2cae1a04 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -4949,6 +4949,28 @@ void TABLE_LIST::set_check_materialized()
}
}
+TABLE *TABLE_LIST::get_real_join_table()
+{
+ TABLE_LIST *tbl= this;
+ while (tbl->table == NULL || tbl->table->reginfo.join_tab == NULL)
+ {
+ if (tbl->view == NULL && tbl->derived == NULL)
+ break;
+ /* we do not support merging of union yet */
+ DBUG_ASSERT(tbl->view == NULL ||
+ tbl->view->select_lex.next_select() == NULL);
+ DBUG_ASSERT(tbl->derived == NULL ||
+ tbl->derived->first_select()->next_select() == NULL);
+
+ if (tbl->table)
+ table= tbl->table;
+ tbl= (tbl->view != NULL ?
+ tbl->view->select_lex.get_table_list() :
+ tbl->derived->first_select()->get_table_list());
+ }
+ return tbl->table;
+}
+
Natural_join_column::Natural_join_column(Field_translator *field_param,
TABLE_LIST *tab)
diff --git a/sql/table.h b/sql/table.h
index fc451ff5050..9e26f907920 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -1088,15 +1088,20 @@ public:
uint db_stat; /* mode of file as in handler.h */
/* number of select if it is derived table */
uint derived_select_number;
- int current_lock; /* Type of lock on table */
- bool copy_blobs; /* copy_blobs when storing */
-
/*
0 or JOIN_TYPE_{LEFT|RIGHT}. Currently this is only compared to 0.
If maybe_null !=0, this table is inner w.r.t. some outer join operation,
and null_row may be true.
*/
uint maybe_null;
+ int current_lock; /* Type of lock on table */
+ bool copy_blobs; /* copy_blobs when storing */
+ /*
+ Set if next_number_field is in the UPDATE fields of INSERT ... ON DUPLICATE
+ KEY UPDATE.
+ */
+ bool next_number_field_updated;
+
/*
If true, the current table row is considered to have all columns set to
NULL, including columns declared as "not null" (see maybe_null).
@@ -1964,6 +1969,7 @@ struct TABLE_LIST
TABLE_LIST *find_underlying_table(TABLE *table);
TABLE_LIST *first_leaf_for_name_resolution();
TABLE_LIST *last_leaf_for_name_resolution();
+ TABLE *get_real_join_table();
bool is_leaf_for_name_resolution();
inline TABLE_LIST *top_table()
{ return belong_to_view ? belong_to_view : this; }
diff --git a/sql/tztime.cc b/sql/tztime.cc
index 9fae9f3fedd..ba24cab9ca7 100644
--- a/sql/tztime.cc
+++ b/sql/tztime.cc
@@ -2329,7 +2329,6 @@ my_tz_find(THD *thd, const String *name)
if (!str_to_offset(name->ptr(), name->length(), &offset))
{
-
if (!(result_tz= (Time_zone_offset *)my_hash_search(&offset_tzs,
(const uchar *)&offset,
sizeof(long))))
@@ -2371,6 +2370,9 @@ my_tz_find(THD *thd, const String *name)
mysql_mutex_unlock(&tz_LOCK);
+ if (result_tz && result_tz != my_tz_SYSTEM && result_tz != my_tz_UTC)
+ status_var_increment(thd->status_var.feature_timezone);
+
DBUG_RETURN(result_tz);
}