From a02b81daeaa63c327bea9e6c24fe45b53dc0008e Mon Sep 17 00:00:00 2001 From: Monty Date: Tue, 26 Sep 2017 00:12:36 +0300 Subject: Moved autosetting of host_cache_size and back_log to proper place - Clean up formulas and comments for host_cache_size and back_log - Added test of autoset (for host_cache_size) - Marked open_files_limit as auto_set --- mysql-test/r/mysqld--help.result | 7 ++-- .../suite/sys_vars/r/host_cache_size_auto.result | 3 ++ .../sys_vars/r/sysvars_server_notembedded.result | 2 +- .../sys_vars/t/host_cache_size_auto-master.opt | 1 + .../suite/sys_vars/t/host_cache_size_auto.test | 1 + sql/mysqld.cc | 47 ++++++++++++++-------- sql/sys_vars.cc | 8 ++-- 7 files changed, 45 insertions(+), 24 deletions(-) create mode 100644 mysql-test/suite/sys_vars/r/host_cache_size_auto.result create mode 100644 mysql-test/suite/sys_vars/t/host_cache_size_auto-master.opt create mode 100644 mysql-test/suite/sys_vars/t/host_cache_size_auto.test diff --git a/mysql-test/r/mysqld--help.result b/mysql-test/r/mysqld--help.result index bcc985a8a50..7005a850ea5 100644 --- a/mysql-test/r/mysqld--help.result +++ b/mysql-test/r/mysqld--help.result @@ -569,9 +569,10 @@ The following options may be given as the first argument: --open-files-limit=# If this is not 0, then mysqld will use this value to reserve file descriptors to use with setrlimit(). If this - value is 0 then mysqld will reserve max_connections*5 or - max_connections + table_cache*2 (whichever is larger) - number of file descriptors + value is 0 or autoset then mysqld will reserve + max_connections*5 or max_connections + table_cache*2 + (whichever is larger) number of file descriptors + (Automatically configured unless set explicitly) --optimizer-prune-level=# Controls the heuristic(s) applied during query optimization to prune less-promising partial plans from diff --git a/mysql-test/suite/sys_vars/r/host_cache_size_auto.result b/mysql-test/suite/sys_vars/r/host_cache_size_auto.result new file mode 100644 index 00000000000..a9a683e017b --- /dev/null +++ b/mysql-test/suite/sys_vars/r/host_cache_size_auto.result @@ -0,0 +1,3 @@ +select @@global.host_cache_size; +@@global.host_cache_size +653 diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result index 8d68dce0245..329b519588d 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result @@ -5216,7 +5216,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME OPEN_FILES_LIMIT VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BIGINT UNSIGNED -VARIABLE_COMMENT If this is not 0, then mysqld will use this value to reserve file descriptors to use with setrlimit(). If this value is 0 then mysqld will reserve max_connections*5 or max_connections + table_cache*2 (whichever is larger) number of file descriptors +VARIABLE_COMMENT If this is not 0, then mysqld will use this value to reserve file descriptors to use with setrlimit(). If this value is 0 or autoset then mysqld will reserve max_connections*5 or max_connections + table_cache*2 (whichever is larger) number of file descriptors NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 NUMERIC_BLOCK_SIZE 1 diff --git a/mysql-test/suite/sys_vars/t/host_cache_size_auto-master.opt b/mysql-test/suite/sys_vars/t/host_cache_size_auto-master.opt new file mode 100644 index 00000000000..ae09e3f57ac --- /dev/null +++ b/mysql-test/suite/sys_vars/t/host_cache_size_auto-master.opt @@ -0,0 +1 @@ +--max_connections=1000 --open-files-limit=1000 --autoset-host-cache-size diff --git a/mysql-test/suite/sys_vars/t/host_cache_size_auto.test b/mysql-test/suite/sys_vars/t/host_cache_size_auto.test new file mode 100644 index 00000000000..35846713d70 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/host_cache_size_auto.test @@ -0,0 +1 @@ +select @@global.host_cache_size; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index f464ec807f6..e552d0b05a6 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4400,21 +4400,6 @@ static int init_common_variables() SYSVAR_AUTOSIZE(threadpool_size, my_getncpus()); #endif - /* Fix host_cache_size. */ - if (IS_SYSVAR_AUTOSIZE(&host_cache_size)) - { - if (max_connections <= 628 - 128) - SYSVAR_AUTOSIZE(host_cache_size, 128 + max_connections); - else if (max_connections <= ((ulong)(2000 - 628)) * 20 + 500) - SYSVAR_AUTOSIZE(host_cache_size, 628 + ((max_connections - 500) / 20)); - else - SYSVAR_AUTOSIZE(host_cache_size, 2000); - } - - /* Fix back_log (back_log == 0 added for MySQL compatibility) */ - if (back_log == 0 || IS_SYSVAR_AUTOSIZE(&back_log)) - SYSVAR_AUTOSIZE(back_log, MY_MIN(900, (50 + max_connections / 5))); - /* connections and databases needs lots of files */ { uint files, wanted_files, max_open_files; @@ -4439,7 +4424,7 @@ static int init_common_variables() if (files < wanted_files) { - if (!open_files_limit) + if (!open_files_limit || IS_SYSVAR_AUTOSIZE(&open_files_limit)) { /* If we have requested too much file handles than we bring @@ -4468,6 +4453,36 @@ static int init_common_variables() } SYSVAR_AUTOSIZE(open_files_limit, files); } + + /* + Max_connections is now set. + Now we can fix other variables depending on this variable. + */ + + /* Fix host_cache_size */ + if (IS_SYSVAR_AUTOSIZE(&host_cache_size)) + { + /* + The default value is 128. + The autoset value is 128, plus 1 for a value of max_connections + up to 500, plus 1 for every increment of 20 over 500 in the + max_connections value, capped at 2000. + */ + uint size= (HOST_CACHE_SIZE + MY_MIN(max_connections, 500) + + MY_MAX(((long) max_connections)-500,0)/20); + SYSVAR_AUTOSIZE(host_cache_size, size); + } + + /* Fix back_log (back_log == 0 added for MySQL compatibility) */ + if (back_log == 0 || IS_SYSVAR_AUTOSIZE(&back_log)) + { + /* + The default value is 150. + The autoset value is 50 + max_connections / 5 capped at 900 + */ + SYSVAR_AUTOSIZE(back_log, MY_MIN(900, (50 + max_connections / 5))); + } + unireg_init(opt_specialflag); /* Set up extern variabels */ if (!(my_default_lc_messages= my_locale_by_name(lc_messages))) diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 7405ca7e884..6f3ccfc9823 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -2311,10 +2311,10 @@ export sys_var *Sys_old_passwords_ptr= &Sys_old_passwords; // for sql_acl.cc static Sys_var_ulong Sys_open_files_limit( "open_files_limit", "If this is not 0, then mysqld will use this value to reserve file " - "descriptors to use with setrlimit(). If this value is 0 then mysqld " - "will reserve max_connections*5 or max_connections + table_cache*2 " - "(whichever is larger) number of file descriptors", - READ_ONLY GLOBAL_VAR(open_files_limit), CMD_LINE(REQUIRED_ARG), + "descriptors to use with setrlimit(). If this value is 0 or autoset " + "then mysqld will reserve max_connections*5 or max_connections + " + "table_cache*2 (whichever is larger) number of file descriptors", + AUTO_SET READ_ONLY GLOBAL_VAR(open_files_limit), CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, OS_FILE_LIMIT), DEFAULT(0), BLOCK_SIZE(1)); /// @todo change to enum -- cgit v1.2.1 From d387bc89ede0adf00d5940ee89004a412aebdf46 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Tue, 26 Sep 2017 08:03:08 +0400 Subject: MDEV-13907 compoind.test fails in build-bot for bb-10.2-ext --- sql/item.cc | 39 +++++++++++++++++++++++++++++++++++ sql/item.h | 27 +++++++++++++++++++++++- sql/sp_head.cc | 1 + sql/sql_class.h | 4 ++++ sql/sql_lex.cc | 59 ++++++++++++++++++++++------------------------------- sql/sql_lex.h | 57 +++++++++++++++++++-------------------------------- sql/sql_yacc.yy | 12 +++-------- sql/sql_yacc_ora.yy | 12 +++-------- 8 files changed, 121 insertions(+), 90 deletions(-) diff --git a/sql/item.cc b/sql/item.cc index 9dcc81bbae7..ce9f258612e 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1542,6 +1542,45 @@ bool mark_unsupported_function(const char *w1, const char *w2, return mark_unsupported_function(ptr, store, result); } + +Query_fragment::Query_fragment(THD *thd, sp_head *sphead, + const char *start, const char *end) +{ + DBUG_ASSERT(start <= end); + if (sphead) + { + if (sphead->m_tmp_query) + { + // Normal SP statement + DBUG_ASSERT(sphead->m_tmp_query <= start); + set(start - sphead->m_tmp_query, end - start); + } + else + { + /* + We're in the "if" expression of a compound query: + if (expr) + do_something; + end if; + sphead->m_tmp_query is not set yet at this point, because + the "if" part of such statements is never put into the binary log. + Values of Rewritable_query_parameter::pos_in_query and + Rewritable_query_parameter:len_in_query will not be important, + so setting both to 0 should be fine. + */ + set(0, 0); + } + } + else + { + // Non-SP statement + DBUG_ASSERT(thd->query() <= start); + DBUG_ASSERT(end <= thd->query_end()); + set(start - thd->query(), end - start); + } +} + + /***************************************************************************** Item_sp_variable methods *****************************************************************************/ diff --git a/sql/item.h b/sql/item.h index 04dad5265d3..13f6f2019e4 100644 --- a/sql/item.h +++ b/sql/item.h @@ -89,6 +89,7 @@ public: const char *dbug_print_item(Item *item); +class sp_head; class Protocol; struct TABLE_LIST; void item_init(void); /* Init item functions */ @@ -391,6 +392,31 @@ public: { return NULL; } }; + +/* + A helper class to calculate offset and length of a query fragment + - outside of SP + - inside an SP + - inside a compound block +*/ +class Query_fragment +{ + uint m_pos; + uint m_length; + void set(size_t pos, size_t length) + { + DBUG_ASSERT(pos < UINT_MAX32); + DBUG_ASSERT(length < UINT_MAX32); + m_pos= (uint) pos; + m_length= (uint) length; + } +public: + Query_fragment(THD *thd, sp_head *sphead, const char *start, const char *end); + uint pos() const { return m_pos; } + uint length() const { return m_length; } +}; + + /** This is used for items in the query that needs to be rewritten before binlogging @@ -2100,7 +2126,6 @@ public: Field_enumerator() {} /* Remove gcc warning */ }; -class sp_head; class Item_string; diff --git a/sql/sp_head.cc b/sql/sp_head.cc index b83195b8c71..faf208f549f 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -545,6 +545,7 @@ sp_head::sp_head(const Sp_handler *sph) Database_qualified_name(&null_clex_str, &null_clex_str), m_handler(sph), m_flags(0), + m_tmp_query(NULL), m_explicit_name(false), /* FIXME: the only use case when name is NULL is events, and it should diff --git a/sql/sql_class.h b/sql/sql_class.h index 1c4e657cf5a..8e87b3b41f9 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1069,6 +1069,10 @@ public: { return static_cast(query_string.length()); } + inline char *query_end() const + { + return query_string.str() + query_string.length(); + } CHARSET_INFO *query_charset() const { return query_string.charset(); } void set_query_inner(const CSET_STRING &string_arg) { diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 64b24ad7846..b080fb7f822 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -6287,15 +6287,17 @@ Item *LEX::create_and_link_Item_trigger_field(THD *thd, Item_param *LEX::add_placeholder(THD *thd, const LEX_CSTRING *name, - uint pos_in_query, uint len_in_query) + const char *start, const char *end) { if (!parsing_options.allows_variable) { my_error(ER_VIEW_SELECT_VARIABLE, MYF(0)); return NULL; } + + Query_fragment pos(thd, sphead, start, end); Item_param *item= new (thd->mem_root) Item_param(thd, name, - pos_in_query, len_in_query); + pos.pos(), pos.length()); if (!item || param_list.push_back(item, thd->mem_root)) { my_error(ER_OUT_OF_RESOURCES, MYF(0)); @@ -6305,12 +6307,6 @@ Item_param *LEX::add_placeholder(THD *thd, const LEX_CSTRING *name, } -const char *LEX::substatement_query(THD *thd) const -{ - return sphead ? sphead->m_tmp_query : thd->query(); -} - - bool LEX::add_signal_statement(THD *thd, const sp_condition_value *v) { Yacc_state *state= &thd->m_parser_state->m_yacc; @@ -6364,8 +6360,8 @@ Item_splocal *LEX::create_item_spvar_row_field(THD *thd, const LEX_CSTRING *a, const LEX_CSTRING *b, sp_variable *spv, - uint pos_in_q, - uint length_in_q) + const char *start, + const char *end) { if (!parsing_options.allows_variable) { @@ -6373,6 +6369,7 @@ Item_splocal *LEX::create_item_spvar_row_field(THD *thd, return NULL; } + Query_fragment pos(thd, sphead, start, end); Item_splocal *item; if (spv->field_def.is_table_rowtype_ref() || spv->field_def.is_cursor_rowtype_ref()) @@ -6380,7 +6377,7 @@ Item_splocal *LEX::create_item_spvar_row_field(THD *thd, if (!(item= new (thd->mem_root) Item_splocal_row_field_by_name(thd, a, b, spv->offset, MYSQL_TYPE_NULL, - pos_in_q, length_in_q))) + pos.pos(), pos.length()))) return NULL; } else @@ -6394,7 +6391,7 @@ Item_splocal *LEX::create_item_spvar_row_field(THD *thd, Item_splocal_row_field(thd, a, b, spv->offset, row_field_offset, def->real_field_type(), - pos_in_q, length_in_q))) + pos.pos(), pos.length()))) return NULL; } #ifndef DBUG_OFF @@ -6489,14 +6486,14 @@ Item *LEX::create_item_func_setval(THD *thd, Table_ident *table_ident, Item *LEX::create_item_ident(THD *thd, const LEX_CSTRING *a, const LEX_CSTRING *b, - uint pos_in_q, uint length_in_q) + const char *start, const char *end) { sp_variable *spv; if (spcont && (spv= spcont->find_variable(a, false)) && (spv->field_def.is_row() || spv->field_def.is_table_rowtype_ref() || spv->field_def.is_cursor_rowtype_ref())) - return create_item_spvar_row_field(thd, a, b, spv, pos_in_q, length_in_q); + return create_item_spvar_row_field(thd, a, b, spv, start, end); if ((thd->variables.sql_mode & MODE_ORACLE) && b->length == 7) { @@ -6550,7 +6547,7 @@ Item *LEX::create_item_ident(THD *thd, Item *LEX::create_item_limit(THD *thd, const LEX_CSTRING *a, - uint pos_in_q, uint length_in_q) + const char *start, const char *end) { sp_variable *spv; if (!spcont || !(spv= spcont->find_variable(a, false))) @@ -6559,10 +6556,11 @@ Item *LEX::create_item_limit(THD *thd, return NULL; } + Query_fragment pos(thd, sphead, start, end); Item_splocal *item; if (!(item= new (thd->mem_root) Item_splocal(thd, a, spv->offset, spv->sql_type(), - pos_in_q, length_in_q))) + pos.pos(), pos.length()))) return NULL; #ifndef DBUG_OFF item->m_sp= sphead; @@ -6582,7 +6580,7 @@ Item *LEX::create_item_limit(THD *thd, Item *LEX::create_item_limit(THD *thd, const LEX_CSTRING *a, const LEX_CSTRING *b, - uint pos_in_q, uint length_in_q) + const char *start, const char *end) { sp_variable *spv; if (!spcont || !(spv= spcont->find_variable(a, false))) @@ -6593,8 +6591,7 @@ Item *LEX::create_item_limit(THD *thd, // Qualified %TYPE variables are not possible DBUG_ASSERT(!spv->field_def.column_type_ref()); Item_splocal *item; - if (!(item= create_item_spvar_row_field(thd, a, b, spv, - pos_in_q, length_in_q))) + if (!(item= create_item_spvar_row_field(thd, a, b, spv, start, end))) return NULL; if (item->type() != Item::INT_ITEM) { @@ -6660,11 +6657,12 @@ Item *LEX::create_item_ident_nosp(THD *thd, LEX_CSTRING *name) Item *LEX::create_item_ident_sp(THD *thd, LEX_CSTRING *name, - uint start_in_q, - uint length_in_q) + const char *start, + const char *end) { sp_variable *spv; DBUG_ASSERT(spcont); + DBUG_ASSERT(sphead); if ((spv= spcont->find_variable(name, false))) { /* We're compiling a stored procedure and found a variable */ @@ -6674,17 +6672,18 @@ Item *LEX::create_item_ident_sp(THD *thd, LEX_CSTRING *name, return NULL; } + Query_fragment pos(thd, sphead, start, end); Item_splocal *splocal= spv->field_def.is_column_type_ref() ? new (thd->mem_root) Item_splocal_with_delayed_data_type(thd, name, spv->offset, - start_in_q, - length_in_q) : + pos.pos(), + pos.length()) : spv->field_def.is_row() || spv->field_def.is_table_rowtype_ref() ? new (thd->mem_root) Item_splocal_row(thd, name, spv->offset, - start_in_q, length_in_q) : + pos.pos(), pos.length()) : new (thd->mem_root) Item_splocal(thd, name, spv->offset, spv->sql_type(), - start_in_q, length_in_q); + pos.pos(), pos.length()); if (splocal == NULL) return NULL; #ifndef DBUG_OFF @@ -6705,16 +6704,6 @@ Item *LEX::create_item_ident_sp(THD *thd, LEX_CSTRING *name, } -Item *LEX::create_item_ident_sp(THD *thd, LEX_CSTRING *name, - const char *start_in_q, - const char *end_in_q) -{ - DBUG_ASSERT(sphead); - return create_item_ident_sp(thd, name, start_in_q - sphead->m_tmp_query, - end_in_q - start_in_q); -} - - /** Generate instructions for: SET x.y= expr; diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 38ce41e43dd..7be918f2c0b 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -2994,8 +2994,6 @@ public: void start(THD *thd); - const char *substatement_query(THD *thd) const; - inline bool is_ps_or_view_context_analysis() { return (context_analysis_only & @@ -3226,22 +3224,16 @@ public: bool sp_open_cursor(THD *thd, const LEX_CSTRING *name, List *parameters); Item_splocal *create_item_for_sp_var(LEX_CSTRING *name, sp_variable *spvar, - const char *start_in_q, - const char *end_in_q); + const char *start, const char *end); Item *create_item_ident_nosp(THD *thd, LEX_CSTRING *name); Item *create_item_ident_sp(THD *thd, LEX_CSTRING *name, - uint start_in_q, - uint length_in_q); - Item *create_item_ident_sp(THD *thd, LEX_CSTRING *name, - const char *start_in_q, - const char *end_in_q); + const char *start, const char *end); Item *create_item_ident(THD *thd, LEX_CSTRING *name, - const char *start_in_q, - const char *end_in_q) + const char *start, const char *end) { return sphead ? - create_item_ident_sp(thd, name, start_in_q, end_in_q) : + create_item_ident_sp(thd, name, start, end) : create_item_ident_nosp(thd, name); } @@ -3268,15 +3260,15 @@ public: @param field - the ROW variable field name @param spvar - the variable that was previously found by name using "var_name". - @pos_in_q - position in the query (for binary log) - @length_in_q - length in the query (for binary log) + @param start - position in the query (for binary log) + @param end - end in the query (for binary log) */ Item_splocal *create_item_spvar_row_field(THD *thd, const LEX_CSTRING *var, const LEX_CSTRING *field, sp_variable *spvar, - uint pos_in_q, - uint length_in_q); + const char *start, + const char *end); /* Create an item from its qualified name. Depending on context, it can be either a ROW variable field, @@ -3286,15 +3278,15 @@ public: @param thd - THD, for mem_root @param a - the first name @param b - the second name - @param pos_in_q - position in the query (for binary log) - @param length_in_q - length in the query (for binary log) + @param start - position in the query (for binary log) + @param end - end in the query (for binary log) @retval - NULL on error, or a pointer to a new Item. */ Item *create_item_ident(THD *thd, const LEX_CSTRING *a, const LEX_CSTRING *b, - uint pos_in_q, uint length_in_q); - + const char *start, + const char *end); /* Create an item from its qualified name. Depending on context, it can be a table field, a table field reference, @@ -3333,23 +3325,24 @@ public: Create an item for a name in LIMIT clause: LIMIT var @param THD - THD, for mem_root @param var_name - the variable name - @param pos_in_q - position in the query (for binary log) - @param length_in_q - length in the query (for binary log) + @param start - position in the query (for binary log) + @param end - end in the query (for binary log) @retval - a new Item corresponding to the SP variable, or NULL on error (non in SP, unknown variable, wrong data type). */ Item *create_item_limit(THD *thd, const LEX_CSTRING *var_name, - uint pos_in_q, uint length_in_q); + const char *start, + const char *end); /* Create an item for a qualified name in LIMIT clause: LIMIT var.field @param THD - THD, for mem_root @param var_name - the variable name @param field_name - the variable field name - @param pos_in_q - position in the query (for binary log) - @param length_in_q - length in the query (for binary log) + @param start - start in the query (for binary log) + @param end - end in the query (for binary log) @retval - a new Item corresponding to the SP variable, or NULL on error (non in SP, unknown variable, unknown ROW field, @@ -3358,7 +3351,8 @@ public: Item *create_item_limit(THD *thd, const LEX_CSTRING *var_name, const LEX_CSTRING *field_name, - uint pos_in_q, uint length_in_q); + const char *start, + const char *end); Item *make_item_func_replace(THD *thd, Item *org, Item *find, Item *replace); @@ -3441,16 +3435,7 @@ public: bool sp_push_goto_label(THD *thd, const LEX_CSTRING *label_name); Item_param *add_placeholder(THD *thd, const LEX_CSTRING *name, - uint pos_in_query, uint len_in_query); - Item_param *add_placeholder(THD *thd, const LEX_CSTRING *name, - const char *start, const char *end) - { - size_t pos= start - substatement_query(thd); - size_t len= end - start; - DBUG_ASSERT(pos < UINT_MAX32); - DBUG_ASSERT(len < UINT_MAX32); - return add_placeholder(thd, name, (uint) pos, (uint) len); - } + const char *start, const char *end); /* Integer range FOR LOOP methods */ sp_variable *sp_add_for_loop_variable(THD *thd, const LEX_CSTRING *name, diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 17d6f016b2c..24fee1548cb 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -11926,9 +11926,7 @@ limit_option: LEX *lex= thd->lex; Lex_input_stream *lip= & thd->m_parser_state->m_lip; if (!($$= lex->create_item_limit(thd, &$1, - $1.m_pos - - lex->substatement_query(thd), - lip->get_tok_end() - $1.m_pos))) + $1.m_pos, lip->get_tok_end()))) MYSQL_YYABORT; } | ident_with_tok_start '.' ident @@ -11936,9 +11934,7 @@ limit_option: LEX *lex= thd->lex; Lex_input_stream *lip= & thd->m_parser_state->m_lip; if (!($$= lex->create_item_limit(thd, &$1, &$3, - $1.m_pos - - lex->substatement_query(thd), - lip->get_ptr() - $1.m_pos))) + $1.m_pos, lip->get_ptr()))) MYSQL_YYABORT; } | param_marker @@ -14239,9 +14235,7 @@ simple_ident: { LEX *lex= thd->lex; if (!($$= lex->create_item_ident(thd, &$1, &$3, - $1.m_pos - - lex->substatement_query(thd), - YYLIP->get_tok_end() - $1.m_pos))) + $1.m_pos, YYLIP->get_tok_end()))) MYSQL_YYABORT; } ; diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy index 052c219a7a4..053c2625da1 100644 --- a/sql/sql_yacc_ora.yy +++ b/sql/sql_yacc_ora.yy @@ -11983,9 +11983,7 @@ limit_option: LEX *lex= thd->lex; Lex_input_stream *lip= & thd->m_parser_state->m_lip; if (!($$= lex->create_item_limit(thd, &$1, - $1.m_pos - - lex->substatement_query(thd), - lip->get_tok_end() - $1.m_pos))) + $1.m_pos, lip->get_tok_end()))) MYSQL_YYABORT; } | ident_with_tok_start '.' ident @@ -11993,9 +11991,7 @@ limit_option: LEX *lex= thd->lex; Lex_input_stream *lip= & thd->m_parser_state->m_lip; if (!($$= lex->create_item_limit(thd, &$1, &$3, - $1.m_pos - - lex->substatement_query(thd), - lip->get_ptr() - $1.m_pos))) + $1.m_pos, lip->get_ptr()))) MYSQL_YYABORT; } | param_marker @@ -14315,9 +14311,7 @@ simple_ident: { LEX *lex= thd->lex; if (!($$= lex->create_item_ident(thd, &$1, &$3, - $1.m_pos - - lex->substatement_query(thd), - YYLIP->get_tok_end() - $1.m_pos))) + $1.m_pos, YYLIP->get_tok_end()))) MYSQL_YYABORT; } ; -- cgit v1.2.1 From fd2c5d19d0f0eeb054d18d4455d3ad28dd680219 Mon Sep 17 00:00:00 2001 From: Eugene Kosov Date: Tue, 26 Sep 2017 15:35:34 +0300 Subject: fix a data race reapply 6192f0bffa798c01acc85db9f427ed02234aead4 TSAN warnings count decreased from 206 to 195 --- storage/innobase/sync/sync0debug.cc | 43 ++----------------------------------- 1 file changed, 2 insertions(+), 41 deletions(-) diff --git a/storage/innobase/sync/sync0debug.cc b/storage/innobase/sync/sync0debug.cc index c80ea6aef3e..fa7a99ea4c0 100644 --- a/storage/innobase/sync/sync0debug.cc +++ b/storage/innobase/sync/sync0debug.cc @@ -49,14 +49,7 @@ my_bool srv_sync_debug; /** The global mutex which protects debug info lists of all rw-locks. To modify the debug info list of an rw-lock, this mutex has to be acquired in addition to the mutex protecting the lock. */ -static ib_mutex_t rw_lock_debug_mutex; - -/** If deadlock detection does not get immediately the mutex, -it may wait for this event */ -static os_event_t rw_lock_debug_event; - -/** This is set to true, if there may be waiters for the event */ -static bool rw_lock_debug_waiters; +static SysMutex rw_lock_debug_mutex; /** The latch held by a thread */ struct Latched { @@ -1242,13 +1235,7 @@ void LatchDebug::init() UNIV_NOTHROW { - ut_a(rw_lock_debug_event == NULL); - mutex_create(LATCH_ID_RW_LOCK_DEBUG, &rw_lock_debug_mutex); - - rw_lock_debug_event = os_event_create("rw_lock_debug_event"); - - rw_lock_debug_waiters = FALSE; } /** Shutdown the latch debug checking @@ -1259,12 +1246,6 @@ void LatchDebug::shutdown() UNIV_NOTHROW { - ut_a(rw_lock_debug_event != NULL); - - os_event_destroy(rw_lock_debug_event); - - rw_lock_debug_event = NULL; - mutex_free(&rw_lock_debug_mutex); ut_a(s_initialized); @@ -1284,22 +1265,7 @@ mutex. */ void rw_lock_debug_mutex_enter() { - for (;;) { - - if (0 == mutex_enter_nowait(&rw_lock_debug_mutex)) { - return; - } - - os_event_reset(rw_lock_debug_event); - - rw_lock_debug_waiters = TRUE; - - if (0 == mutex_enter_nowait(&rw_lock_debug_mutex)) { - return; - } - - os_event_wait(rw_lock_debug_event); - } + mutex_enter(&rw_lock_debug_mutex); } /** Releases the debug mutex. */ @@ -1307,11 +1273,6 @@ void rw_lock_debug_mutex_exit() { mutex_exit(&rw_lock_debug_mutex); - - if (rw_lock_debug_waiters) { - rw_lock_debug_waiters = FALSE; - os_event_set(rw_lock_debug_event); - } } #endif /* UNIV_DEBUG */ -- cgit v1.2.1 From f44d5de689cb62fc96676571f72df050a1760b20 Mon Sep 17 00:00:00 2001 From: halfspawn Date: Wed, 27 Sep 2017 16:49:40 +0200 Subject: MDEV-13919 sql_mode=ORACLE: Derive length of VARCHAR SP parameters with no length from actual parameters --- mysql-test/suite/compat/oracle/r/sp-param.result | 86 ++++++++++++++++++++++++ mysql-test/suite/compat/oracle/t/sp-param.test | 82 ++++++++++++++++++++++ sql/sp_head.cc | 19 ++++-- sql/sp_head.h | 2 +- sql/sp_rcontext.cc | 25 ++++++- sql/sp_rcontext.h | 6 +- sql/sql_type.cc | 23 +++++++ sql/sql_type.h | 6 ++ sql/sql_yacc_ora.yy | 23 +++---- 9 files changed, 251 insertions(+), 21 deletions(-) diff --git a/mysql-test/suite/compat/oracle/r/sp-param.result b/mysql-test/suite/compat/oracle/r/sp-param.result index 4f4585c4570..15e1516efdb 100644 --- a/mysql-test/suite/compat/oracle/r/sp-param.result +++ b/mysql-test/suite/compat/oracle/r/sp-param.result @@ -130,3 +130,89 @@ t1 CREATE TABLE "t1" ( ) DROP TABLE t1; DROP FUNCTION f1; + +MDEV-13919 sql_mode=ORACLE: Derive length of VARCHAR SP parameters with no length from actual parameters + +set sql_mode= 'oracle,strict_trans_tables'; +CREATE OR REPLACE PROCEDURE p1(pinout INOUT varchar, pin IN varchar) +AS +BEGIN +pinout:=pin; +END; +/ +call p1(@w,'0123456789') +/ +declare w varchar(10); +begin +call p1(w,'0123456789'); +end; +/ +declare w varchar(5); +begin +call p1(w,'0123456789'); +end; +/ +ERROR 22001: Data too long for column 'pinout' at row 1 +declare w varchar(20); +begin +w:='aaa'; +call p1(w,'0123456789'); +end; +/ +declare w varchar(8); +begin +w:='aaa'; +call p1(w,'0123456789'); +end; +/ +ERROR 22001: Data too long for column 'pinout' at row 1 +declare str varchar(6000); +pout varchar(6000); +begin +str:=lpad('x',6000,'y'); +call p1(pout,str); +select length(pout); +end; +/ +length(pout) +6000 +declare str varchar(6000); +pout varchar(4000); +begin +str:=lpad('x',6000,'y'); +call p1(pout,str); +select length(pout); +end; +/ +ERROR 22001: Data too long for column 'pinout' at row 1 +declare str varchar(40000); +pout varchar(60000); +begin +str:=lpad('x',40000,'y'); +call p1(pout,str); +select length(pout); +end; +/ +length(pout) +40000 +declare str text(80000); +pout text(80000); +begin +str:=lpad('x',80000,'y'); +call p1(pout,str); +select length(pout); +end; +/ +ERROR 22001: Data too long for column 'pin' at row 1 +declare str text(80000); +pout text(80000); +begin +str:=lpad('x',60000,'y'); +call p1(pout,str); +select length(pout); +end; +/ +length(pout) +60000 +drop procedure p1 +/ diff --git a/mysql-test/suite/compat/oracle/t/sp-param.test b/mysql-test/suite/compat/oracle/t/sp-param.test index 23203317f50..0a6d7dec0fd 100644 --- a/mysql-test/suite/compat/oracle/t/sp-param.test +++ b/mysql-test/suite/compat/oracle/t/sp-param.test @@ -35,3 +35,85 @@ SET sql_mode=ORACLE; --let type = RAW --let length = 4000 --source sp-param.inc + +--echo +--echo MDEV-13919 sql_mode=ORACLE: Derive length of VARCHAR SP parameters with no length from actual parameters +--echo +set sql_mode= 'oracle,strict_trans_tables'; +delimiter /; +CREATE OR REPLACE PROCEDURE p1(pinout INOUT varchar, pin IN varchar) +AS +BEGIN + pinout:=pin; +END; +/ +call p1(@w,'0123456789') +/ +declare w varchar(10); +begin + call p1(w,'0123456789'); +end; +/ +--error ER_DATA_TOO_LONG +declare w varchar(5); +begin + call p1(w,'0123456789'); +end; +/ +declare w varchar(20); +begin + w:='aaa'; + call p1(w,'0123456789'); +end; +/ +--error ER_DATA_TOO_LONG +declare w varchar(8); +begin + w:='aaa'; + call p1(w,'0123456789'); +end; +/ +declare str varchar(6000); + pout varchar(6000); +begin + str:=lpad('x',6000,'y'); + call p1(pout,str); + select length(pout); +end; +/ +--error ER_DATA_TOO_LONG +declare str varchar(6000); + pout varchar(4000); +begin + str:=lpad('x',6000,'y'); + call p1(pout,str); + select length(pout); +end; +/ +declare str varchar(40000); + pout varchar(60000); +begin + str:=lpad('x',40000,'y'); + call p1(pout,str); + select length(pout); +end; +/ +--error ER_DATA_TOO_LONG +declare str text(80000); + pout text(80000); +begin + str:=lpad('x',80000,'y'); + call p1(pout,str); + select length(pout); +end; +/ +declare str text(80000); + pout text(80000); +begin + str:=lpad('x',60000,'y'); + call p1(pout,str); + select length(pout); +end; +/ +drop procedure p1 +/ diff --git a/sql/sp_head.cc b/sql/sp_head.cc index faf208f549f..72ce5d65a5d 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -1439,7 +1439,8 @@ bool sp_head::check_execute_access(THD *thd) const @retval NULL - error (access denided or EOM) @retval !NULL - success (the invoker has rights to all %TYPE tables) */ -sp_rcontext *sp_head::rcontext_create(THD *thd, Field *ret_value) +sp_rcontext *sp_head::rcontext_create(THD *thd, Field *ret_value, + List *args) { bool has_column_type_refs= m_flags & HAS_COLUMN_TYPE_REFS; #ifndef NO_EMBEDDED_ACCESS_CHECKS @@ -1449,7 +1450,7 @@ sp_rcontext *sp_head::rcontext_create(THD *thd, Field *ret_value) return NULL; #endif sp_rcontext *res= sp_rcontext::create(thd, m_pcont, ret_value, - has_column_type_refs); + has_column_type_refs, args); #ifndef NO_EMBEDDED_ACCESS_CHECKS if (has_column_type_refs) m_security_ctx.restore_security_context(thd, save_security_ctx); @@ -1556,7 +1557,7 @@ sp_head::execute_trigger(THD *thd, thd->set_n_backup_active_arena(&call_arena, &backup_arena); if (!(nctx= sp_rcontext::create(thd, m_pcont, NULL, - m_flags & HAS_COLUMN_TYPE_REFS))) + m_flags & HAS_COLUMN_TYPE_REFS, NULL))) { err_status= TRUE; goto err_with_cleanup; @@ -1637,6 +1638,7 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, MEM_ROOT call_mem_root; Query_arena call_arena(&call_mem_root, Query_arena::STMT_INITIALIZED_FOR_SP); Query_arena backup_arena; + List largs; DBUG_ENTER("sp_head::execute_function"); DBUG_PRINT("info", ("function %s", m_name.str)); @@ -1671,7 +1673,12 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, init_sql_alloc(&call_mem_root, MEM_ROOT_BLOCK_SIZE, 0, MYF(0)); thd->set_n_backup_active_arena(&call_arena, &backup_arena); - if (!(nctx= rcontext_create(thd, return_value_fld))) + for (uint i= 0 ; i < argcount ; i++) + { + largs.push_back(argp[i]); + } + + if (!(nctx= rcontext_create(thd, return_value_fld, &largs))) { thd->restore_active_arena(&call_arena, &backup_arena); err_status= TRUE; @@ -1886,7 +1893,7 @@ sp_head::execute_procedure(THD *thd, List *args) if (! octx) { /* Create a temporary old context. */ - if (!(octx= rcontext_create(thd, NULL))) + if (!(octx= rcontext_create(thd, NULL, args))) { DBUG_PRINT("error", ("Could not create octx")); DBUG_RETURN(TRUE); @@ -1901,7 +1908,7 @@ sp_head::execute_procedure(THD *thd, List *args) thd->spcont->callers_arena= thd; } - if (!(nctx= rcontext_create(thd, NULL))) + if (!(nctx= rcontext_create(thd, NULL, args))) { delete nctx; /* Delete nctx if it was init() that failed. */ thd->spcont= save_spcont; diff --git a/sql/sp_head.h b/sql/sp_head.h index 207d41f74fd..2f4f21a76f4 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -215,7 +215,7 @@ public: m_sp_cache_version= version_arg; } - sp_rcontext *rcontext_create(THD *thd, Field *retval); + sp_rcontext *rcontext_create(THD *thd, Field *retval, List *args); private: /** diff --git a/sql/sp_rcontext.cc b/sql/sp_rcontext.cc index a684265ee66..3413a76e8c7 100644 --- a/sql/sp_rcontext.cc +++ b/sql/sp_rcontext.cc @@ -63,7 +63,8 @@ sp_rcontext::~sp_rcontext() sp_rcontext *sp_rcontext::create(THD *thd, const sp_pcontext *root_parsing_ctx, Field *return_value_fld, - bool resolve_type_refs) + bool resolve_type_refs, + List *args) { sp_rcontext *ctx= new (thd->mem_root) sp_rcontext(root_parsing_ctx, return_value_fld, @@ -75,6 +76,10 @@ sp_rcontext *sp_rcontext::create(THD *thd, List field_def_lst; ctx->m_root_parsing_ctx->retrieve_field_definitions(&field_def_lst); + if (args && + ctx->adjust_formal_params_to_actual_params(thd, field_def_lst, args)) + return NULL; + if (ctx->alloc_arrays(thd) || (resolve_type_refs && ctx->resolve_type_refs(thd, field_def_lst)) || ctx->init_var_table(thd, field_def_lst) || @@ -88,6 +93,24 @@ sp_rcontext *sp_rcontext::create(THD *thd, } +bool sp_rcontext::adjust_formal_params_to_actual_params(THD *thd, + List &field_def_lst, + List *args) +{ + List_iterator it(field_def_lst); + List_iterator it_args(*args); + DBUG_ASSERT(field_def_lst.elements >= args->elements ); + Spvar_definition *def; + Item *arg; + while ((def= it++) && (arg= it_args++)) + { + if (def->type_handler()->adjust_spparam_type(def, arg)) + true; + } + return false; +} + + bool sp_rcontext::alloc_arrays(THD *thd) { { diff --git a/sql/sp_rcontext.h b/sql/sp_rcontext.h index 98464518787..39635d47029 100644 --- a/sql/sp_rcontext.h +++ b/sql/sp_rcontext.h @@ -71,7 +71,8 @@ public: static sp_rcontext *create(THD *thd, const sp_pcontext *root_parsing_ctx, Field *return_value_fld, - bool resolve_type_refs); + bool resolve_type_refs, + List *args); ~sp_rcontext(); @@ -344,6 +345,9 @@ private: Qualified_column_ident *ref); bool resolve_table_rowtype_ref(THD *thd, Row_definition_list &defs, Table_ident *ref); + bool adjust_formal_params_to_actual_params(THD *thd, + List &field_def_lst, + List *args); /// Create and initialize an Item-adapter (Item_field) for each SP-var field. /// diff --git a/sql/sql_type.cc b/sql/sql_type.cc index d9b3d53465e..339d24ebeb6 100644 --- a/sql/sql_type.cc +++ b/sql/sql_type.cc @@ -2384,6 +2384,29 @@ Field *Type_handler_set::make_table_field(const LEX_CSTRING *name, attr.collation); } +/* + If length is not specified for a varchar parameter, set length to the + maximum length of the actual argument. Goals are: + - avoid to allocate too much unused memory for m_var_table + - allow length check inside the callee rather than during copy of + returned values in output variables. + - allow varchar parameter size greater than 4000 + Default length has been stored in "decimal" member during parse. +*/ +bool Type_handler_varchar::adjust_spparam_type(Spvar_definition *def, + Item *from) const +{ + if (def->decimals) + { + uint def_max_char_length= MAX_FIELD_VARCHARLENGTH / def->charset->mbmaxlen; + uint arg_max_length= from->max_char_length(); + set_if_smaller(arg_max_length, def_max_char_length); + def->length= arg_max_length > 0 ? arg_max_length : def->decimals; + def->create_length_to_internal_length_string(); + } + return false; +} + /*************************************************************************/ uint32 Type_handler_decimal_result::max_display_length(const Item *item) const diff --git a/sql/sql_type.h b/sql/sql_type.h index 528ba005850..57737662c48 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -65,6 +65,7 @@ class in_vector; class Type_handler_hybrid_field_type; class Sort_param; class Arg_comparator; +class Spvar_definition; struct st_value; class Protocol; class handler; @@ -688,6 +689,10 @@ public: type_handler_adjusted_to_max_octet_length(uint max_octet_length, CHARSET_INFO *cs) const { return this; } + virtual bool adjust_spparam_type(Spvar_definition *def, Item *from) const + { + return false; + } virtual ~Type_handler() {} /** Determines MariaDB traditional data types that always present @@ -2523,6 +2528,7 @@ public: const Record_addr &addr, const Type_all_attributes &attr, TABLE *table) const; + bool adjust_spparam_type(Spvar_definition *def, Item *from) const; }; diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy index 053c2625da1..bc3302c49d3 100644 --- a/sql/sql_yacc_ora.yy +++ b/sql/sql_yacc_ora.yy @@ -1054,8 +1054,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %type field_length opt_field_length opt_field_length_default_1 - opt_field_length_default_sp_param_varchar - opt_field_length_default_sp_param_char %type text_string hex_or_bin_String opt_gconcat_separator @@ -1219,6 +1217,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %type cast_type cast_type_numeric cast_type_temporal %type precision opt_precision float_options + opt_field_length_default_sp_param_varchar + opt_field_length_default_sp_param_char %type keyword keyword_sp keyword_directly_assignable @@ -6549,9 +6549,11 @@ opt_field_length_default_1: /* - In sql_mode=ORACLE, a VARCHAR with no length is used - in SP parameters and return values and it's translated to VARCHAR(4000), - where 4000 is the maximum possible size for VARCHAR. + In sql_mode=ORACLE, real size of VARCHAR and CHAR with no length + in SP parameters is fixed at runtime with the length of real args. + Let's translate VARCHAR to VARCHAR(4000) for return value. + + Since Oracle 9, maximum size for VARCHAR in PL/SQL is 32767. In MariaDB the limit for VARCHAR is 65535 bytes. We could translate VARCHAR with no length to VARCHAR(65535), but @@ -6562,17 +6564,14 @@ opt_field_length_default_1: the maximum possible length in characters in case of mbmaxlen=4 (e.g. utf32, utf16, utf8mb4). However, we'll have character sets with mbmaxlen=5 soon (e.g. gb18030). - - Let's translate VARCHAR to VARCHAR(4000), which covert all possible Oracle - values. */ opt_field_length_default_sp_param_varchar: - /* empty */ { $$= (char*) "4000"; } - | field_length { $$= $1; } + /* empty */ { $$.set("4000", "4000"); } + | field_length { $$.set($1, NULL); } opt_field_length_default_sp_param_char: - /* empty */ { $$= (char*) "2000"; } - | field_length { $$= $1; } + /* empty */ { $$.set("2000", "2000"); } + | field_length { $$.set($1, NULL); } opt_precision: /* empty */ { $$.set(0, 0); } -- cgit v1.2.1 From c6e8d66e594a5409dfbd204a3184d1115977435f Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Wed, 27 Sep 2017 17:55:48 +0000 Subject: Fix buildbot error on windows. Update.rdiff fle Also, introduce my_popen()/my_fgets() wrapper function for popen()/fgets() in mysqltest to workaround a popen() bug in Windows C runtime, mentioned in MDEV-9409 This workaround was used previously for "exec". From now on, it is also used are used also for "perl" snippets. --- client/mysqltest.cc | 97 ++++++++++++++++++++++--------------- mysql-test/r/mysqld--help,win.rdiff | 27 +++++------ 2 files changed, 69 insertions(+), 55 deletions(-) diff --git a/client/mysqltest.cc b/client/mysqltest.cc index 05113f02a44..6e844ce1799 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -836,6 +836,47 @@ void revert_properties(); static void handle_no_active_connection(struct st_command* command, struct st_connection *cn, DYNAMIC_STRING *ds); + +/* Wrapper for fgets.Strips \r off newlines on Windows. + Should be used with together with my_popen(). +*/ +static char *my_fgets(char * s, int n, FILE * stream, int *len) +{ + char *buf = fgets(s, n, stream); + if (!buf) + { + *len= 0; + return buf; + } + + *len = (int)strlen(buf); +#ifdef _WIN32 + /* Strip '\r' off newlines. */ + if (*len > 1 && buf[*len - 2] == '\r' && buf[*len - 1] == '\n') + { + buf[*len - 2]= '\n'; + buf[*len - 1]= 0; + (*len)--; + } +#endif + return buf; +} + +/* + Wrapper for popen(). + On Windows, uses binary mode to workaround + C runtime bug mentioned in MDEV-9409 +*/ +static FILE* my_popen(const char *cmd, const char *mode) +{ + FILE *f= popen(cmd, mode); +#ifdef _WIN32 + if (f) + _setmode(fileno(f), O_BINARY); +#endif + return f; +} + #ifdef EMBEDDED_LIBRARY #define EMB_SEND_QUERY 1 @@ -1785,19 +1826,20 @@ static int run_command(char* cmd, DBUG_ENTER("run_command"); DBUG_PRINT("enter", ("cmd: %s", cmd)); - if (!(res_file= popen(cmd, "r"))) + if (!(res_file= my_popen(cmd, "r"))) { report_or_die("popen(\"%s\", \"r\") failed", cmd); DBUG_RETURN(-1); } - while (fgets(buf, sizeof(buf), res_file)) + int len; + while (my_fgets(buf, sizeof(buf), res_file, &len)) { DBUG_PRINT("info", ("buf: %s", buf)); if(ds_res) { /* Save the output of this command in the supplied string */ - dynstr_append(ds_res, buf); + dynstr_append_mem(ds_res, buf,len); } else { @@ -1886,14 +1928,15 @@ static int diff_check(const char *diff_name) my_snprintf(buf, sizeof(buf), "%s -v", diff_name); - if (!(res_file= popen(buf, "r"))) + if (!(res_file= my_popen(buf, "r"))) die("popen(\"%s\", \"r\") failed", buf); /* if diff is not present, nothing will be in stdout to increment have_diff */ - if (fgets(buf, sizeof(buf), res_file)) + int len; + if (my_fgets(buf, sizeof(buf), res_file, &len)) have_diff= 1; pclose(res_file); @@ -3246,18 +3289,6 @@ void free_tmp_sh_file() #endif -FILE* my_popen(DYNAMIC_STRING *ds_cmd, const char *mode) -{ -#if defined _WIN32 && defined USE_CYGWIN - /* Dump the command into a sh script file and execute with popen */ - str_to_file(tmp_sh_name, ds_cmd->str, ds_cmd->length); - return popen(tmp_sh_cmd, mode); -#else - return popen(ds_cmd->str, mode); -#endif -} - - static void init_builtin_echo(void) { #ifdef _WIN32 @@ -3392,7 +3423,7 @@ void do_exec(struct st_command *command) DBUG_PRINT("info", ("Executing '%s' as '%s'", command->first_argument, ds_cmd.str)); - if (!(res_file= my_popen(&ds_cmd, "r"))) + if (!(res_file= my_popen(ds_cmd.str, "r"))) { dynstr_free(&ds_cmd); if (command->abort_on_error) @@ -3406,24 +3437,9 @@ void do_exec(struct st_command *command) init_dynamic_string(&ds_sorted, "", 1024, 1024); ds_result= &ds_sorted; } - -#ifdef _WIN32 - /* Workaround for CRT bug, MDEV-9409 */ - _setmode(fileno(res_file), O_BINARY); -#endif - - while (fgets(buf, sizeof(buf), res_file)) + int len; + while (my_fgets(buf, sizeof(buf), res_file,&len)) { - int len = (int)strlen(buf); -#ifdef _WIN32 - /* Strip '\r' off newlines. */ - if (len > 1 && buf[len-2] == '\r' && buf[len-1] == '\n') - { - buf[len-2] = '\n'; - buf[len-1] = 0; - len--; - } -#endif replace_dynstr_append_mem(ds_result, buf, len); } error= pclose(res_file); @@ -4685,7 +4701,7 @@ void do_perl(struct st_command *command) /* Format the "perl " command */ my_snprintf(buf, sizeof(buf), "perl %s", temp_file_path); - if (!(res_file= popen(buf, "r"))) + if (!(res_file= my_popen(buf, "r"))) { if (command->abort_on_error) die("popen(\"%s\", \"r\") failed", buf); @@ -4693,16 +4709,17 @@ void do_perl(struct st_command *command) DBUG_VOID_RETURN; } - while (fgets(buf, sizeof(buf), res_file)) + int len; + while (my_fgets(buf, sizeof(buf), res_file,&len)) { if (disable_result_log) { - buf[strlen(buf)-1]=0; - DBUG_PRINT("exec_result",("%s", buf)); + buf[len - 1] = 0; + DBUG_PRINT("exec_result", ("%s", buf)); } else { - replace_dynstr_append(&ds_res, buf); + replace_dynstr_append_mem(&ds_res, buf, len); } } error= pclose(res_file); diff --git a/mysql-test/r/mysqld--help,win.rdiff b/mysql-test/r/mysqld--help,win.rdiff index 4e46a9da285..ac0f75b94eb 100644 --- a/mysql-test/r/mysqld--help,win.rdiff +++ b/mysql-test/r/mysqld--help,win.rdiff @@ -16,7 +16,7 @@ --net-buffer-length=# Buffer length for TCP/IP and socket communication --net-read-timeout=# -@@ -956,6 +956,9 @@ +@@ -957,6 +957,9 @@ characteristics (isolation level, read only/read write,snapshot - but not any work done / data modified within the transaction). @@ -26,7 +26,7 @@ --show-slave-auth-info Show user and password in SHOW SLAVE HOSTS on this master. -@@ -1068,6 +1071,10 @@ +@@ -1069,6 +1072,10 @@ Log slow queries to given log file. Defaults logging to 'hostname'-slow.log. Must be enabled to activate other slow log options @@ -37,7 +37,7 @@ --socket=name Socket file to use for connection --sort-buffer-size=# Each thread that needs to do a sort allocates a buffer of -@@ -1086,6 +1093,7 @@ +@@ -1087,6 +1094,7 @@ NO_ENGINE_SUBSTITUTION, PAD_CHAR_TO_FULL_LENGTH --stack-trace Print a symbolic stack trace on failure (Defaults to on; use --skip-stack-trace to disable.) @@ -45,22 +45,19 @@ --standard-compliant-cte Allow only CTEs compliant to SQL standard (Defaults to on; use --skip-standard-compliant-cte to disable.) -@@ -1134,8 +1142,12 @@ +@@ -1135,6 +1143,11 @@ --thread-pool-max-threads=# Maximum allowed number of worker threads in the thread pool -- --thread-pool-oversubscribe=# -- How many additional active worker threads in a group are + --thread-pool-min-threads=# + Minimum number of threads in the thread pool. + --thread-pool-mode=name + Chose implementation of the threadpool. One of: windows, + generic -+ --thread-pool-oversubscribe=# How many additional active worker threads in a group are + --thread-pool-oversubscribe=# + How many additional active worker threads in a group are allowed. - --thread-pool-prio-kickup-timer=# - The number of milliseconds before a dequeued low-priority -@@ -1172,8 +1184,8 @@ +@@ -1173,8 +1186,8 @@ automatically convert it to an on-disk MyISAM or Aria table. -t, --tmpdir=name Path for temporary files. Several paths may be specified, @@ -71,7 +68,7 @@ --transaction-alloc-block-size=# Allocation block size for transactions to be stored in binary log -@@ -1298,7 +1310,6 @@ +@@ -1299,7 +1312,6 @@ key-cache-division-limit 100 key-cache-file-hash-size 512 key-cache-segments 0 @@ -79,7 +76,7 @@ lc-messages en_US lc-messages-dir MYSQL_SHAREDIR/ lc-time-names en_US -@@ -1368,6 +1379,7 @@ +@@ -1369,6 +1381,7 @@ myisam-stats-method NULLS_UNEQUAL myisam-use-mmap FALSE mysql56-temporal-format TRUE @@ -87,7 +84,7 @@ net-buffer-length 16384 net-read-timeout 30 net-retry-count 10 -@@ -1469,6 +1481,8 @@ +@@ -1470,6 +1483,8 @@ session-track-state-change FALSE session-track-system-variables session-track-transaction-info OFF @@ -96,7 +93,7 @@ show-slave-auth-info FALSE silent-startup FALSE skip-grant-tables TRUE -@@ -1493,6 +1507,7 @@ +@@ -1494,6 +1509,7 @@ slave-type-conversions slow-launch-time 2 slow-query-log FALSE @@ -104,7 +101,7 @@ sort-buffer-size 2097152 sql-mode STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION stack-trace TRUE -@@ -1506,14 +1521,16 @@ +@@ -1507,14 +1523,16 @@ sync-relay-log 10000 sync-relay-log-info 10000 sysdate-is-now FALSE -- cgit v1.2.1 From 2fdbe150329f3aea7514648ca838ef59113a0bd6 Mon Sep 17 00:00:00 2001 From: Monty Date: Wed, 27 Sep 2017 22:19:26 +0300 Subject: Correct test output after variable comment change --- mysql-test/suite/sys_vars/r/sysvars_server_embedded,32bit.rdiff | 2 +- mysql-test/suite/sys_vars/r/sysvars_server_embedded.result | 2 +- mysql-test/suite/sys_vars/r/sysvars_server_notembedded,32bit.rdiff | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_embedded,32bit.rdiff b/mysql-test/suite/sys_vars/r/sysvars_server_embedded,32bit.rdiff index 9f2748037dd..6c94f747005 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_embedded,32bit.rdiff +++ b/mysql-test/suite/sys_vars/r/sysvars_server_embedded,32bit.rdiff @@ -1237,7 +1237,7 @@ VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE BIGINT UNSIGNED +VARIABLE_TYPE INT UNSIGNED - VARIABLE_COMMENT If this is not 0, then mysqld will use this value to reserve file descriptors to use with setrlimit(). If this value is 0 then mysqld will reserve max_connections*5 or max_connections + table_cache*2 (whichever is larger) number of file descriptors + VARIABLE_COMMENT If this is not 0, then mysqld will use this value to reserve file descriptors to use with setrlimit(). If this value is 0 or autoset then mysqld will reserve max_connections*5 or max_connections + table_cache*2 (whichever is larger) number of file descriptors NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 @@ -4346,7 +4346,7 @@ diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result index 7767ef18be2..537446fdb1e 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result @@ -4334,7 +4334,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME OPEN_FILES_LIMIT VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BIGINT UNSIGNED -VARIABLE_COMMENT If this is not 0, then mysqld will use this value to reserve file descriptors to use with setrlimit(). If this value is 0 then mysqld will reserve max_connections*5 or max_connections + table_cache*2 (whichever is larger) number of file descriptors +VARIABLE_COMMENT If this is not 0, then mysqld will use this value to reserve file descriptors to use with setrlimit(). If this value is 0 or autoset then mysqld will reserve max_connections*5 or max_connections + table_cache*2 (whichever is larger) number of file descriptors NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 NUMERIC_BLOCK_SIZE 1 diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded,32bit.rdiff b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded,32bit.rdiff index 272ddb59beb..200b9283618 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded,32bit.rdiff +++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded,32bit.rdiff @@ -1291,7 +1291,7 @@ VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE BIGINT UNSIGNED +VARIABLE_TYPE INT UNSIGNED - VARIABLE_COMMENT If this is not 0, then mysqld will use this value to reserve file descriptors to use with setrlimit(). If this value is 0 then mysqld will reserve max_connections*5 or max_connections + table_cache*2 (whichever is larger) number of file descriptors + VARIABLE_COMMENT If this is not 0, then mysqld will use this value to reserve file descriptors to use with setrlimit(). If this value is 0 or autoset then mysqld will reserve max_connections*5 or max_connections + table_cache*2 (whichever is larger) number of file descriptors NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 @@ -5228,7 +5228,7 @@ -- cgit v1.2.1 From 06f7a7620fd74cbf17b4759eca481961a9943d14 Mon Sep 17 00:00:00 2001 From: Monty Date: Tue, 26 Sep 2017 21:51:10 +0300 Subject: Fixed compiler warning --- storage/maria/ma_create.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/storage/maria/ma_create.c b/storage/maria/ma_create.c index 2eb635b880e..ca2ce0ebe61 100644 --- a/storage/maria/ma_create.c +++ b/storage/maria/ma_create.c @@ -57,7 +57,7 @@ int maria_create(const char *name, enum data_file_type datafile_type, char kfilename[FN_REFLEN], klinkname[FN_REFLEN], *klinkname_ptr; char dfilename[FN_REFLEN], dlinkname[FN_REFLEN], *dlinkname_ptr; ulong pack_reclength; - ulonglong tot_length,max_rows, tmp; + ulonglong tot_length,max_rows, tmp, tot_length_part; enum en_fieldtype type; enum data_file_type org_datafile_type= datafile_type; MARIA_SHARE share; @@ -664,10 +664,10 @@ int maria_create(const char *name, enum data_file_type datafile_type, if (tot_length == ULLONG_MAX) continue; - ulonglong tot_length_part= (max_rows/(ulong) (((uint) maria_block_size - - MAX_KEYPAGE_HEADER_SIZE - - KEYPAGE_CHECKSUM_SIZE)/ - (length*2))); + tot_length_part= (max_rows/(ulong) (((uint) maria_block_size - + MAX_KEYPAGE_HEADER_SIZE - + KEYPAGE_CHECKSUM_SIZE)/ + (length*2))); if (tot_length_part >= (ULLONG_MAX / maria_block_size + ULLONG_MAX % maria_block_size)) tot_length= ULLONG_MAX; -- cgit v1.2.1 From 8d006b9b124555298063d94d1473c9c881f2db1f Mon Sep 17 00:00:00 2001 From: Daniel Bartholomew Date: Wed, 27 Sep 2017 18:25:32 -0400 Subject: bump the VERSION --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index b816ecbfe54..49f5a7357e1 100644 --- a/VERSION +++ b/VERSION @@ -1,3 +1,3 @@ MYSQL_VERSION_MAJOR=10 MYSQL_VERSION_MINOR=2 -MYSQL_VERSION_PATCH=9 +MYSQL_VERSION_PATCH=10 -- cgit v1.2.1 From c9a01420cfecb62bce216bd187894fd6aa670a14 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Thu, 28 Sep 2017 11:05:27 +0400 Subject: Additional tests for MDEV-13919 sql_mode=ORACLE: Derive length of VARCHAR... --- mysql-test/suite/compat/oracle/r/sp-param.result | 186 +++++++++++++++++++ mysql-test/suite/compat/oracle/t/sp-param.test | 225 +++++++++++++++++++++++ sql/sp_head.cc | 2 - sql/sql_type.cc | 2 + 4 files changed, 413 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/compat/oracle/r/sp-param.result b/mysql-test/suite/compat/oracle/r/sp-param.result index 15e1516efdb..301c0f09fc5 100644 --- a/mysql-test/suite/compat/oracle/r/sp-param.result +++ b/mysql-test/suite/compat/oracle/r/sp-param.result @@ -216,3 +216,189 @@ length(pout) 60000 drop procedure p1 / +SET sql_mode=ORACLE; +CREATE PROCEDURE p1(pinout INOUT varchar, pin IN varchar) +AS +BEGIN +pinout:=pin; +END; +/ +CREATE PROCEDURE p2(len INT) +AS +pinout VARCHAR(10); +pin VARCHAR(30); +BEGIN +pin:= REPEAT('x', len); +p1(pinout, pin); +SELECT LENGTH(pinout); +END; +/ +CALL p2(10); +LENGTH(pinout) +10 +CALL p2(11); +LENGTH(pinout) +10 +Warnings: +Warning 1265 Data truncated for column 'pinout' at row 1 +DROP PROCEDURE p1; +DROP PROCEDURE p2; +SET sql_mode=ORACLE; +CREATE FUNCTION f1(pin VARCHAR, padlen INT) RETURN TEXT +AS +BEGIN +pin:=LPAD(pin, padlen); +RETURN pin; +END; +/ +CREATE PROCEDURE p2(padlen INT) AS +str TEXT :='x'; +BEGIN +SELECT LENGTH(f1(str,padlen)); +END; +/ +CALL p2(65535); +LENGTH(f1(str,padlen)) +65535 +CALL p2(65536); +LENGTH(f1(str,padlen)) +65535 +Warnings: +Warning 1265 Data truncated for column 'pin' at row 1 +DROP PROCEDURE p2; +DROP FUNCTION f1; +SET sql_mode='ORACLE,STRICT_TRANS_TABLES'; +CREATE PROCEDURE p1(pinout INOUT VARCHAR CHARACTER SET utf8, +pin IN VARCHAR CHARACTER SET utf8) +AS +BEGIN +pinout:=pin; +END; +/ +CREATE PROCEDURE p2(padlen INT) AS +str VARCHAR(40000) CHARACTER SET latin1; +pout VARCHAR(60000) CHARACTER SET latin1; +BEGIN +str:=lpad('x',padlen,'y'); +p1(pout,str); +SELECT length(pout); +END; +/ +CALL p2(21844); +length(pout) +21844 +CALL p2(21845); +length(pout) +21845 +CALL p2(21846); +ERROR 22001: Data too long for column 'pin' at row 1 +DROP PROCEDURE p2; +DROP PROCEDURE p1; +SET sql_mode='ORACLE,STRICT_TRANS_TABLES'; +CREATE PROCEDURE p1(pinout INOUT VARCHAR CHARACTER SET utf8, +pin IN VARCHAR CHARACTER SET utf8) +AS +BEGIN +pinout:=pin; +END; +/ +CREATE PROCEDURE p2(padlen INT) AS +str TEXT CHARACTER SET utf8; +pout TEXT CHARACTER SET utf8; +BEGIN +str:=lpad('x',padlen,'y'); +p1(pout,str); +SELECT length(pout); +END; +/ +CALL p2(21845); +length(pout) +21845 +CALL p2(21846); +ERROR 22001: Data too long for column 'pin' at row 1 +DROP PROCEDURE p2; +DROP PROCEDURE p1; +SET sql_mode='ORACLE,STRICT_TRANS_TABLES'; +CREATE FUNCTION f1(pin VARCHAR CHARACTER SET latin1, padlen INT) RETURN TEXT +AS +BEGIN +pin:=LPAD(pin, padlen); +RETURN pin; +END; +/ +CREATE PROCEDURE p2(padlen INT) AS +str TEXT CHARACTER SET latin1 :='x'; +BEGIN +SELECT LENGTH(f1(str,padlen)); +END; +/ +CALL p2(65535); +LENGTH(f1(str,padlen)) +65535 +CALL p2(65536); +ERROR 22001: Data too long for column 'pin' at row 1 +DROP PROCEDURE p2; +DROP FUNCTION f1; +SET sql_mode='ORACLE,STRICT_TRANS_TABLES'; +CREATE FUNCTION f1(pin VARCHAR CHARACTER SET utf8, padlen INT) RETURN TEXT +AS +BEGIN +pin:=LPAD(pin, padlen); +RETURN pin; +END; +/ +CREATE PROCEDURE p2(padlen INT) AS +str TEXT CHARACTER SET utf8 := 'x'; +BEGIN +SELECT LENGTH(f1(str,padlen)); +END; +/ +CALL p2(21845); +LENGTH(f1(str,padlen)) +21845 +CALL p2(21846); +ERROR 22001: Data too long for column 'pin' at row 1 +DROP PROCEDURE p2; +DROP FUNCTION f1; +SET sql_mode='ORACLE,STRICT_TRANS_TABLES'; +CREATE FUNCTION f1(pin VARCHAR CHARACTER SET utf8, padlen INT) RETURN TEXT +AS +BEGIN +pin:=LPAD(pin, padlen); +RETURN pin; +END; +/ +CREATE PROCEDURE p2(padlen INT) AS +str TEXT CHARACTER SET latin1 := 'x'; +BEGIN +SELECT LENGTH(f1(str,padlen)); +END; +/ +CALL p2(21845); +LENGTH(f1(str,padlen)) +21845 +CALL p2(21846); +ERROR 22001: Data too long for column 'pin' at row 1 +DROP PROCEDURE p2; +DROP FUNCTION f1; +SET sql_mode='ORACLE,STRICT_TRANS_TABLES'; +CREATE FUNCTION f1(pin VARCHAR CHARACTER SET latin1, padlen INT) RETURN TEXT +AS +BEGIN +pin:=LPAD(pin, padlen); +RETURN pin; +END; +/ +CREATE PROCEDURE p2(padlen INT) AS +str TEXT CHARACTER SET utf8 := 'x'; +BEGIN +SELECT LENGTH(f1(str,padlen)); +END; +/ +CALL p2(65535); +LENGTH(f1(str,padlen)) +65535 +CALL p2(65536); +ERROR 22001: Data too long for column 'pin' at row 1 +DROP PROCEDURE p2; +DROP FUNCTION f1; diff --git a/mysql-test/suite/compat/oracle/t/sp-param.test b/mysql-test/suite/compat/oracle/t/sp-param.test index 0a6d7dec0fd..769aeca93d4 100644 --- a/mysql-test/suite/compat/oracle/t/sp-param.test +++ b/mysql-test/suite/compat/oracle/t/sp-param.test @@ -117,3 +117,228 @@ end; / drop procedure p1 / +DELIMITER ;/ + + +# +# Procedure, non-strict mode +# + +SET sql_mode=ORACLE; +DELIMITER /; +CREATE PROCEDURE p1(pinout INOUT varchar, pin IN varchar) +AS +BEGIN + pinout:=pin; +END; +/ +CREATE PROCEDURE p2(len INT) +AS + pinout VARCHAR(10); + pin VARCHAR(30); +BEGIN + pin:= REPEAT('x', len); + p1(pinout, pin); + SELECT LENGTH(pinout); +END; +/ +DELIMITER ;/ +CALL p2(10); +CALL p2(11); +DROP PROCEDURE p1; +DROP PROCEDURE p2; + + +# +# Function, not-strict mode +# + +SET sql_mode=ORACLE; +DELIMITER /; +CREATE FUNCTION f1(pin VARCHAR, padlen INT) RETURN TEXT +AS +BEGIN + pin:=LPAD(pin, padlen); + RETURN pin; +END; +/ +CREATE PROCEDURE p2(padlen INT) AS + str TEXT :='x'; +BEGIN + SELECT LENGTH(f1(str,padlen)); +END; +/ +DELIMITER ;/ +CALL p2(65535); +CALL p2(65536); +DROP PROCEDURE p2; +DROP FUNCTION f1; + + +# +# Procedure, utf8 formal parameter, latin actual parameter +# + +SET sql_mode='ORACLE,STRICT_TRANS_TABLES'; +DELIMITER /; +CREATE PROCEDURE p1(pinout INOUT VARCHAR CHARACTER SET utf8, + pin IN VARCHAR CHARACTER SET utf8) +AS +BEGIN + pinout:=pin; +END; +/ +CREATE PROCEDURE p2(padlen INT) AS + str VARCHAR(40000) CHARACTER SET latin1; + pout VARCHAR(60000) CHARACTER SET latin1; +BEGIN + str:=lpad('x',padlen,'y'); + p1(pout,str); + SELECT length(pout); +END; +/ +DELIMITER ;/ +CALL p2(21844); +CALL p2(21845); +--error ER_DATA_TOO_LONG +CALL p2(21846); +DROP PROCEDURE p2; +DROP PROCEDURE p1; + + +# +# Procedure, utf8 formal parameter, utf8 actual parameter +# + +SET sql_mode='ORACLE,STRICT_TRANS_TABLES'; +DELIMITER /; +CREATE PROCEDURE p1(pinout INOUT VARCHAR CHARACTER SET utf8, + pin IN VARCHAR CHARACTER SET utf8) +AS +BEGIN + pinout:=pin; +END; +/ +CREATE PROCEDURE p2(padlen INT) AS + str TEXT CHARACTER SET utf8; + pout TEXT CHARACTER SET utf8; +BEGIN + str:=lpad('x',padlen,'y'); + p1(pout,str); + SELECT length(pout); +END; +/ +DELIMITER ;/ +CALL p2(21845); +--error ER_DATA_TOO_LONG +CALL p2(21846); +DROP PROCEDURE p2; +DROP PROCEDURE p1; + + +# +# Function, latin1 formal parameter, latin1 actual parameter +# + +SET sql_mode='ORACLE,STRICT_TRANS_TABLES'; +DELIMITER /; +CREATE FUNCTION f1(pin VARCHAR CHARACTER SET latin1, padlen INT) RETURN TEXT +AS +BEGIN + pin:=LPAD(pin, padlen); + RETURN pin; +END; +/ +CREATE PROCEDURE p2(padlen INT) AS + str TEXT CHARACTER SET latin1 :='x'; +BEGIN + SELECT LENGTH(f1(str,padlen)); +END; +/ +DELIMITER ;/ +CALL p2(65535); +--error ER_DATA_TOO_LONG +CALL p2(65536); +DROP PROCEDURE p2; +DROP FUNCTION f1; + + +# +# Function, utf8 formal parameter, utf8 actual parameter +# + +SET sql_mode='ORACLE,STRICT_TRANS_TABLES'; +DELIMITER /; +CREATE FUNCTION f1(pin VARCHAR CHARACTER SET utf8, padlen INT) RETURN TEXT +AS +BEGIN + pin:=LPAD(pin, padlen); + RETURN pin; +END; +/ +CREATE PROCEDURE p2(padlen INT) AS + str TEXT CHARACTER SET utf8 := 'x'; +BEGIN + SELECT LENGTH(f1(str,padlen)); +END; +/ +DELIMITER ;/ +CALL p2(21845); +--error ER_DATA_TOO_LONG +CALL p2(21846); +DROP PROCEDURE p2; +DROP FUNCTION f1; + + +# +# Function, utf8 formal parameter, latin1 actual parameter +# + +SET sql_mode='ORACLE,STRICT_TRANS_TABLES'; +DELIMITER /; +CREATE FUNCTION f1(pin VARCHAR CHARACTER SET utf8, padlen INT) RETURN TEXT +AS +BEGIN + pin:=LPAD(pin, padlen); + RETURN pin; +END; +/ +CREATE PROCEDURE p2(padlen INT) AS + str TEXT CHARACTER SET latin1 := 'x'; +BEGIN + SELECT LENGTH(f1(str,padlen)); +END; +/ +DELIMITER ;/ +CALL p2(21845); +--error ER_DATA_TOO_LONG +CALL p2(21846); +DROP PROCEDURE p2; +DROP FUNCTION f1; + + +# +# Function, latin1 formal parameter, utf8 actual parameter +# + +SET sql_mode='ORACLE,STRICT_TRANS_TABLES'; +DELIMITER /; +CREATE FUNCTION f1(pin VARCHAR CHARACTER SET latin1, padlen INT) RETURN TEXT +AS +BEGIN + pin:=LPAD(pin, padlen); + RETURN pin; +END; +/ +CREATE PROCEDURE p2(padlen INT) AS + str TEXT CHARACTER SET utf8 := 'x'; +BEGIN + SELECT LENGTH(f1(str,padlen)); +END; +/ +DELIMITER ;/ +CALL p2(65535); +--error ER_DATA_TOO_LONG +CALL p2(65536); +DROP PROCEDURE p2; +DROP FUNCTION f1; diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 72ce5d65a5d..16688a4ae63 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -1674,9 +1674,7 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, thd->set_n_backup_active_arena(&call_arena, &backup_arena); for (uint i= 0 ; i < argcount ; i++) - { largs.push_back(argp[i]); - } if (!(nctx= rcontext_create(thd, return_value_fld, &largs))) { diff --git a/sql/sql_type.cc b/sql/sql_type.cc index 339d24ebeb6..737d01f7b89 100644 --- a/sql/sql_type.cc +++ b/sql/sql_type.cc @@ -2384,6 +2384,8 @@ Field *Type_handler_set::make_table_field(const LEX_CSTRING *name, attr.collation); } +/*************************************************************************/ + /* If length is not specified for a varchar parameter, set length to the maximum length of the actual argument. Goals are: -- cgit v1.2.1 From 5a0cd753be0d48022db257ddcc7327341b12c1af Mon Sep 17 00:00:00 2001 From: Monty Date: Thu, 28 Sep 2017 11:59:28 +0300 Subject: Added missing test if table is transactional or not in Aria - The line was accidently removed by dd8474b1dc556d0ea9491d1908a2d1237818e8c1 - The effect of the missing test was just a few extra malloc when creating internal temporary tables. Nothing critical, but better got get fixed. --- storage/maria/ma_open.c | 1 + 1 file changed, 1 insertion(+) diff --git a/storage/maria/ma_open.c b/storage/maria/ma_open.c index 5c5e41be1f8..c1fdd52357f 100644 --- a/storage/maria/ma_open.c +++ b/storage/maria/ma_open.c @@ -918,6 +918,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) if (internal_table) set_if_smaller(share->base.max_data_file_length, max_data_file_length); + if (share->now_transactional) { /* Setup initial state that is visible for all */ MARIA_STATE_HISTORY_CLOSED *history; -- cgit v1.2.1 From de7c2e5e545df90fc9814c60a8a5a8d20f22b2c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 28 Sep 2017 15:12:00 +0300 Subject: Avoid implicit conversion from unsigned to signed --- storage/innobase/page/page0page.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/innobase/page/page0page.cc b/storage/innobase/page/page0page.cc index fcc77aeb591..fb528843da6 100644 --- a/storage/innobase/page/page0page.cc +++ b/storage/innobase/page/page0page.cc @@ -1569,7 +1569,7 @@ page_dir_balance_slot( /* The last directory slot cannot be balanced with the upper neighbor, as there is none. */ - if (UNIV_UNLIKELY(slot_no == page_dir_get_n_slots(page) - 1)) { + if (UNIV_UNLIKELY(slot_no + 1 == page_dir_get_n_slots(page))) { return; } -- cgit v1.2.1 From 3a6d94428f71171a88f1e7324952c1abbda00295 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Thu, 28 Sep 2017 17:00:42 +0400 Subject: Fixing a warning introduced by MDEV-13919 ("true" instread of "return true") --- sql/sp_rcontext.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sp_rcontext.cc b/sql/sp_rcontext.cc index 3413a76e8c7..9fca1d37c1d 100644 --- a/sql/sp_rcontext.cc +++ b/sql/sp_rcontext.cc @@ -105,7 +105,7 @@ bool sp_rcontext::adjust_formal_params_to_actual_params(THD *thd, while ((def= it++) && (arg= it_args++)) { if (def->type_handler()->adjust_spparam_type(def, arg)) - true; + return true; } return false; } -- cgit v1.2.1 From 596baeb1bfb812ad9b458eba0f6ea7d9bcdf4671 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Thu, 28 Sep 2017 17:26:23 +0400 Subject: A cleanup for MDEV-10577 and MDEV-13919: moving a few sp_rcontext methods Moving a few methods from sp_rcontext to different classes: - Table_ident::resolve_table_rowtype_ref - Qualified_column_ident::resolve_type_ref - Row_definition_list::resolve_table_rowtype_ref - Row_definition_list::adjust_formal_params_to_actual_params It easier to reuse these methods this way in the future. --- sql/field.h | 2 ++ sql/sp_rcontext.cc | 43 ++++++++++++++++++++----------------------- sql/sp_rcontext.h | 9 --------- sql/sql_class.h | 2 ++ 4 files changed, 24 insertions(+), 32 deletions(-) diff --git a/sql/field.h b/sql/field.h index f36e9a668c4..32ff75042e0 100644 --- a/sql/field.h +++ b/sql/field.h @@ -4095,6 +4095,8 @@ public: } return 0; } + bool adjust_formal_params_to_actual_params(THD *thd, List *args); + bool resolve_type_refs(THD *); }; diff --git a/sql/sp_rcontext.cc b/sql/sp_rcontext.cc index 9fca1d37c1d..e82947835f0 100644 --- a/sql/sp_rcontext.cc +++ b/sql/sp_rcontext.cc @@ -73,15 +73,15 @@ sp_rcontext *sp_rcontext::create(THD *thd, if (!ctx) return NULL; - List field_def_lst; + Row_definition_list field_def_lst; ctx->m_root_parsing_ctx->retrieve_field_definitions(&field_def_lst); if (args && - ctx->adjust_formal_params_to_actual_params(thd, field_def_lst, args)) + field_def_lst.adjust_formal_params_to_actual_params(thd, args)) return NULL; if (ctx->alloc_arrays(thd) || - (resolve_type_refs && ctx->resolve_type_refs(thd, field_def_lst)) || + (resolve_type_refs && field_def_lst.resolve_type_refs(thd)) || ctx->init_var_table(thd, field_def_lst) || ctx->init_var_items(thd, field_def_lst)) { @@ -93,13 +93,12 @@ sp_rcontext *sp_rcontext::create(THD *thd, } -bool sp_rcontext::adjust_formal_params_to_actual_params(THD *thd, - List &field_def_lst, - List *args) +bool Row_definition_list:: + adjust_formal_params_to_actual_params(THD *thd, List *args) { - List_iterator it(field_def_lst); + List_iterator it(*this); List_iterator it_args(*args); - DBUG_ASSERT(field_def_lst.elements >= args->elements ); + DBUG_ASSERT(elements >= args->elements ); Spvar_definition *def; Item *arg; while ((def= it++) && (arg= it_args++)) @@ -169,8 +168,7 @@ check_column_grant_for_type_ref(THD *thd, TABLE_LIST *table_list, /** This method implementation is very close to fill_schema_table_by_open(). */ -bool sp_rcontext::resolve_type_ref(THD *thd, Column_definition *def, - Qualified_column_ident *ref) +bool Qualified_column_ident::resolve_type_ref(THD *thd, Column_definition *def) { Open_tables_backup open_tables_state_backup; thd->reset_n_backup_open_tables_state(&open_tables_state_backup); @@ -187,18 +185,18 @@ bool sp_rcontext::resolve_type_ref(THD *thd, Column_definition *def, // Make %TYPE variables see temporary tables that shadow permanent tables thd->temporary_tables= open_tables_state_backup.temporary_tables; - if ((table_list= lex.select_lex.add_table_to_list(thd, ref, NULL, 0, + if ((table_list= lex.select_lex.add_table_to_list(thd, this, NULL, 0, TL_READ_NO_INSERT, MDL_SHARED_READ)) && !check_table_access(thd, SELECT_ACL, table_list, TRUE, UINT_MAX, FALSE) && !open_tables_only_view_structure(thd, table_list, thd->mdl_context.has_locks())) { - if ((src= lex.query_tables->table->find_field_by_name(&ref->m_column))) + if ((src= lex.query_tables->table->find_field_by_name(&m_column))) { if (!(rc= check_column_grant_for_type_ref(thd, table_list, - ref->m_column.str, - ref->m_column.length))) + m_column.str, + m_column.length))) { *def= Column_definition(thd, src, NULL/*No defaults,no constraints*/); def->flags&= (uint) ~NOT_NULL_FLAG; @@ -206,7 +204,7 @@ bool sp_rcontext::resolve_type_ref(THD *thd, Column_definition *def, } } else - my_error(ER_BAD_FIELD_ERROR, MYF(0), ref->m_column.str, ref->table.str); + my_error(ER_BAD_FIELD_ERROR, MYF(0), m_column.str, table.str); } lex.unit.cleanup(); @@ -223,9 +221,8 @@ bool sp_rcontext::resolve_type_ref(THD *thd, Column_definition *def, rec t1%ROWTYPE; It opens the table "t1" and copies its structure to %ROWTYPE variable. */ -bool sp_rcontext::resolve_table_rowtype_ref(THD *thd, - Row_definition_list &defs, - Table_ident *ref) +bool Table_ident::resolve_table_rowtype_ref(THD *thd, + Row_definition_list &defs) { Open_tables_backup open_tables_state_backup; thd->reset_n_backup_open_tables_state(&open_tables_state_backup); @@ -246,7 +243,7 @@ bool sp_rcontext::resolve_table_rowtype_ref(THD *thd, // Make %ROWTYPE variables see temporary tables that shadow permanent tables thd->temporary_tables= open_tables_state_backup.temporary_tables; - if ((table_list= lex.select_lex.add_table_to_list(thd, ref, NULL, 0, + if ((table_list= lex.select_lex.add_table_to_list(thd, this, NULL, 0, TL_READ_NO_INSERT, MDL_SHARED_READ)) && !check_table_access(thd, SELECT_ACL, table_list, TRUE, UINT_MAX, FALSE) && @@ -284,14 +281,14 @@ bool sp_rcontext::resolve_table_rowtype_ref(THD *thd, } -bool sp_rcontext::resolve_type_refs(THD *thd, List &defs) +bool Row_definition_list::resolve_type_refs(THD *thd) { - List_iterator it(defs); + List_iterator it(*this); Spvar_definition *def; while ((def= it++)) { if (def->is_column_type_ref() && - resolve_type_ref(thd, def, def->column_type_ref())) + def->column_type_ref()->resolve_type_ref(thd, def)) return true; } return false; @@ -323,7 +320,7 @@ bool sp_rcontext::init_var_items(THD *thd, Row_definition_list defs; Item_field_row *item= new (thd->mem_root) Item_field_row(thd, field); if (!(m_var_items[idx]= item) || - resolve_table_rowtype_ref(thd, defs, def->table_rowtype_ref()) || + def->table_rowtype_ref()->resolve_table_rowtype_ref(thd, defs) || item->row_create_items(thd, &defs)) return true; } diff --git a/sql/sp_rcontext.h b/sql/sp_rcontext.h index 39635d47029..2638aad03bf 100644 --- a/sql/sp_rcontext.h +++ b/sql/sp_rcontext.h @@ -340,15 +340,6 @@ private: /// @retval true on error. bool init_var_table(THD *thd, List &defs); - bool resolve_type_refs(THD *, List &defs); - bool resolve_type_ref(THD *thd, Column_definition *def, - Qualified_column_ident *ref); - bool resolve_table_rowtype_ref(THD *thd, Row_definition_list &defs, - Table_ident *ref); - bool adjust_formal_params_to_actual_params(THD *thd, - List &field_def_lst, - List *args); - /// Create and initialize an Item-adapter (Item_field) for each SP-var field. /// /// param thd Thread handle. diff --git a/sql/sql_class.h b/sql/sql_class.h index 8e87b3b41f9..a957bb67726 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -5496,6 +5496,7 @@ public: { db= *db_name; } + bool resolve_table_rowtype_ref(THD *thd, Row_definition_list &defs); }; @@ -5519,6 +5520,7 @@ public: :Table_ident(thd, db, table, false), m_column(*column) { } + bool resolve_type_ref(THD *thd, Column_definition *def); }; -- cgit v1.2.1 From 139441d0a0e7964898f33659429c22e33bd20dda Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Thu, 28 Sep 2017 17:48:33 +0400 Subject: A cleanup for MDEV-13919 sql_mode=ORACLE: Derive length of VARCHAR SP param... The intent of this patch is to avoid copying arguments from a pair "Item **args, uint arg_count" to List in sp_head::execute_function(). If the number of a stored function parameters is huge, such copying can affect performance. Change: 1. Adding a new method Row_definition_list::adjust_formal_params_to_actual_params, which accepts a pair of "Item **, uint". 2. Modifying the code to use the new method: - the calls for sp_rcontext::retrieve_field_definitions() and Row_definition_list::adjust_formal_params_to_actual_params() have been moved from sp_rcontext::create() to sp_head::rcontext_create(), to handle different argument notations easier (Item** vs List). - sp_rcontext::create() now assumes that the passed Row_definition_list is already adjusted to the actual SP parameters, and all "TYPE OF" and "ROWTYPE OF" references are resolved. 3. Removing creation of List in sp_head::execute_procedure(), using the code with "Item**, uint" notation instead. 4. Improvement of the code for MDEV-10577: As a good side effect, this patch gets rid of double security context switch inside sp_head::execute_trigger(): sp_rcontext is created when the context is already switched, so the second context switch inside sp_head::rcontext_create() was redundant. This is solved by adding a "bool switch_secutiry_ctx" parameter to rcontext_create(), so now execute_function() and execute_procedure() pass "true", while execute_trigger() passes "false". --- sql/field.h | 2 ++ sql/sp_head.cc | 51 +++++++++++++++++++++++++++++++++++++-------------- sql/sp_head.h | 6 +++++- sql/sp_rcontext.cc | 28 +++++++++++++++++----------- sql/sp_rcontext.h | 3 +-- 5 files changed, 62 insertions(+), 28 deletions(-) diff --git a/sql/field.h b/sql/field.h index 32ff75042e0..548445eb1fa 100644 --- a/sql/field.h +++ b/sql/field.h @@ -4096,6 +4096,8 @@ public: return 0; } bool adjust_formal_params_to_actual_params(THD *thd, List *args); + bool adjust_formal_params_to_actual_params(THD *thd, + Item **args, uint arg_count); bool resolve_type_refs(THD *); }; diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 16688a4ae63..c797d172e5d 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -1427,7 +1427,7 @@ bool sp_head::check_execute_access(THD *thd) const /** - Create rcontext using the routine security. + Create rcontext optionally using the routine security. This is important for sql_mode=ORACLE to make sure that the invoker has access to the tables mentioned in the %TYPE references. @@ -1440,25 +1440,51 @@ bool sp_head::check_execute_access(THD *thd) const @retval !NULL - success (the invoker has rights to all %TYPE tables) */ sp_rcontext *sp_head::rcontext_create(THD *thd, Field *ret_value, - List *args) + Row_definition_list *defs, + bool switch_security_ctx) { - bool has_column_type_refs= m_flags & HAS_COLUMN_TYPE_REFS; + if (!(m_flags & HAS_COLUMN_TYPE_REFS)) + return sp_rcontext::create(thd, m_pcont, ret_value, *defs); + sp_rcontext *res= NULL; #ifndef NO_EMBEDDED_ACCESS_CHECKS Security_context *save_security_ctx; - if (has_column_type_refs && + if (switch_security_ctx && set_routine_security_ctx(thd, this, &save_security_ctx)) return NULL; #endif - sp_rcontext *res= sp_rcontext::create(thd, m_pcont, ret_value, - has_column_type_refs, args); + if (!defs->resolve_type_refs(thd)) + res= sp_rcontext::create(thd, m_pcont, ret_value, *defs); #ifndef NO_EMBEDDED_ACCESS_CHECKS - if (has_column_type_refs) + if (switch_security_ctx) m_security_ctx.restore_security_context(thd, save_security_ctx); #endif return res; } +sp_rcontext *sp_head::rcontext_create(THD *thd, Field *ret_value, + List *args) +{ + DBUG_ASSERT(args); + Row_definition_list defs; + m_pcont->retrieve_field_definitions(&defs); + if (defs.adjust_formal_params_to_actual_params(thd, args)) + return NULL; + return rcontext_create(thd, ret_value, &defs, true); +} + + +sp_rcontext *sp_head::rcontext_create(THD *thd, Field *ret_value, + Item **args, uint arg_count) +{ + Row_definition_list defs; + m_pcont->retrieve_field_definitions(&defs); + if (defs.adjust_formal_params_to_actual_params(thd, args, arg_count)) + return NULL; + return rcontext_create(thd, ret_value, &defs, true); +} + + /** Execute trigger stored program. @@ -1556,8 +1582,9 @@ sp_head::execute_trigger(THD *thd, init_sql_alloc(&call_mem_root, MEM_ROOT_BLOCK_SIZE, 0, MYF(0)); thd->set_n_backup_active_arena(&call_arena, &backup_arena); - if (!(nctx= sp_rcontext::create(thd, m_pcont, NULL, - m_flags & HAS_COLUMN_TYPE_REFS, NULL))) + Row_definition_list defs; + m_pcont->retrieve_field_definitions(&defs); + if (!(nctx= rcontext_create(thd, NULL, &defs, false))) { err_status= TRUE; goto err_with_cleanup; @@ -1638,7 +1665,6 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, MEM_ROOT call_mem_root; Query_arena call_arena(&call_mem_root, Query_arena::STMT_INITIALIZED_FOR_SP); Query_arena backup_arena; - List largs; DBUG_ENTER("sp_head::execute_function"); DBUG_PRINT("info", ("function %s", m_name.str)); @@ -1673,10 +1699,7 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, init_sql_alloc(&call_mem_root, MEM_ROOT_BLOCK_SIZE, 0, MYF(0)); thd->set_n_backup_active_arena(&call_arena, &backup_arena); - for (uint i= 0 ; i < argcount ; i++) - largs.push_back(argp[i]); - - if (!(nctx= rcontext_create(thd, return_value_fld, &largs))) + if (!(nctx= rcontext_create(thd, return_value_fld, argp, argcount))) { thd->restore_active_arena(&call_arena, &backup_arena); err_status= TRUE; diff --git a/sql/sp_head.h b/sql/sp_head.h index 2f4f21a76f4..272bc5d445c 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -216,7 +216,11 @@ public: } sp_rcontext *rcontext_create(THD *thd, Field *retval, List *args); - + sp_rcontext *rcontext_create(THD *thd, Field *retval, + Item **args, uint arg_count); + sp_rcontext *rcontext_create(THD *thd, Field *retval, + Row_definition_list *list, + bool switch_security_ctx); private: /** Version of the stored routine cache at the moment when the diff --git a/sql/sp_rcontext.cc b/sql/sp_rcontext.cc index e82947835f0..43a42b579bd 100644 --- a/sql/sp_rcontext.cc +++ b/sql/sp_rcontext.cc @@ -63,25 +63,15 @@ sp_rcontext::~sp_rcontext() sp_rcontext *sp_rcontext::create(THD *thd, const sp_pcontext *root_parsing_ctx, Field *return_value_fld, - bool resolve_type_refs, - List *args) + Row_definition_list &field_def_lst) { sp_rcontext *ctx= new (thd->mem_root) sp_rcontext(root_parsing_ctx, return_value_fld, thd->in_sub_stmt); - if (!ctx) return NULL; - Row_definition_list field_def_lst; - ctx->m_root_parsing_ctx->retrieve_field_definitions(&field_def_lst); - - if (args && - field_def_lst.adjust_formal_params_to_actual_params(thd, args)) - return NULL; - if (ctx->alloc_arrays(thd) || - (resolve_type_refs && field_def_lst.resolve_type_refs(thd)) || ctx->init_var_table(thd, field_def_lst) || ctx->init_var_items(thd, field_def_lst)) { @@ -110,6 +100,22 @@ bool Row_definition_list:: } +bool Row_definition_list:: + adjust_formal_params_to_actual_params(THD *thd, + Item **args, uint arg_count) +{ + List_iterator it(*this); + DBUG_ASSERT(elements >= arg_count ); + Spvar_definition *def; + for (uint i= 0; (def= it++) && (i < arg_count) ; i++) + { + if (def->type_handler()->adjust_spparam_type(def, args[i])) + return true; + } + return false; +} + + bool sp_rcontext::alloc_arrays(THD *thd) { { diff --git a/sql/sp_rcontext.h b/sql/sp_rcontext.h index 2638aad03bf..93c8cacc70a 100644 --- a/sql/sp_rcontext.h +++ b/sql/sp_rcontext.h @@ -71,8 +71,7 @@ public: static sp_rcontext *create(THD *thd, const sp_pcontext *root_parsing_ctx, Field *return_value_fld, - bool resolve_type_refs, - List *args); + Row_definition_list &defs); ~sp_rcontext(); -- cgit v1.2.1