Commit 28f81366 authored by Otto Kekäläinen's avatar Otto Kekäläinen
Browse files

Merge tag 'upstream/5.5.58' into ubuntu-14.04

Upstream version 5.5.58

# gpg: Signature made la 30. joulukuuta 2017 17.55.25 EET
# gpg:                using RSA key BED8449FCEE8DA88
# gpg: Good signature from "Otto Kekäläinen <otto@seravo.fi>" [full]
# gpg:                 aka "Otto Kekäläinen <otto@kekalainen.net>" [full]
# gpg:                 aka "Otto Kekäläinen <otto@fsfe.org>" [full]
# gpg:                 aka "Otto Kekäläinen <otto@linux.com>" [full]
# gpg:                 aka "Otto Kekäläinen <otto.kekalainen@seravo.fi>" [full]
# gpg:                 aka "Otto Kekäläinen <otto@mariadb.org>" [undefined]
# gpg:                 aka "Otto Kekäläinen <otto@debian.org>" [undefined]
# gpg:                 aka "Otto Kekäläinen <otto@sange.fi>" [full]
parents d84cded3 fa5f29ea
...@@ -139,7 +139,7 @@ sp_get_item_value(THD *thd, Item *item, String *str) ...@@ -139,7 +139,7 @@ sp_get_item_value(THD *thd, Item *item, String *str)
case DECIMAL_RESULT: case DECIMAL_RESULT:
if (item->field_type() != MYSQL_TYPE_BIT) if (item->field_type() != MYSQL_TYPE_BIT)
return item->val_str(str); return item->val_str(str);
else {/* Bit type is handled as binary string */} /* fall through */
case STRING_RESULT: case STRING_RESULT:
{ {
String *result= item->val_str(str); String *result= item->val_str(str);
......
...@@ -54,7 +54,6 @@ static bool admin_recreate_table(THD *thd, TABLE_LIST *table_list) ...@@ -54,7 +54,6 @@ static bool admin_recreate_table(THD *thd, TABLE_LIST *table_list)
if (thd->stmt_da->is_ok()) if (thd->stmt_da->is_ok())
thd->stmt_da->reset_diagnostics_area(); thd->stmt_da->reset_diagnostics_area();
table_list->table= NULL; table_list->table= NULL;
result_code= result_code ? HA_ADMIN_FAILED : HA_ADMIN_OK;
DBUG_RETURN(result_code); DBUG_RETURN(result_code);
} }
......
...@@ -8128,13 +8128,15 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields, ...@@ -8128,13 +8128,15 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
bool setup_fields(THD *thd, Item **ref_pointer_array, bool setup_fields(THD *thd, Item **ref_pointer_array,
List<Item> &fields, enum_mark_columns mark_used_columns, List<Item> &fields, enum_mark_columns mark_used_columns,
List<Item> *sum_func_list, bool allow_sum_func) List<Item> *sum_func_list, List<Item> *pre_fix,
bool allow_sum_func)
{ {
reg2 Item *item; reg2 Item *item;
enum_mark_columns save_mark_used_columns= thd->mark_used_columns; enum_mark_columns save_mark_used_columns= thd->mark_used_columns;
nesting_map save_allow_sum_func= thd->lex->allow_sum_func; nesting_map save_allow_sum_func= thd->lex->allow_sum_func;
List_iterator<Item> it(fields); List_iterator<Item> it(fields);
bool save_is_item_list_lookup; bool save_is_item_list_lookup;
bool make_pre_fix= (pre_fix && (pre_fix->elements == 0));
DBUG_ENTER("setup_fields"); DBUG_ENTER("setup_fields");
DBUG_PRINT("enter", ("ref_pointer_array: %p", ref_pointer_array)); DBUG_PRINT("enter", ("ref_pointer_array: %p", ref_pointer_array));
...@@ -8181,6 +8183,9 @@ bool setup_fields(THD *thd, Item **ref_pointer_array, ...@@ -8181,6 +8183,9 @@ bool setup_fields(THD *thd, Item **ref_pointer_array,
thd->lex->current_select->cur_pos_in_select_list= 0; thd->lex->current_select->cur_pos_in_select_list= 0;
while ((item= it++)) while ((item= it++))
{ {
if (make_pre_fix)
pre_fix->push_back(item, thd->stmt_arena->mem_root);
if ((!item->fixed && item->fix_fields(thd, it.ref())) || if ((!item->fixed && item->fix_fields(thd, it.ref())) ||
(item= *(it.ref()))->check_cols(1)) (item= *(it.ref()))->check_cols(1))
{ {
......
...@@ -216,7 +216,8 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields, ...@@ -216,7 +216,8 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
List<Item> *sum_func_list, uint wild_num); List<Item> *sum_func_list, uint wild_num);
bool setup_fields(THD *thd, Item** ref_pointer_array, bool setup_fields(THD *thd, Item** ref_pointer_array,
List<Item> &item, enum_mark_columns mark_used_columns, List<Item> &item, enum_mark_columns mark_used_columns,
List<Item> *sum_func_list, bool allow_sum_func); List<Item> *sum_func_list, List<Item> *pre_fix,
bool allow_sum_func);
void unfix_fields(List<Item> &items); void unfix_fields(List<Item> &items);
bool fill_record(THD *thd, Field **field, List<Item> &values, bool fill_record(THD *thd, Field **field, List<Item> &values,
bool ignore_errors, bool use_value); bool ignore_errors, bool use_value);
...@@ -407,7 +408,7 @@ inline bool setup_fields_with_no_wrap(THD *thd, Item **ref_pointer_array, ...@@ -407,7 +408,7 @@ inline bool setup_fields_with_no_wrap(THD *thd, Item **ref_pointer_array,
bool res; bool res;
thd->lex->select_lex.no_wrap_view_item= TRUE; thd->lex->select_lex.no_wrap_view_item= TRUE;
res= setup_fields(thd, ref_pointer_array, item, mark_used_columns, res= setup_fields(thd, ref_pointer_array, item, mark_used_columns,
sum_func_list, allow_sum_func); sum_func_list, NULL, allow_sum_func);
thd->lex->select_lex.no_wrap_view_item= FALSE; thd->lex->select_lex.no_wrap_view_item= FALSE;
return res; return res;
} }
......
...@@ -41,7 +41,18 @@ ...@@ -41,7 +41,18 @@
#define MAX_MBWIDTH 3 /* Max multibyte sequence */ #define MAX_MBWIDTH 3 /* Max multibyte sequence */
#define MAX_FIELD_CHARLENGTH 255 #define MAX_FIELD_CHARLENGTH 255
#define MAX_FIELD_VARCHARLENGTH 65535 /*
In MAX_FIELD_VARCHARLENGTH we reserve extra bytes for the overhead:
- 2 bytes for the length
- 1 byte for NULL bits
to avoid the "Row size too large" error for these three corner definitions:
CREATE TABLE t1 (c VARBINARY(65533));
CREATE TABLE t1 (c VARBINARY(65534));
CREATE TABLE t1 (c VARBINARY(65535));
Like VARCHAR(65536), they will be converted to BLOB automatically
in non-sctict mode.
*/
#define MAX_FIELD_VARCHARLENGTH (65535-2-1)
#define MAX_FIELD_BLOBLENGTH UINT_MAX32 /* cf field_blob::get_length() */ #define MAX_FIELD_BLOBLENGTH UINT_MAX32 /* cf field_blob::get_length() */
#define CONVERT_IF_BIGGER_TO_BLOB 512 /* Threshold *in characters* */ #define CONVERT_IF_BIGGER_TO_BLOB 512 /* Threshold *in characters* */
......
...@@ -510,6 +510,8 @@ bool mysql_derived_merge_for_insert(THD *thd, LEX *lex, TABLE_LIST *derived) ...@@ -510,6 +510,8 @@ bool mysql_derived_merge_for_insert(THD *thd, LEX *lex, TABLE_LIST *derived)
DBUG_ENTER("mysql_derived_merge_for_insert"); DBUG_ENTER("mysql_derived_merge_for_insert");
if (derived->merged_for_insert) if (derived->merged_for_insert)
DBUG_RETURN(FALSE); DBUG_RETURN(FALSE);
if (derived->init_derived(thd, FALSE))
DBUG_RETURN(TRUE);
if (derived->is_materialized_derived()) if (derived->is_materialized_derived())
DBUG_RETURN(mysql_derived_prepare(thd, lex, derived)); DBUG_RETURN(mysql_derived_prepare(thd, lex, derived));
if ((thd->lex->sql_command == SQLCOM_UPDATE_MULTI || if ((thd->lex->sql_command == SQLCOM_UPDATE_MULTI ||
...@@ -526,8 +528,6 @@ bool mysql_derived_merge_for_insert(THD *thd, LEX *lex, TABLE_LIST *derived) ...@@ -526,8 +528,6 @@ bool mysql_derived_merge_for_insert(THD *thd, LEX *lex, TABLE_LIST *derived)
derived->merged_for_insert= TRUE; derived->merged_for_insert= TRUE;
} }
} }
else
derived->table= derived->merge_underlying_list->table;
DBUG_RETURN(FALSE); DBUG_RETURN(FALSE);
} }
......
...@@ -28,7 +28,7 @@ bool mysql_do(THD *thd, List<Item> &values) ...@@ -28,7 +28,7 @@ bool mysql_do(THD *thd, List<Item> &values)
List_iterator<Item> li(values); List_iterator<Item> li(values);
Item *value; Item *value;
DBUG_ENTER("mysql_do"); DBUG_ENTER("mysql_do");
if (setup_fields(thd, 0, values, MARK_COLUMNS_NONE, 0, 0)) if (setup_fields(thd, 0, values, MARK_COLUMNS_NONE, 0, NULL, 0))
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
while ((value = li++)) while ((value = li++))
value->val_int(); value->val_int();
......
...@@ -262,7 +262,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list, ...@@ -262,7 +262,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list,
if (table_list->is_view()) if (table_list->is_view())
unfix_fields(fields); unfix_fields(fields);
res= setup_fields(thd, 0, fields, MARK_COLUMNS_WRITE, 0, 0); res= setup_fields(thd, 0, fields, MARK_COLUMNS_WRITE, 0, NULL, 0);
/* Restore the current context. */ /* Restore the current context. */
ctx_state.restore_state(context, table_list); ctx_state.restore_state(context, table_list);
...@@ -373,7 +373,7 @@ static int check_update_fields(THD *thd, TABLE_LIST *insert_table_list, ...@@ -373,7 +373,7 @@ static int check_update_fields(THD *thd, TABLE_LIST *insert_table_list,
} }
/* Check the fields we are going to modify */ /* Check the fields we are going to modify */
if (setup_fields(thd, 0, update_fields, MARK_COLUMNS_WRITE, 0, 0)) if (setup_fields(thd, 0, update_fields, MARK_COLUMNS_WRITE, 0, NULL, 0))
return -1; return -1;
if (insert_table_list->is_view() && if (insert_table_list->is_view() &&
...@@ -810,7 +810,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, ...@@ -810,7 +810,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
my_error(ER_WRONG_VALUE_COUNT_ON_ROW, MYF(0), counter); my_error(ER_WRONG_VALUE_COUNT_ON_ROW, MYF(0), counter);
goto abort; goto abort;
} }
if (setup_fields(thd, 0, *values, MARK_COLUMNS_READ, 0, 0)) if (setup_fields(thd, 0, *values, MARK_COLUMNS_READ, 0, NULL, 0))
goto abort; goto abort;
} }
its.rewind (); its.rewind ();
...@@ -1452,7 +1452,7 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, ...@@ -1452,7 +1452,7 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list,
table_list->next_local= 0; table_list->next_local= 0;
context->resolve_in_table_list_only(table_list); context->resolve_in_table_list_only(table_list);
res= (setup_fields(thd, 0, *values, MARK_COLUMNS_READ, 0, 0) || res= (setup_fields(thd, 0, *values, MARK_COLUMNS_READ, 0, NULL, 0) ||
check_insert_fields(thd, context->table_list, fields, *values, check_insert_fields(thd, context->table_list, fields, *values,
!insert_into_view, 0, &map)); !insert_into_view, 0, &map));
...@@ -1468,7 +1468,7 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, ...@@ -1468,7 +1468,7 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list,
} }
if (!res) if (!res)
res= setup_fields(thd, 0, update_values, MARK_COLUMNS_READ, 0, 0); res= setup_fields(thd, 0, update_values, MARK_COLUMNS_READ, 0, NULL, 0);
if (!res && duplic == DUP_UPDATE) if (!res && duplic == DUP_UPDATE)
{ {
...@@ -3369,7 +3369,7 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u) ...@@ -3369,7 +3369,7 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
*/ */
lex->current_select= &lex->select_lex; lex->current_select= &lex->select_lex;
res= (setup_fields(thd, 0, values, MARK_COLUMNS_READ, 0, 0) || res= (setup_fields(thd, 0, values, MARK_COLUMNS_READ, 0, NULL, 0) ||
check_insert_fields(thd, table_list, *fields, values, check_insert_fields(thd, table_list, *fields, values,
!insert_into_view, 1, &map)); !insert_into_view, 1, &map));
...@@ -3425,7 +3425,7 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u) ...@@ -3425,7 +3425,7 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
ctx_state.get_first_name_resolution_table(); ctx_state.get_first_name_resolution_table();
res= res || setup_fields(thd, 0, *info.update_values, res= res || setup_fields(thd, 0, *info.update_values,
MARK_COLUMNS_READ, 0, 0); MARK_COLUMNS_READ, 0, NULL, 0);
if (!res) if (!res)
{ {
/* /*
......
...@@ -1147,12 +1147,14 @@ static int lex_one_token(YYSTYPE *yylval, THD *thd) ...@@ -1147,12 +1147,14 @@ static int lex_one_token(YYSTYPE *yylval, THD *thd)
state= MY_LEX_HEX_NUMBER; state= MY_LEX_HEX_NUMBER;
break; break;
} }
/* fall through */
case MY_LEX_IDENT_OR_BIN: case MY_LEX_IDENT_OR_BIN:
if (lip->yyPeek() == '\'') if (lip->yyPeek() == '\'')
{ // Found b'bin-number' { // Found b'bin-number'
state= MY_LEX_BIN_NUMBER; state= MY_LEX_BIN_NUMBER;
break; break;
} }
/* fall through */
case MY_LEX_IDENT: case MY_LEX_IDENT:
const char *start; const char *start;
#if defined(USE_MB) && defined(USE_MB_IDENT) #if defined(USE_MB) && defined(USE_MB_IDENT)
...@@ -1499,7 +1501,7 @@ static int lex_one_token(YYSTYPE *yylval, THD *thd) ...@@ -1499,7 +1501,7 @@ static int lex_one_token(YYSTYPE *yylval, THD *thd)
state= MY_LEX_USER_VARIABLE_DELIMITER; state= MY_LEX_USER_VARIABLE_DELIMITER;
break; break;
} }
/* " used for strings */ /* fall through */ /* " used for strings */
case MY_LEX_STRING: // Incomplete text string case MY_LEX_STRING: // Incomplete text string
if (!(yylval->lex_str.str = get_text(lip, 1, 1))) if (!(yylval->lex_str.str = get_text(lip, 1, 1)))
{ {
......
...@@ -758,6 +758,7 @@ class st_select_lex: public st_select_lex_node ...@@ -758,6 +758,7 @@ class st_select_lex: public st_select_lex_node
Group_list_ptrs *group_list_ptrs; Group_list_ptrs *group_list_ptrs;
List<Item> item_list; /* list of fields & expressions */ List<Item> item_list; /* list of fields & expressions */
List<Item> pre_fix; /* above list before fix_fields */
List<String> interval_list; List<String> interval_list;
bool is_item_list_lookup; bool is_item_list_lookup;
/* /*
......
...@@ -293,15 +293,15 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, ...@@ -293,15 +293,15 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
Let us also prepare SET clause, altough it is probably empty Let us also prepare SET clause, altough it is probably empty
in this case. in this case.
*/ */
if (setup_fields(thd, 0, set_fields, MARK_COLUMNS_WRITE, 0, 0) || if (setup_fields(thd, 0, set_fields, MARK_COLUMNS_WRITE, 0, NULL, 0) ||
setup_fields(thd, 0, set_values, MARK_COLUMNS_READ, 0, 0)) setup_fields(thd, 0, set_values, MARK_COLUMNS_READ, 0, NULL, 0))
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
} }
else else
{ // Part field list { // Part field list
/* TODO: use this conds for 'WITH CHECK OPTIONS' */ /* TODO: use this conds for 'WITH CHECK OPTIONS' */
if (setup_fields(thd, 0, fields_vars, MARK_COLUMNS_WRITE, 0, 0) || if (setup_fields(thd, 0, fields_vars, MARK_COLUMNS_WRITE, 0, NULL, 0) ||
setup_fields(thd, 0, set_fields, MARK_COLUMNS_WRITE, 0, 0) || setup_fields(thd, 0, set_fields, MARK_COLUMNS_WRITE, 0, NULL, 0) ||
check_that_all_fields_are_given_values(thd, table, table_list)) check_that_all_fields_are_given_values(thd, table, table_list))
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
/* /*
...@@ -320,7 +320,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, ...@@ -320,7 +320,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
} }
} }
/* Fix the expressions in SET clause */ /* Fix the expressions in SET clause */
if (setup_fields(thd, 0, set_values, MARK_COLUMNS_READ, 0, 0)) if (setup_fields(thd, 0, set_values, MARK_COLUMNS_READ, 0, NULL, 0))
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
} }
......
...@@ -811,8 +811,7 @@ bool do_command(THD *thd) ...@@ -811,8 +811,7 @@ bool do_command(THD *thd)
@retval FALSE The statement isn't updating any relevant tables. @retval FALSE The statement isn't updating any relevant tables.
*/ */
static my_bool deny_updates_if_read_only_option(THD *thd, static bool deny_updates_if_read_only_option(THD *thd, TABLE_LIST *all_tables)
TABLE_LIST *all_tables)
{ {
DBUG_ENTER("deny_updates_if_read_only_option"); DBUG_ENTER("deny_updates_if_read_only_option");
...@@ -821,11 +820,7 @@ static my_bool deny_updates_if_read_only_option(THD *thd, ...@@ -821,11 +820,7 @@ static my_bool deny_updates_if_read_only_option(THD *thd,
LEX *lex= thd->lex; LEX *lex= thd->lex;
const my_bool user_is_super= if (thd->security_ctx->master_access & SUPER_ACL)
((ulong)(thd->security_ctx->master_access & SUPER_ACL) ==
(ulong)SUPER_ACL);
if (user_is_super)
DBUG_RETURN(FALSE); DBUG_RETURN(FALSE);
if (!(sql_command_flags[lex->sql_command] & CF_CHANGES_DATA)) if (!(sql_command_flags[lex->sql_command] & CF_CHANGES_DATA))
...@@ -835,30 +830,26 @@ static my_bool deny_updates_if_read_only_option(THD *thd, ...@@ -835,30 +830,26 @@ static my_bool deny_updates_if_read_only_option(THD *thd,
if (lex->sql_command == SQLCOM_UPDATE_MULTI) if (lex->sql_command == SQLCOM_UPDATE_MULTI)
DBUG_RETURN(FALSE); DBUG_RETURN(FALSE);
if (lex->sql_command == SQLCOM_CREATE_DB ||
lex->sql_command == SQLCOM_DROP_DB)
DBUG_RETURN(TRUE);
/* /*
a table-to-be-created is not in the temp table list yet, a table-to-be-created is not in the temp table list yet,
so CREATE TABLE needs a special treatment so CREATE TABLE needs a special treatment
*/ */
const bool update_real_tables= if (lex->sql_command == SQLCOM_CREATE_TABLE)
lex->sql_command == SQLCOM_CREATE_TABLE DBUG_RETURN(!(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE));
? !(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE)
: some_non_temp_table_to_be_updated(thd, all_tables);
const bool create_or_drop_databases=
(lex->sql_command == SQLCOM_CREATE_DB) ||
(lex->sql_command == SQLCOM_DROP_DB);
if (update_real_tables || create_or_drop_databases)
{
/* /*
An attempt was made to modify one or more non-temporary tables. a table-to-be-dropped might not exist (DROP TEMPORARY TABLE IF EXISTS),
cannot use the temp table list either.
*/ */
DBUG_RETURN(TRUE); if (lex->sql_command == SQLCOM_DROP_TABLE && lex->drop_temporary)
}
/* Assuming that only temporary tables are modified. */
DBUG_RETURN(FALSE); DBUG_RETURN(FALSE);
/* Now, check thd->temporary_tables list */
DBUG_RETURN(some_non_temp_table_to_be_updated(thd, all_tables));
} }
/** /**
...@@ -2481,7 +2472,7 @@ case SQLCOM_PREPARE: ...@@ -2481,7 +2472,7 @@ case SQLCOM_PREPARE:
#ifdef WITH_PARTITION_STORAGE_ENGINE #ifdef WITH_PARTITION_STORAGE_ENGINE
{ {
partition_info *part_info= thd->lex->part_info; partition_info *part_info= thd->lex->part_info;
if (part_info && !(part_info= thd->lex->part_info->get_clone())) if (part_info && !(part_info= part_info->get_clone()))
{ {
res= -1; res= -1;
goto end_with_restore_list; goto end_with_restore_list;
...@@ -2850,8 +2841,8 @@ case SQLCOM_PREPARE: ...@@ -2850,8 +2841,8 @@ case SQLCOM_PREPARE:
/* mysql_update return 2 if we need to switch to multi-update */ /* mysql_update return 2 if we need to switch to multi-update */
if (up_result != 2) if (up_result != 2)
break; break;
/* Fall through */
} }
/* fall through */
case SQLCOM_UPDATE_MULTI: case SQLCOM_UPDATE_MULTI:
{ {
DBUG_ASSERT(first_table == all_tables && first_table != 0); DBUG_ASSERT(first_table == all_tables && first_table != 0);
...@@ -2961,6 +2952,7 @@ case SQLCOM_PREPARE: ...@@ -2961,6 +2952,7 @@ case SQLCOM_PREPARE:
DBUG_PRINT("debug", ("Just after generate_incident()")); DBUG_PRINT("debug", ("Just after generate_incident()"));
} }
#endif #endif
/* fall through */
case SQLCOM_INSERT: case SQLCOM_INSERT:
{ {
DBUG_ASSERT(first_table == all_tables && first_table != 0); DBUG_ASSERT(first_table == all_tables && first_table != 0);
...@@ -3698,6 +3690,7 @@ case SQLCOM_PREPARE: ...@@ -3698,6 +3690,7 @@ case SQLCOM_PREPARE:
initialize this variable because RESET shares the same code as FLUSH initialize this variable because RESET shares the same code as FLUSH
*/ */
lex->no_write_to_binlog= 1; lex->no_write_to_binlog= 1;
/* fall through */
case SQLCOM_FLUSH: case SQLCOM_FLUSH:
{ {
int write_to_binlog; int write_to_binlog;
......
/* Copyright (c) 2005, 2014, Oracle and/or its affiliates. /* Copyright (c) 2005, 2017, Oracle and/or its affiliates.
Copyright (c) 2009, 2014, SkySQL Ab. Copyright (c) 2009, 2017, SkySQL Ab.
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
...@@ -4640,7 +4640,7 @@ uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info, ...@@ -4640,7 +4640,7 @@ uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info,
thd->work_part_info= thd->lex->part_info; thd->work_part_info= thd->lex->part_info;
if (thd->work_part_info && if (thd->work_part_info &&
!(thd->work_part_info= thd->lex->part_info->get_clone())) !(thd->work_part_info= thd->work_part_info->get_clone()))
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
/* ALTER_ADMIN_PARTITION is handled in mysql_admin_table */ /* ALTER_ADMIN_PARTITION is handled in mysql_admin_table */
...@@ -6672,7 +6672,8 @@ uint fast_alter_partition_table(THD *thd, TABLE *table, ...@@ -6672,7 +6672,8 @@ uint fast_alter_partition_table(THD *thd, TABLE *table,
lpt->alter_info= alter_info; lpt->alter_info= alter_info;
lpt->create_info= create_info; lpt->create_info= create_info;
lpt->db_options= create_info->table_options; lpt->db_options= create_info->table_options;
if (create_info->row_type == ROW_TYPE_DYNAMIC) if (create_info->row_type != ROW_TYPE_FIXED &&
create_info->row_type != ROW_TYPE_DEFAULT)
lpt->db_options|= HA_OPTION_PACK_RECORD; lpt->db_options|= HA_OPTION_PACK_RECORD;
lpt->table= fast_alter_table; lpt->table= fast_alter_table;
lpt->old_table= table; lpt->old_table= table;
...@@ -8163,6 +8164,7 @@ int create_partition_name(char *out, size_t outlen, const char *in1, ...@@ -8163,6 +8164,7 @@ int create_partition_name(char *out, size_t outlen, const char *in1,
} }
else else
transl_part= in2; transl_part= in2;
if (name_variant == NORMAL_PART_NAME) if (name_variant == NORMAL_PART_NAME)
end= strxnmov(out, outlen-1, in1, "#P#", transl_part, NullS); end= strxnmov(out, outlen-1, in1, "#P#", transl_part, NullS);
else if (name_variant == TEMP_PART_NAME) else if (name_variant == TEMP_PART_NAME)
...@@ -8177,25 +8179,19 @@ int create_partition_name(char *out, size_t outlen, const char *in1, ...@@ -8177,25 +8179,19 @@ int create_partition_name(char *out, size_t outlen, const char *in1,
return 0; return 0;
} }
/**
/* Create subpartition name. This method is used to calculate the
Create subpartition name subpartition name, service routine to the del_ren_cre_table method.
The output buffer size should be FN_REFLEN + 1(terminating '\0').
SYNOPSIS
create_subpartition_name() @param [out] out Created partition name string
out:out The buffer for the created partition name string @param in1 First part
must be *at least* of FN_REFLEN+1 bytes @param in2 Second part
in1 First part @param in3 Third part
in2 Second part @param name_variant Normal, temporary or renamed partition name
in3 Third part
name_variant Normal, temporary or renamed partition name @retval true Error.
@retval false Success.
RETURN VALUE
0 if ok, error if name too long
DESCRIPTION
This method is used to calculate the subpartition name, service routine to
the del_ren_cre_table method.
*/ */
int create_subpartition_name(char *out, size_t outlen, int create_subpartition_name(char *out, size_t outlen,
...@@ -8207,6 +8203,7 @@ int create_subpartition_name(char *out, size_t outlen, ...@@ -8207,6 +8203,7 @@ int create_subpartition_name(char *out, size_t outlen,
tablename_to_filename(in2, transl_part_name, FN_REFLEN); tablename_to_filename(in2, transl_part_name, FN_REFLEN);
tablename_to_filename(in3, transl_subpart_name, FN_REFLEN); tablename_to_filename(in3, transl_subpart_name, FN_REFLEN);
if (name_variant == NORMAL_PART_NAME) if (name_variant == NORMAL_PART_NAME)
end= strxnmov(out, outlen-1, in1, "#P#", transl_part_name, end= strxnmov(out, outlen-1, in1, "#P#", transl_part_name,
"#SP#", transl_subpart_name, NullS); "#SP#", transl_subpart_name, NullS);
......
#ifndef SQL_PARTITION_INCLUDED #ifndef SQL_PARTITION_INCLUDED
#define SQL_PARTITION_INCLUDED #define SQL_PARTITION_INCLUDED
/* Copyright (c) 2006, 2013, Oracle and/or its affiliates. /* Copyright (c) 2006, 2017, Oracle and/or its affiliates.
Copyright (c) 2011, 2017, MariaDB
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
......
...@@ -194,7 +194,6 @@ static DYNAMIC_ARRAY plugin_array; ...@@ -194,7 +194,6 @@ static DYNAMIC_ARRAY plugin_array;
static HASH plugin_hash[MYSQL_MAX_PLUGIN_TYPE_NUM]; static HASH plugin_hash[MYSQL_MAX_PLUGIN_TYPE_NUM];
static MEM_ROOT plugin_mem_root; static MEM_ROOT plugin_mem_root;
static bool reap_needed= false; static bool reap_needed= false;
static int plugin_array_version=0;
static bool initialized= 0; static bool initialized= 0;
...@@ -312,7 +311,6 @@ static void plugin_vars_free_values(sys_var *vars); ...@@ -312,7 +311,6 @@ static void plugin_vars_free_values(sys_var *vars);
static void restore_pluginvar_names(sys_var *first); static void restore_pluginvar_names(sys_var *first);
static void plugin_opt_set_limits(struct my_option *, static void plugin_opt_set_limits(struct my_option *,
const struct st_mysql_sys_var *); const struct st_mysql_sys_var *);
static plugin_ref intern_plugin_lock(LEX *lex, plugin_ref plugin);
static void intern_plugin_unlock(LEX *lex, plugin_ref plugin); static void intern_plugin_unlock(LEX *lex, plugin_ref plugin);
static void reap_plugins(void); static void reap_plugins(void);
...@@ -924,14 +922,16 @@ SHOW_COMP_OPTION plugin_status(const char *name, size_t len, int type) ...@@ -924,14 +922,16 @@ SHOW_COMP_OPTION plugin_status(const char *name, size_t len, int type)
} }
static plugin_ref intern_plugin_lock(LEX *lex, plugin_ref rc) static plugin_ref intern_plugin_lock(LEX *lex, plugin_ref rc,
uint state_mask= PLUGIN_IS_READY |
PLUGIN_IS_UNINITIALIZED)
{ {
st_plugin_int *pi= plugin_ref_to_int(rc); st_plugin_int *pi= plugin_ref_to_int(rc);
DBUG_ENTER("intern_plugin_lock"); DBUG_ENTER("intern_plugin_lock");
mysql_mutex_assert_owner(&LOCK_plugin); mysql_mutex_assert_owner(&LOCK_plugin);
if (pi->state & (PLUGIN_IS_READY | PLUGIN_IS_UNINITIALIZED)) if (pi->state & state_mask)
{ {
plugin_ref plugin; plugin_ref plugin;
#ifdef DBUG_OFF #ifdef DBUG_OFF
...@@ -1111,7 +1111,6 @@ static bool plugin_add(MEM_ROOT *tmp_root, ...@@ -1111,7 +1111,6 @@ static bool plugin_add(MEM_ROOT *tmp_root,
if (!(tmp_plugin_ptr= plugin_insert_or_reuse(&tmp))) if (!(tmp_plugin_ptr= plugin_insert_or_reuse(&tmp)))
goto err; goto err;
plugin_array_version++;
if (my_hash_insert(&plugin_hash[plugin->type], (uchar*)tmp_plugin_ptr)) if (my_hash_insert(&plugin_hash[plugin->type], (uchar*)tmp_plugin_ptr))
tmp_plugin_ptr->state= PLUGIN_IS_FREED; tmp_plugin_ptr->state= PLUGIN_IS_FREED;
init_alloc_root(&tmp_plugin_ptr->mem_root, 4096, 4096); init_alloc_root(&tmp_plugin_ptr->mem_root, 4096, 4096);
...@@ -1210,7 +1209,6 @@ static void plugin_del(struct st_plugin_int *plugin) ...@@ -1210,7 +1209,6 @@ static void plugin_del(struct st_plugin_int *plugin)
if (plugin->plugin_dl) if (plugin->plugin_dl)
plugin_dl_del(&plugin->plugin_dl->dl); plugin_dl_del(&plugin->plugin_dl->dl);
plugin->state= PLUGIN_IS_FREED; plugin->state= PLUGIN_IS_FREED;
plugin_array_version++;
free_root(&plugin->mem_root, MYF(0)); free_root(&plugin->mem_root, MYF(0));
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
...@@ -1824,10 +1822,10 @@ static bool plugin_load_list(MEM_ROOT *tmp_root, const char *list) ...@@ -1824,10 +1822,10 @@ static bool plugin_load_list(MEM_ROOT *tmp_root, const char *list)
case '\0': case '\0':
list= NULL; /* terminate the loop */ list= NULL; /* terminate the loop */
/* fall through */ /* fall through */
case ';':
#ifndef __WIN__ #ifndef __WIN__
case ':': /* can't use this as delimiter as it may be drive letter */ case ':': /* can't use this as delimiter as it may be drive letter */
#endif #endif
case ';':
str->str[str->length]= '\0'; str->str[str->length]= '\0';
if (str == &name) // load all plugins in named module if (str == &name) // load all plugins in named module
{ {
...@@ -1865,6 +1863,7 @@ static bool plugin_load_list(MEM_ROOT *tmp_root, const char *list) ...@@ -1865,6 +1863,7 @@ static bool plugin_load_list(MEM_ROOT *tmp_root, const char *list)
str->str= p; str->str= p;
continue; continue;
} }
/* fall through */
default: default:
str->length++; str->length++;
continue; continue;
...@@ -2297,64 +2296,55 @@ bool mysql_uninstall_plugin(THD *thd, const LEX_STRING *name, ...@@ -2297,64 +2296,55 @@ bool mysql_uninstall_plugin(THD *thd, const LEX_STRING *name,
bool plugin_foreach_with_mask(THD *thd, plugin_foreach_func *func, bool plugin_foreach_with_mask(THD *thd, plugin_foreach_func *func,
int type, uint state_mask, void *arg) int type, uint state_mask, void *arg)
{ {
uint idx, total; uint idx, total= 0;
struct st_plugin_int *plugin, **plugins; struct st_plugin_int *plugin;
int version=plugin_array_version; plugin_ref *plugins;
my_bool res= FALSE;
DBUG_ENTER("plugin_foreach_with_mask"); DBUG_ENTER("plugin_foreach_with_mask");
if (!initialized) if (!initialized)
DBUG_RETURN(FALSE); DBUG_RETURN(FALSE);
state_mask= ~state_mask; // do it only once
mysql_mutex_lock(&LOCK_plugin); mysql_mutex_lock(&LOCK_plugin);
total= type == MYSQL_ANY_PLUGIN ? plugin_array.elements
: plugin_hash[type].records;
/* /*
Do the alloca out here in case we do have a working alloca: Do the alloca out here in case we do have a working alloca:
leaving the nested stack frame invalidates alloca allocation. leaving the nested stack frame invalidates alloca allocation.
*/ */
plugins=(struct st_plugin_int **)my_alloca(total*sizeof(plugin));
if (type == MYSQL_ANY_PLUGIN) if (type == MYSQL_ANY_PLUGIN)
{ {
for (idx= 0; idx < total; idx++) plugins= (plugin_ref*) my_alloca(plugin_array.elements * sizeof(plugin_ref));
for (idx= 0; idx < plugin_array.elements; idx++)
{ {
plugin= *dynamic_element(&plugin_array, idx, struct st_plugin_int **); plugin= *dynamic_element(&plugin_array, idx, struct st_plugin_int **);
plugins[idx]= !(plugin->state & state_mask) ? plugin : NULL; if ((plugins[total]= intern_plugin_lock(0, plugin_int_to_ref(plugin),
state_mask)))
total++;
} }
} }
else else
{ {
HASH *hash= plugin_hash + type; HASH *hash= plugin_hash + type;
for (idx= 0; idx < total; idx++) plugins= (plugin_ref*) my_alloca(hash->records * sizeof(plugin_ref));
for (idx= 0; idx < hash->records; idx++)
{ {
plugin= (struct st_plugin_int *) my_hash_element(hash, idx); plugin= (struct st_plugin_int *) my_hash_element(hash, idx);
plugins[idx]= !(plugin->state & state_mask) ? plugin : NULL; if ((plugins[total]= intern_plugin_lock(0, plugin_int_to_ref(plugin),
state_mask)))
total++;
} }
} }
mysql_mutex_unlock(&LOCK_plugin); mysql_mutex_unlock(&LOCK_plugin);
for (idx= 0; idx < total; idx++) for (idx= 0; idx < total; idx++)
{ {
if (unlikely(version != plugin_array_version))
{
mysql_mutex_lock(&LOCK_plugin);
for (uint i=idx; i < total; i++)
if (plugins[i] && plugins[i]->state & state_mask)
plugins[i]=0;
mysql_mutex_unlock(&LOCK_plugin);
}
plugin= plugins[idx];
/* It will stop iterating on first engine error when "func" returns TRUE */ /* It will stop iterating on first engine error when "func" returns TRUE */
if (plugin && func(thd, plugin_int_to_ref(plugin), arg)) if ((res= func(thd, plugins[idx], arg)))
goto err; break;
} }
plugin_unlock_list(0, plugins, total);
my_afree(plugins); my_afree(plugins);
DBUG_RETURN(FALSE); DBUG_RETURN(res);
err:
my_afree(plugins);
DBUG_RETURN(TRUE);
} }
...@@ -3958,4 +3948,3 @@ void add_plugin_options(DYNAMIC_ARRAY *options, MEM_ROOT *mem_root) ...@@ -3958,4 +3948,3 @@ void add_plugin_options(DYNAMIC_ARRAY *options, MEM_ROOT *mem_root)
insert_dynamic(options, (uchar*) opt); insert_dynamic(options, (uchar*) opt);
} }
} }
...@@ -1307,7 +1307,7 @@ static bool mysql_test_insert(Prepared_statement *stmt, ...@@ -1307,7 +1307,7 @@ static bool mysql_test_insert(Prepared_statement *stmt,
my_error(ER_WRONG_VALUE_COUNT_ON_ROW, MYF(0), counter); my_error(ER_WRONG_VALUE_COUNT_ON_ROW, MYF(0), counter);
goto error; goto error;
} }
if (setup_fields(thd, 0, *values, MARK_COLUMNS_NONE, 0, 0)) if (setup_fields(thd, 0, *values, MARK_COLUMNS_NONE, 0, NULL, 0))
goto error; goto error;
} }
} }
...@@ -1397,7 +1397,7 @@ static int mysql_test_update(Prepared_statement *stmt, ...@@ -1397,7 +1397,7 @@ static int mysql_test_update(Prepared_statement *stmt,
table_list->register_want_access(want_privilege); table_list->register_want_access(want_privilege);
#endif #endif
thd->lex->select_lex.no_wrap_view_item= TRUE; thd->lex->select_lex.no_wrap_view_item= TRUE;
res= setup_fields(thd, 0, select->item_list, MARK_COLUMNS_READ, 0, 0); res= setup_fields(thd, 0, select->item_list, MARK_COLUMNS_READ, 0, NULL, 0);
thd->lex->select_lex.no_wrap_view_item= FALSE; thd->lex->select_lex.no_wrap_view_item= FALSE;
if (res) if (res)
goto error; goto error;
...@@ -1408,7 +1408,8 @@ static int mysql_test_update(Prepared_statement *stmt, ...@@ -1408,7 +1408,8 @@ static int mysql_test_update(Prepared_statement *stmt,
(SELECT_ACL & ~table_list->table->grant.privilege); (SELECT_ACL & ~table_list->table->grant.privilege);
table_list->register_want_access(SELECT_ACL); table_list->register_want_access(SELECT_ACL);
#endif #endif
if (setup_fields(thd, 0, stmt->lex->value_list, MARK_COLUMNS_NONE, 0, 0) || if (setup_fields(thd, 0, stmt->lex->value_list, MARK_COLUMNS_NONE, 0, NULL,
0) ||
check_unique_table(thd, table_list)) check_unique_table(thd, table_list))
goto error; goto error;
/* TODO: here we should send types of placeholders to the client. */ /* TODO: here we should send types of placeholders to the client. */
...@@ -1575,7 +1576,7 @@ static bool mysql_test_do_fields(Prepared_statement *stmt, ...@@ -1575,7 +1576,7 @@ static bool mysql_test_do_fields(Prepared_statement *stmt,
if (open_normal_and_derived_tables(thd, tables, MYSQL_OPEN_FORCE_SHARED_MDL, if (open_normal_and_derived_tables(thd, tables, MYSQL_OPEN_FORCE_SHARED_MDL,
DT_PREPARE | DT_CREATE)) DT_PREPARE | DT_CREATE))
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
DBUG_RETURN(setup_fields(thd, 0, *values, MARK_COLUMNS_NONE, 0, 0)); DBUG_RETURN(setup_fields(thd, 0, *values, MARK_COLUMNS_NONE, 0, NULL, 0));
} }
...@@ -2074,6 +2075,7 @@ static bool check_prepared_statement(Prepared_statement *stmt) ...@@ -2074,6 +2075,7 @@ static bool check_prepared_statement(Prepared_statement *stmt)
if (res != 2) if (res != 2)
break; break;
/* fall through */
case SQLCOM_UPDATE_MULTI: case SQLCOM_UPDATE_MULTI:
res= mysql_test_multiupdate(stmt, tables, res == 2); res= mysql_test_multiupdate(stmt, tables, res == 2);
break; break;
......
...@@ -1139,6 +1139,7 @@ impossible position"; ...@@ -1139,6 +1139,7 @@ impossible position";
loop_breaker = (flags & BINLOG_DUMP_NON_BLOCK); loop_breaker = (flags & BINLOG_DUMP_NON_BLOCK);
break; break;
} }
/* fall through */
default: default:
errmsg = "could not find next log"; errmsg = "could not find next log";
my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG; my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG;
......
...@@ -724,7 +724,7 @@ JOIN::prepare(Item ***rref_pointer_array, ...@@ -724,7 +724,7 @@ JOIN::prepare(Item ***rref_pointer_array,
wild_num)) || wild_num)) ||
select_lex->setup_ref_array(thd, real_og_num) || select_lex->setup_ref_array(thd, real_og_num) ||
setup_fields(thd, (*rref_pointer_array), fields_list, MARK_COLUMNS_READ, setup_fields(thd, (*rref_pointer_array), fields_list, MARK_COLUMNS_READ,
&all_fields, 1) || &all_fields, &select_lex->pre_fix, 1) ||
setup_without_group(thd, (*rref_pointer_array), tables_list, setup_without_group(thd, (*rref_pointer_array), tables_list,
select_lex->leaf_tables, fields_list, select_lex->leaf_tables, fields_list,
all_fields, &conds, order, group_list, all_fields, &conds, order, group_list,
...@@ -13350,9 +13350,22 @@ simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top, ...@@ -13350,9 +13350,22 @@ simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top,
if (table->sj_on_expr && !in_sj) if (table->sj_on_expr && !in_sj)
{ {
/* /*
If this is a semi-join that is not contained within another semi-join, If this is a semi-join that is not contained within another semi-join
leave it intact (otherwise it is flattened) leave it intact (otherwise it is flattened)
*/ */
/*
Make sure that any semi-join appear in
the join->select_lex->sj_nests list only once
*/
List_iterator_fast<TABLE_LIST> sj_it(join->select_lex->sj_nests);
TABLE_LIST *sj_nest;
while ((sj_nest= sj_it++))
{
if (table == sj_nest)
break;
}
if (sj_nest)
continue;
join->select_lex->sj_nests.push_back(table); join->select_lex->sj_nests.push_back(table);
   
/* /*
......
...@@ -262,7 +262,7 @@ int fill_plugins(THD *thd, TABLE_LIST *tables, COND *cond) ...@@ -262,7 +262,7 @@ int fill_plugins(THD *thd, TABLE_LIST *tables, COND *cond)
TABLE *table= tables->table; TABLE *table= tables->table;
if (plugin_foreach_with_mask(thd, show_plugins, MYSQL_ANY_PLUGIN, if (plugin_foreach_with_mask(thd, show_plugins, MYSQL_ANY_PLUGIN,
~PLUGIN_IS_FREED, table)) ~(PLUGIN_IS_FREED | PLUGIN_IS_DYING), table))
DBUG_RETURN(1); DBUG_RETURN(1);
DBUG_RETURN(0); DBUG_RETURN(0);
...@@ -931,6 +931,7 @@ class Show_create_error_handler : public Internal_error_handler { ...@@ -931,6 +931,7 @@ class Show_create_error_handler : public Internal_error_handler {
is_handled= FALSE; is_handled= FALSE;
break; break;
} }
/* fall through */
case ER_COLUMNACCESS_DENIED_ERROR: case ER_COLUMNACCESS_DENIED_ERROR:
case ER_VIEW_NO_EXPLAIN: /* Error was anonymized, ignore all the same. */ case ER_VIEW_NO_EXPLAIN: /* Error was anonymized, ignore all the same. */
case ER_PROCACCESS_DENIED_ERROR: case ER_PROCACCESS_DENIED_ERROR:
...@@ -5294,7 +5295,8 @@ int fill_schema_engines(THD *thd, TABLE_LIST *tables, COND *cond) ...@@ -5294,7 +5295,8 @@ int fill_schema_engines(THD *thd, TABLE_LIST *tables, COND *cond)
DBUG_ENTER("fill_schema_engines"); DBUG_ENTER("fill_schema_engines");
if (plugin_foreach_with_mask(thd, iter_schema_engines, if (plugin_foreach_with_mask(thd, iter_schema_engines,
MYSQL_STORAGE_ENGINE_PLUGIN, MYSQL_STORAGE_ENGINE_PLUGIN,
~PLUGIN_IS_FREED, tables->table)) ~(PLUGIN_IS_FREED | PLUGIN_IS_DYING),
tables->table))
DBUG_RETURN(1); DBUG_RETURN(1);
DBUG_RETURN(0); DBUG_RETURN(0);
} }
...@@ -5716,6 +5718,10 @@ int fill_schema_proc(THD *thd, TABLE_LIST *tables, COND *cond) ...@@ -5716,6 +5718,10 @@ int fill_schema_proc(THD *thd, TABLE_LIST *tables, COND *cond)
DBUG_RETURN(1); DBUG_RETURN(1);
} }
/* Disable padding temporarily so it doesn't break the query */
ulonglong sql_mode_was = thd->variables.sql_mode;
thd->variables.sql_mode &= ~MODE_PAD_CHAR_TO_FULL_LENGTH;
if (proc_table->file->ha_index_init(0, 1)) if (proc_table->file->ha_index_init(0, 1))
{ {
res= 1; res= 1;
...@@ -5751,6 +5757,7 @@ int fill_schema_proc(THD *thd, TABLE_LIST *tables, COND *cond) ...@@ -5751,6 +5757,7 @@ int fill_schema_proc(THD *thd, TABLE_LIST *tables, COND *cond)
(void) proc_table->file->ha_index_end(); (void) proc_table->file->ha_index_end();
close_system_tables(thd, &open_tables_state_backup); close_system_tables(thd, &open_tables_state_backup);
thd->variables.sql_mode = sql_mode_was;
DBUG_RETURN(res); DBUG_RETURN(res);
} }
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment