summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorSergei Golubchik <sergii@pisem.net>2015-01-21 12:03:02 +0100
committerSergei Golubchik <sergii@pisem.net>2015-01-21 12:03:02 +0100
commitd9c01e4b4ac6a7e2bdbcaf71819fa3d4f5269840 (patch)
tree4f86f6ce4e298430e313ed70f2225b3f29485f51 /sql
parentd854a254b84595b3a8f3a4d8083a2b997d59912e (diff)
parent8bc712e481a18976853fa57a7be77aab6159d431 (diff)
downloadmariadb-git-d9c01e4b4ac6a7e2bdbcaf71819fa3d4f5269840.tar.gz
5.5 merge
Diffstat (limited to 'sql')
-rw-r--r--sql/handler.cc4
-rw-r--r--sql/handler.h11
-rw-r--r--sql/item.cc18
-rw-r--r--sql/item.h2
-rw-r--r--sql/item_func.cc5
-rw-r--r--sql/item_func.h7
-rw-r--r--sql/item_timefunc.cc7
-rw-r--r--sql/log_event.cc16
-rw-r--r--sql/log_event.h4
-rw-r--r--sql/opt_range.cc30
-rw-r--r--sql/sql_insert.cc2
-rw-r--r--sql/sql_parse.cc117
-rw-r--r--sql/sql_parse.h3
-rw-r--r--sql/sql_plugin.cc2
-rw-r--r--sql/sql_select.cc2
-rw-r--r--sql/sql_table.cc34
-rw-r--r--sql/sql_view.cc6
-rw-r--r--sql/sys_vars.cc27
-rw-r--r--sql/table.cc32
-rw-r--r--sql/table.h1
20 files changed, 257 insertions, 73 deletions
diff --git a/sql/handler.cc b/sql/handler.cc
index 75481e9e9b5..518ca7b860d 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -83,9 +83,7 @@ static const LEX_STRING sys_table_aliases[]=
};
const char *ha_row_type[] = {
- "", "FIXED", "DYNAMIC", "COMPRESSED", "REDUNDANT", "COMPACT",
- "PAGE",
- "?","?","?"
+ "", "FIXED", "DYNAMIC", "COMPRESSED", "REDUNDANT", "COMPACT", "PAGE"
};
const char *tx_isolation_names[] =
diff --git a/sql/handler.h b/sql/handler.h
index 5bba570f8ec..4222270e9c4 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -452,8 +452,10 @@ enum legacy_db_type
enum row_type { ROW_TYPE_NOT_USED=-1, ROW_TYPE_DEFAULT, ROW_TYPE_FIXED,
ROW_TYPE_DYNAMIC, ROW_TYPE_COMPRESSED,
- ROW_TYPE_REDUNDANT, ROW_TYPE_COMPACT,
- ROW_TYPE_PAGE };
+ ROW_TYPE_REDUNDANT, ROW_TYPE_COMPACT, ROW_TYPE_PAGE };
+
+/* not part of the enum, so that it shouldn't be in switch(row_type) */
+#define ROW_TYPE_MAX ((uint)ROW_TYPE_PAGE + 1)
/* Specifies data storage format for individual columns */
enum column_format_type {
@@ -1389,6 +1391,9 @@ static inline sys_var *find_hton_sysvar(handlerton *hton, st_mysql_sys_var *var)
#define HTON_NO_BINLOG_ROW_OPT (1 << 9)
#define HTON_SUPPORTS_EXTENDED_KEYS (1 <<10) //supports extended keys
+// MySQL compatibility. Unused.
+#define HTON_SUPPORTS_FOREIGN_KEYS (1 << 0) //Foreign key constraint supported.
+
class Ha_trx_info;
struct THD_TRANS
@@ -1570,7 +1575,7 @@ class partition_info;
struct st_partition_iter;
-enum ha_choice { HA_CHOICE_UNDEF, HA_CHOICE_NO, HA_CHOICE_YES };
+enum ha_choice { HA_CHOICE_UNDEF, HA_CHOICE_NO, HA_CHOICE_YES, HA_CHOICE_MAX };
enum enum_stats_auto_recalc { HA_STATS_AUTO_RECALC_DEFAULT= 0,
HA_STATS_AUTO_RECALC_ON,
diff --git a/sql/item.cc b/sql/item.cc
index 1dd4fc2909f..132cfa2846a 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -885,20 +885,20 @@ Item_ident::Item_ident(THD *thd, Item_ident *item)
void Item_ident::cleanup()
{
DBUG_ENTER("Item_ident::cleanup");
-#ifdef CANT_BE_USED_AS_MEMORY_IS_FREED
- db_name ? db_name : "(null)",
- orig_db_name ? orig_db_name : "(null)",
- table_name ? table_name : "(null)",
- orig_table_name ? orig_table_name : "(null)",
- field_name ? field_name : "(null)",
- orig_field_name ? orig_field_name : "(null)"));
-#endif
+ bool was_fixed= fixed;
Item::cleanup();
db_name= orig_db_name;
table_name= orig_table_name;
field_name= orig_field_name;
/* Store if this Item was depended */
- can_be_depended= MY_TEST(depended_from);
+ if (was_fixed)
+ {
+ /*
+ We can trust that depended_from set correctly only if this item
+ was fixed
+ */
+ can_be_depended= MY_TEST(depended_from);
+ }
DBUG_VOID_RETURN;
}
diff --git a/sql/item.h b/sql/item.h
index f337db92ef3..13e80639657 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -4458,7 +4458,7 @@ private:
/**
@todo
Implement the is_null() method for this class. Currently calling is_null()
- on any Item_cache object resolves to Item::is_null(), which reutns FALSE
+ on any Item_cache object resolves to Item::is_null(), which returns FALSE
for any value.
*/
diff --git a/sql/item_func.cc b/sql/item_func.cc
index de05ee358a2..92ddd5feada 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -4620,6 +4620,11 @@ longlong Item_func_sleep::val_int()
mysql_cond_destroy(&cond);
+ DBUG_EXECUTE_IF("sleep_inject_query_done_debug_sync", {
+ debug_sync_set_action
+ (thd, STRING_WITH_LEN("dispatch_command_end SIGNAL query_done"));
+ };);
+
return MY_TEST(!error); // Return 1 killed
}
diff --git a/sql/item_func.h b/sql/item_func.h
index e40f2d771c6..ce1f2fdd676 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -1,7 +1,7 @@
#ifndef ITEM_FUNC_INCLUDED
#define ITEM_FUNC_INCLUDED
-/* Copyright (c) 2000, 2013, Oracle and/or its affiliates.
- Copyright (c) 2009, 2014, SkySQL Ab.
+/* Copyright (c) 2000, 2014, Oracle and/or its affiliates.
+ Copyright (c) 2009, 2014, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -287,7 +287,8 @@ public:
inline longlong check_integer_overflow(longlong value, bool val_unsigned)
{
if ((unsigned_flag && !val_unsigned && value < 0) ||
- (!unsigned_flag && val_unsigned && (ulonglong) value > LONGLONG_MAX))
+ (!unsigned_flag && val_unsigned &&
+ (ulonglong) value > (ulonglong) LONGLONG_MAX))
return raise_integer_overflow();
return value;
}
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index 389d9d5380c..fb55b7660cb 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -1564,10 +1564,9 @@ String *Item_temporal_hybrid_func::val_str_ascii(String *str)
bool Item_func_from_days::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date)
{
longlong value=args[0]->val_int();
- if (args[0]->null_value)
- return (null_value= 1);
- if ((fuzzy_date & TIME_NO_ZERO_DATE) && value == 0)
- return (null_value= 1);
+ if ((null_value= (args[0]->null_value ||
+ ((fuzzy_date & TIME_NO_ZERO_DATE) && value == 0))))
+ return true;
bzero(ltime, sizeof(MYSQL_TIME));
if (get_date_from_daynr((long) value, &ltime->year, &ltime->month,
&ltime->day))
diff --git a/sql/log_event.cc b/sql/log_event.cc
index d568b91a1e2..dd272ac52cd 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -1669,7 +1669,7 @@ Log_event* Log_event::read_log_event(const char* buf, uint event_len,
ev = new Execute_load_log_event(buf, event_len, description_event);
break;
case START_EVENT_V3: /* this is sent only by MySQL <=4.x */
- ev = new Start_log_event_v3(buf, description_event);
+ ev = new Start_log_event_v3(buf, event_len, description_event);
break;
case STOP_EVENT:
ev = new Stop_log_event(buf, description_event);
@@ -4662,11 +4662,16 @@ void Start_log_event_v3::print(FILE* file, PRINT_EVENT_INFO* print_event_info)
Start_log_event_v3::Start_log_event_v3()
*/
-Start_log_event_v3::Start_log_event_v3(const char* buf,
+Start_log_event_v3::Start_log_event_v3(const char* buf, uint event_len,
const Format_description_log_event
*description_event)
- :Log_event(buf, description_event)
+ :Log_event(buf, description_event), binlog_version(BINLOG_VERSION)
{
+ if (event_len < LOG_EVENT_MINIMAL_HEADER_LEN + ST_COMMON_HEADER_LEN_OFFSET)
+ {
+ server_version[0]= 0;
+ return;
+ }
buf+= LOG_EVENT_MINIMAL_HEADER_LEN;
binlog_version= uint2korr(buf+ST_BINLOG_VER_OFFSET);
memcpy(server_version, buf+ST_SERVER_VER_OFFSET,
@@ -4971,9 +4976,12 @@ Format_description_log_event(const char* buf,
const
Format_description_log_event*
description_event)
- :Start_log_event_v3(buf, description_event), event_type_permutation(0)
+ :Start_log_event_v3(buf, event_len, description_event),
+ common_header_len(0), post_header_len(NULL), event_type_permutation(0)
{
DBUG_ENTER("Format_description_log_event::Format_description_log_event(char*,...)");
+ if (!Start_log_event_v3::is_valid())
+ DBUG_VOID_RETURN; /* sanity check */
buf+= LOG_EVENT_MINIMAL_HEADER_LEN;
if ((common_header_len=buf[ST_COMMON_HEADER_LEN_OFFSET]) < OLD_HEADER_LEN)
DBUG_VOID_RETURN; /* sanity check */
diff --git a/sql/log_event.h b/sql/log_event.h
index c0370014c7d..6a3e6f174bb 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -2515,7 +2515,7 @@ public:
void print(FILE* file, PRINT_EVENT_INFO* print_event_info);
#endif
- Start_log_event_v3(const char* buf,
+ Start_log_event_v3(const char* buf, uint event_len,
const Format_description_log_event* description_event);
~Start_log_event_v3() {}
Log_event_type get_type_code() { return START_EVENT_V3;}
@@ -2524,7 +2524,7 @@ public:
#ifdef MYSQL_SERVER
bool write(IO_CACHE* file);
#endif
- bool is_valid() const { return 1; }
+ bool is_valid() const { return server_version[0] != 0; }
int get_data_size()
{
return START_V3_HEADER_LEN; //no variable-sized part
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index a5c27fa66e2..3597ade2cba 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -13167,12 +13167,13 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time)
SYNOPSIS
check_group_min_max_predicates()
- cond [in] the expression tree being analyzed
- min_max_arg [in] the field referenced by the MIN/MAX function(s)
- image_type [in]
- has_min_max_arg [out] true if the subtree being analyzed references min_max_arg
- has_other_arg [out] true if the subtree being analyzed references a column
- other min_max_arg
+ cond [in] the expression tree being analyzed
+ min_max_arg [in] the field referenced by the MIN/MAX function(s)
+ image_type [in]
+ has_min_max_arg [out] true if the subtree being analyzed references
+ min_max_arg
+ has_other_arg [out] true if the subtree being analyzed references a
+ column other min_max_arg
DESCRIPTION
The function walks recursively over the cond tree representing a WHERE
@@ -13216,7 +13217,7 @@ check_group_min_max_predicates(Item *cond, Item_field *min_max_arg_item,
(2) the subtree passes the test, but it is an OR and it references both
the min/max argument and other columns.
*/
- if (!check_group_min_max_predicates(and_or_arg, min_max_arg_item, //1
+ if (!check_group_min_max_predicates(and_or_arg, min_max_arg_item, //1
image_type,
&has_min_max, &has_other) ||
(func_type == Item_func::COND_OR_FUNC && has_min_max && has_other))//2
@@ -13232,7 +13233,7 @@ check_group_min_max_predicates(Item *cond, Item_field *min_max_arg_item,
a subquery in the WHERE clause.
*/
- if (cond_type == Item::SUBSELECT_ITEM)
+ if (unlikely(cond_type == Item::SUBSELECT_ITEM))
{
Item_subselect *subs_cond= (Item_subselect*) cond;
if (subs_cond->is_correlated)
@@ -13249,7 +13250,14 @@ check_group_min_max_predicates(Item *cond, Item_field *min_max_arg_item,
}
DBUG_RETURN(TRUE);
}
-
+ /*
+ Subquery with IS [NOT] NULL
+ TODO: Look into the cache_item and optimize it like we do for
+ subselect's above
+ */
+ if (unlikely(cond_type == Item::CACHE_ITEM))
+ DBUG_RETURN(cond->const_item());
+
/*
Condition of the form 'field' is equivalent to 'field <> 0' and thus
satisfies the SA3 condition.
@@ -13266,7 +13274,9 @@ check_group_min_max_predicates(Item *cond, Item_field *min_max_arg_item,
/* We presume that at this point there are no other Items than functions. */
DBUG_ASSERT(cond_type == Item::FUNC_ITEM);
-
+ if (unlikely(cond_type != Item::FUNC_ITEM)) /* Safety */
+ DBUG_RETURN(FALSE);
+
/* Test if cond references only group-by or non-group fields. */
Item_func *pred= (Item_func*) cond;
Item_func::Functype pred_type= pred->functype();
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 0ecc6418cb2..11f2d6b3dbc 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -1758,7 +1758,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
table->file->adjust_next_insert_id_after_explicit_value(table->next_number_field->val_int());
}
- else
+ else if (prev_insert_id_for_cur_row)
{
table->file->restore_auto_increment(prev_insert_id_for_cur_row);
}
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 88dc862df3e..96e7bbc822e 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -5982,6 +5982,115 @@ bool check_global_access(THD *thd, ulong want_access, bool no_errors)
#endif
}
+
+/**
+ Checks foreign key's parent table access.
+
+ @param thd [in] Thread handler
+ @param create_info [in] Create information (like MAX_ROWS, ENGINE or
+ temporary table flag)
+ @param alter_info [in] Initial list of columns and indexes for the
+ table to be created
+
+ @retval
+ false ok.
+ @retval
+ true error or access denied. Error is sent to client in this case.
+*/
+bool check_fk_parent_table_access(THD *thd,
+ HA_CREATE_INFO *create_info,
+ Alter_info *alter_info)
+{
+ Key *key;
+ List_iterator<Key> key_iterator(alter_info->key_list);
+
+ while ((key= key_iterator++))
+ {
+ if (key->type == Key::FOREIGN_KEY)
+ {
+ TABLE_LIST parent_table;
+ bool is_qualified_table_name;
+ Foreign_key *fk_key= (Foreign_key *)key;
+ LEX_STRING db_name;
+ LEX_STRING table_name= { fk_key->ref_table.str,
+ fk_key->ref_table.length };
+ const ulong privileges= (SELECT_ACL | INSERT_ACL | UPDATE_ACL |
+ DELETE_ACL | REFERENCES_ACL);
+
+ // Check if tablename is valid or not.
+ DBUG_ASSERT(table_name.str != NULL);
+ if (check_table_name(table_name.str, table_name.length, false))
+ {
+ my_error(ER_WRONG_TABLE_NAME, MYF(0), table_name.str);
+ return true;
+ }
+
+ if (fk_key->ref_db.str)
+ {
+ is_qualified_table_name= true;
+ db_name.str= (char *) thd->memdup(fk_key->ref_db.str,
+ fk_key->ref_db.length+1);
+ db_name.length= fk_key->ref_db.length;
+
+ // Check if database name is valid or not.
+ if (fk_key->ref_db.str && check_db_name(&db_name))
+ {
+ my_error(ER_WRONG_DB_NAME, MYF(0), db_name.str);
+ return true;
+ }
+ }
+ else if (thd->lex->copy_db_to(&db_name.str, &db_name.length))
+ return true;
+ else
+ is_qualified_table_name= false;
+
+ // if lower_case_table_names is set then convert tablename to lower case.
+ if (lower_case_table_names)
+ {
+ table_name.str= (char *) thd->memdup(fk_key->ref_table.str,
+ fk_key->ref_table.length+1);
+ table_name.length= my_casedn_str(files_charset_info, table_name.str);
+ }
+
+ parent_table.init_one_table(db_name.str, db_name.length,
+ table_name.str, table_name.length,
+ table_name.str, TL_IGNORE);
+
+ /*
+ Check if user has any of the "privileges" at table level on
+ "parent_table".
+ Having privilege on any of the parent_table column is not
+ enough so checking whether user has any of the "privileges"
+ at table level only here.
+ */
+ if (check_some_access(thd, privileges, &parent_table) ||
+ parent_table.grant.want_privilege)
+ {
+ if (is_qualified_table_name)
+ {
+ const size_t qualified_table_name_len= NAME_LEN + 1 + NAME_LEN + 1;
+ char *qualified_table_name= (char *) thd->alloc(qualified_table_name_len);
+
+ my_snprintf(qualified_table_name, qualified_table_name_len, "%s.%s",
+ db_name.str, table_name.str);
+ table_name.str= qualified_table_name;
+ }
+
+ my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0),
+ "REFERENCES",
+ thd->security_ctx->priv_user,
+ thd->security_ctx->host_or_ip,
+ table_name.str);
+
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+
/****************************************************************************
Check stack size; Send error if there isn't enough stack to continue
****************************************************************************/
@@ -7391,7 +7500,7 @@ static uint kill_threads_for_user(THD *thd, LEX_USER *user,
host.str[0] == '%' means that host name was not given. See sql_yacc.yy
*/
if (((user->host.str[0] == '%' && !user->host.str[1]) ||
- !strcmp(tmp->security_ctx->host, user->host.str)) &&
+ !strcmp(tmp->security_ctx->host_or_ip, user->host.str)) &&
!strcmp(tmp->security_ctx->user, user->user.str))
{
if (!(thd->security_ctx->master_access & SUPER_ACL) &&
@@ -8047,7 +8156,9 @@ bool create_table_precheck(THD *thd, TABLE_LIST *tables,
if (check_table_access(thd, SELECT_ACL, tables, FALSE, UINT_MAX, FALSE))
goto err;
}
- error= FALSE;
+
+ if (check_fk_parent_table_access(thd, &lex->create_info, &lex->alter_info))
+ goto err;
/*
For CREATE TABLE we should not open the table even if it exists.
@@ -8055,6 +8166,8 @@ bool create_table_precheck(THD *thd, TABLE_LIST *tables,
*/
lex->query_tables->open_strategy= TABLE_LIST::OPEN_STUB;
+ error= FALSE;
+
err:
DBUG_RETURN(error);
}
diff --git a/sql/sql_parse.h b/sql/sql_parse.h
index 926a4d800ad..40ae5427133 100644
--- a/sql/sql_parse.h
+++ b/sql/sql_parse.h
@@ -46,6 +46,9 @@ bool delete_precheck(THD *thd, TABLE_LIST *tables);
bool insert_precheck(THD *thd, TABLE_LIST *tables);
bool create_table_precheck(THD *thd, TABLE_LIST *tables,
TABLE_LIST *create_table);
+bool check_fk_parent_table_access(THD *thd,
+ HA_CREATE_INFO *create_info,
+ Alter_info *alter_info);
bool parse_sql(THD *thd, Parser_state *parser_state,
Object_creation_ctx *creation_ctx, bool do_pfs_digest=false);
diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc
index 3741712160e..4227641859d 100644
--- a/sql/sql_plugin.cc
+++ b/sql/sql_plugin.cc
@@ -3961,7 +3961,7 @@ static int test_plugin_options(MEM_ROOT *tmp_root, struct st_plugin_int *tmp,
we copy string values to a plugin's memroot.
*/
if (mysqld_server_started &&
- ((o->flags & (PLUGIN_VAR_STR | PLUGIN_VAR_NOCMDOPT |
+ ((o->flags & (PLUGIN_VAR_TYPEMASK | PLUGIN_VAR_NOCMDOPT |
PLUGIN_VAR_MEMALLOC)) == PLUGIN_VAR_STR))
{
sysvar_str_t* str= (sysvar_str_t *)o;
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 3912a039b9c..ed56191c32b 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -9991,7 +9991,7 @@ bool generate_derived_keys_for_table(KEYUSE *keyuse, uint count, uint keys)
else
{
/* Mark keyuses for this key to be excluded */
- for (KEYUSE *curr=save_first_keyuse; curr < first_keyuse; curr++)
+ for (KEYUSE *curr=save_first_keyuse; curr < keyuse; curr++)
{
curr->key= MAX_KEY;
}
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 8a2f38831dc..48aac779215 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -8376,9 +8376,21 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
}
/*
- If this is an ALTER TABLE and no explicit row type specified reuse
- the table's row type.
- Note : this is the same as if the row type was specified explicitly.
+ If foreign key is added then check permission to access parent table.
+
+ In function "check_fk_parent_table_access", create_info->db_type is used
+ to identify whether engine supports FK constraint or not. Since
+ create_info->db_type is set here, check to parent table access is delayed
+ till this point for the alter operation.
+ */
+ if ((alter_info->flags & Alter_info::ADD_FOREIGN_KEY) &&
+ check_fk_parent_table_access(thd, create_info, alter_info))
+ DBUG_RETURN(true);
+
+ /*
+ If this is an ALTER TABLE and no explicit row type specified reuse
+ the table's row type.
+ Note: this is the same as if the row type was specified explicitly.
*/
if (create_info->row_type == ROW_TYPE_NOT_USED)
{
@@ -9521,12 +9533,12 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
/*
- Recreates tables by calling mysql_alter_table().
+ Recreates one table by calling mysql_alter_table().
SYNOPSIS
mysql_recreate_table()
thd Thread handler
- tables Tables to recreate
+ table_list Table to recreate
table_copy Recreate the table by using
ALTER TABLE COPY algorithm
@@ -9538,13 +9550,15 @@ bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list, bool table_copy)
{
HA_CREATE_INFO create_info;
Alter_info alter_info;
- DBUG_ENTER("mysql_recreate_table");
- DBUG_ASSERT(!table_list->next_global);
+ TABLE_LIST *next_table= table_list->next_global;
+ DBUG_ENTER("mysql_recreate_table");
/* Set lock type which is appropriate for ALTER TABLE. */
table_list->lock_type= TL_READ_NO_INSERT;
/* Same applies to MDL request. */
table_list->mdl_request.set_type(MDL_SHARED_NO_WRITE);
+ /* hide following tables from open_tables() */
+ table_list->next_global= NULL;
bzero((char*) &create_info, sizeof(create_info));
create_info.row_type=ROW_TYPE_NOT_USED;
@@ -9556,9 +9570,11 @@ bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list, bool table_copy)
if (table_copy)
alter_info.requested_algorithm= Alter_info::ALTER_TABLE_ALGORITHM_COPY;
- DBUG_RETURN(mysql_alter_table(thd, NullS, NullS, &create_info,
+ bool res= mysql_alter_table(thd, NullS, NullS, &create_info,
table_list, &alter_info, 0,
- (ORDER *) 0, 0));
+ (ORDER *) 0, 0);
+ table_list->next_global= next_table;
+ DBUG_RETURN(res);
}
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index 6a81301a6d9..20a16e3eae1 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -685,7 +685,7 @@ err:
/* number of required parameters for making view */
-static const int required_view_parameters= 14;
+static const int required_view_parameters= 15;
/*
table of VIEW .frm field descriptors
@@ -736,6 +736,9 @@ static File_option view_parameters[]=
{{(char*) STRING_WITH_LEN("view_body_utf8")},
my_offsetof(TABLE_LIST, view_body_utf8),
FILE_OPTIONS_ESTRING},
+ {{ C_STRING_WITH_LEN("mariadb-version")},
+ my_offsetof(TABLE_LIST, mariadb_version),
+ FILE_OPTIONS_ULONGLONG},
{{NullS, 0}, 0,
FILE_OPTIONS_STRING}
};
@@ -836,6 +839,7 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
version 2 - empty definer_host means a role
*/
view->file_version= 2;
+ view->mariadb_version= MYSQL_VERSION_ID;
view->calc_md5(md5);
if (!(view->md5.str= (char*) thd->memdup(md5, 32)))
{
diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc
index a0cc344d43f..f1942d08591 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -3435,13 +3435,13 @@ static Sys_var_bit Sys_log_off(
static bool fix_sql_log_bin_after_update(sys_var *self, THD *thd,
enum_var_type type)
{
- if (type == OPT_SESSION)
- {
- if (thd->variables.sql_log_bin)
- thd->variables.option_bits |= OPTION_BIN_LOG;
- else
- thd->variables.option_bits &= ~OPTION_BIN_LOG;
- }
+ DBUG_ASSERT(type == OPT_SESSION);
+
+ if (thd->variables.sql_log_bin)
+ thd->variables.option_bits |= OPTION_BIN_LOG;
+ else
+ thd->variables.option_bits &= ~OPTION_BIN_LOG;
+
return FALSE;
}
@@ -3463,7 +3463,10 @@ static bool check_sql_log_bin(sys_var *self, THD *thd, set_var *var)
return TRUE;
if (var->type == OPT_GLOBAL)
- return FALSE;
+ {
+ my_error(ER_INCORRECT_GLOBAL_LOCAL_VAR, MYF(0), self->name.str, "SESSION");
+ return TRUE;
+ }
if (error_if_in_trans_or_substatement(thd,
ER_STORED_FUNCTION_PREVENTS_SWITCH_SQL_LOG_BIN,
@@ -3474,9 +3477,9 @@ static bool check_sql_log_bin(sys_var *self, THD *thd, set_var *var)
}
static Sys_var_mybool Sys_log_binlog(
- "sql_log_bin", "sql_log_bin",
- SESSION_VAR(sql_log_bin), NO_CMD_LINE,
- DEFAULT(TRUE), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_sql_log_bin),
+ "sql_log_bin", "Controls whether logging to the binary log is done",
+ SESSION_VAR(sql_log_bin), NO_CMD_LINE, DEFAULT(TRUE),
+ NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_sql_log_bin),
ON_UPDATE(fix_sql_log_bin_after_update));
static Sys_var_bit Sys_sql_warnings(
@@ -4483,7 +4486,7 @@ static Sys_var_ulong Sys_sp_cache_size(
"The soft upper limit for number of cached stored routines for "
"one connection.",
GLOBAL_VAR(stored_program_cache_size), CMD_LINE(REQUIRED_ARG),
- VALID_RANGE(256, 512 * 1024), DEFAULT(256), BLOCK_SIZE(1));
+ VALID_RANGE(0, 512 * 1024), DEFAULT(256), BLOCK_SIZE(1));
export const char *plugin_maturity_names[]=
{ "unknown", "experimental", "alpha", "beta", "gamma", "stable", 0 };
diff --git a/sql/table.cc b/sql/table.cc
index f23823bdf4f..321c2a96b4f 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -828,6 +828,24 @@ static bool create_key_infos(const uchar *strpos, const uchar *frm_image_end,
}
+/** ensures that the enum value (read from frm) is within limits
+
+ if not - issues a warning and resets the value to 0
+ (that is, 0 is assumed to be a default value)
+*/
+
+static uint enum_value_with_check(THD *thd, TABLE_SHARE *share,
+ const char *name, uint value, uint limit)
+{
+ if (value < limit)
+ return value;
+
+ sql_print_warning("%s.frm: invalid value %d for the field %s",
+ share->normalized_path.str, value, name);
+ return 0;
+}
+
+
/**
Check if a collation has changed number
@@ -837,8 +855,7 @@ static bool create_key_infos(const uchar *strpos, const uchar *frm_image_end,
@retval new collation number (same as current collation number of no change)
*/
-static uint
-upgrade_collation(ulong mysql_version, uint cs_number)
+static uint upgrade_collation(ulong mysql_version, uint cs_number)
{
if (mysql_version >= 50300 && mysql_version <= 50399)
{
@@ -862,8 +879,6 @@ upgrade_collation(ulong mysql_version, uint cs_number)
}
-
-
/**
Read data from a binary .frm file image into a TABLE_SHARE
@@ -1047,9 +1062,12 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
share->incompatible_version|= HA_CREATE_USED_CHARSET;
share->avg_row_length= uint4korr(frm_image+34);
- share->transactional= (ha_choice) (frm_image[39] & 3);
- share->page_checksum= (ha_choice) ((frm_image[39] >> 2) & 3);
- share->row_type= (enum row_type) frm_image[40];
+ share->transactional= (ha_choice)
+ enum_value_with_check(thd, share, "transactional", frm_image[39] & 3, HA_CHOICE_MAX);
+ share->page_checksum= (ha_choice)
+ enum_value_with_check(thd, share, "page_checksum", (frm_image[39] >> 2) & 3, HA_CHOICE_MAX);
+ share->row_type= (enum row_type)
+ enum_value_with_check(thd, share, "row_format", frm_image[40], ROW_TYPE_MAX);
if (cs_new && !(share->table_charset= get_charset(cs_new, MYF(MY_WME))))
goto err;
diff --git a/sql/table.h b/sql/table.h
index 58b78af6836..b978484158b 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -1898,6 +1898,7 @@ struct TABLE_LIST
LEX_STRING timestamp; /* GMT time stamp of last operation */
st_lex_user definer; /* definer of view */
ulonglong file_version; /* version of file's field set */
+ ulonglong mariadb_version; /* version of server on creation */
ulonglong updatable_view; /* VIEW can be updated */
/**
@brief The declared algorithm, if this is a view.