From 5b01a77c9c92dff6020c58d8c24f22f7659d3f16 Mon Sep 17 00:00:00 2001 From: "dkatz@damien-katzs-computer.local" <> Date: Mon, 22 Oct 2007 15:16:43 -0400 Subject: [PATCH 02/16] Bug #31332 --event-scheduler option misbehaving Changed the behaviour of the --event-scheduler option when used without an arguments. It now turns the option on. --- mysql-test/r/events_bugs.result | 4 ++++ mysql-test/t/events_bugs-master.opt | 1 + mysql-test/t/events_bugs.test | 15 +++++++++++++++ sql/events.cc | 2 +- 4 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 mysql-test/t/events_bugs-master.opt diff --git a/mysql-test/r/events_bugs.result b/mysql-test/r/events_bugs.result index b6b77101874..b0de2358777 100644 --- a/mysql-test/r/events_bugs.result +++ b/mysql-test/r/events_bugs.result @@ -3,6 +3,10 @@ drop database if exists mysqltest_db1; drop database if exists mysqltest_db2; create database events_test; use events_test; +select * from information_schema.global_variables where variable_name like 'event_scheduler'; +VARIABLE_NAME VARIABLE_VALUE +EVENT_SCHEDULER ON +SET GLOBAL event_scheduler = 'OFF'; CREATE EVENT lower_case ON SCHEDULE EVERY 1 MINUTE DO SELECT 1; CREATE EVENT Lower_case ON SCHEDULE EVERY 2 MINUTE DO SELECT 2; ERROR HY000: Event 'Lower_case' already exists diff --git a/mysql-test/t/events_bugs-master.opt b/mysql-test/t/events_bugs-master.opt new file mode 100644 index 00000000000..f93413a61e5 --- /dev/null +++ b/mysql-test/t/events_bugs-master.opt @@ -0,0 +1 @@ +--event-scheduler diff --git a/mysql-test/t/events_bugs.test b/mysql-test/t/events_bugs.test index ebd86f3a3d2..efdb67349ec 100644 --- a/mysql-test/t/events_bugs.test +++ b/mysql-test/t/events_bugs.test @@ -9,6 +9,21 @@ drop database if exists mysqltest_db2; create database events_test; use events_test; +# +# START: Bug #31332 --event-scheduler option misbehaving +# + +# NOTE!! this test must come first! It's testing that the --event-scheduler +# option with no argument in events_bugs-master.opt turns the scheduler on. + +select * from information_schema.global_variables where variable_name like 'event_scheduler'; + +SET GLOBAL event_scheduler = 'OFF'; + +# +# END: Bug #31332 +# + # # START - 16415: Events: event names are case sensitive # diff --git a/sql/events.cc b/sql/events.cc index 1bfbc5d6645..67249b40c79 100644 --- a/sql/events.cc +++ b/sql/events.cc @@ -146,7 +146,7 @@ bool Events::set_opt_event_scheduler(char *argument) { if (argument == NULL) - opt_event_scheduler= Events::EVENTS_DISABLED; + opt_event_scheduler= Events::EVENTS_ON; else { int type; From 5f33524d247729b31326f07ecf06c1325da44979 Mon Sep 17 00:00:00 2001 From: "anozdrin/alik@station." <> Date: Mon, 12 Nov 2007 14:44:17 +0300 Subject: [PATCH 03/16] Fix for a BUG#31898: 16M memory allocations for user variables in stored procedure. The problem was that MySQL used unnecessarily large amounts of memory if user variables were used as an argument to CONCAT or CONCAT_WS -- 16M per each user variable used. Technically, it happened because MySQL used the following allocation strategy for string functions to avoid multiple realloc() calls: in the virtual operation fix_length_and_dec() the attribute max_length was calculated as a sum of max_length values for each argument. Although this approach worked well for small (or fixed) data types, there could be a problem if there as a user variable among the arguments of a string function -- max_length of the function would be 16M (as the max_length of a user variable is 16M). Both CONCAT() and CONCAT_WS() functions suffer from this problem. The fix is to do not use meta-data for allocating memory. The following strategy is proposed instead: allocate the exact length of the result string at the first record, double the amount of memory allocated when it is required. No test case for this bug because there is no way to test memory consumption in a robust way with our test suite. --- sql/item_strfunc.cc | 60 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 55 insertions(+), 5 deletions(-) diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 03c65c9d654..a7624c5bbcd 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -356,10 +356,35 @@ String *Item_func_concat::val_str(String *str) } else { // Two big const strings - if (tmp_value.alloc(max_length) || - tmp_value.copy(*res) || - tmp_value.append(*res2)) + /* + NOTE: We should be prudent in the initial allocation unit -- the + size of the arguments is a function of data distribution, which + can be any. Instead of overcommitting at the first row, we grow + the allocated amount by the factor of 2. This ensures that no + more than 25% of memory will be overcommitted on average. + */ + + uint concat_len= res->length() + res2->length(); + + if (tmp_value.alloced_length() < concat_len) + { + if (tmp_value.alloced_length() == 0) + { + if (tmp_value.alloc(concat_len)) + goto null; + } + else + { + uint new_len = max(tmp_value.alloced_length() * 2, concat_len); + + if (tmp_value.realloc(new_len)) + goto null; + } + } + + if (tmp_value.copy(*res) || tmp_value.append(*res2)) goto null; + res= &tmp_value; use_as_buff=str; } @@ -679,8 +704,33 @@ String *Item_func_concat_ws::val_str(String *str) } else { // Two big const strings - if (tmp_value.alloc(max_length) || - tmp_value.copy(*res) || + /* + NOTE: We should be prudent in the initial allocation unit -- the + size of the arguments is a function of data distribution, which can + be any. Instead of overcommitting at the first row, we grow the + allocated amount by the factor of 2. This ensures that no more than + 25% of memory will be overcommitted on average. + */ + + uint concat_len= res->length() + sep_str->length() + res2->length(); + + if (tmp_value.alloced_length() < concat_len) + { + if (tmp_value.alloced_length() == 0) + { + if (tmp_value.alloc(concat_len)) + goto null; + } + else + { + uint new_len = max(tmp_value.alloced_length() * 2, concat_len); + + if (tmp_value.realloc(new_len)) + goto null; + } + } + + if (tmp_value.copy(*res) || tmp_value.append(*sep_str) || tmp_value.append(*res2)) goto null; From 99d33cd67a0d0e3224ae653692d6f73a6aedb1ac Mon Sep 17 00:00:00 2001 From: "anozdrin/alik@station." <> Date: Mon, 12 Nov 2007 17:26:32 +0300 Subject: [PATCH 04/16] A patch for BUG#32172: information_schema test fails with wait_condition timeout. The problem was that the event thread didn't manage to execute the event in 30 seconds on highly-loaded box. The fix is to increase timeout. This is a fix for the test suite. --- mysql-test/t/information_schema.test | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/t/information_schema.test b/mysql-test/t/information_schema.test index 1987d9d5773..55334916913 100644 --- a/mysql-test/t/information_schema.test +++ b/mysql-test/t/information_schema.test @@ -1142,6 +1142,7 @@ END$$ DELIMITER ;$$ +let $wait_timeout= 300; let $wait_condition=select count(*) = 0 from information_schema.events where event_name='event_status'; --source include/wait_condition.inc From 2ed0d9ea21120bf193f1a0189d61c211f33f17df Mon Sep 17 00:00:00 2001 From: "dkatz@damien-katzs-computer.local" <> Date: Wed, 14 Nov 2007 16:12:46 -0500 Subject: [PATCH 05/16] Bug#28785 thread-handling not displayed properly in SHOW VARIABLES --- mysql-test/r/no-threads.result | 3 +++ mysql-test/t/no-threads.test | 1 + sql/mysqld.cc | 5 +++-- sql/scheduler.h | 2 +- 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/no-threads.result b/mysql-test/r/no-threads.result index 50e52138be8..aefecd0f7bc 100644 --- a/mysql-test/r/no-threads.result +++ b/mysql-test/r/no-threads.result @@ -4,3 +4,6 @@ select 1+1; select 1+2; 1+2 3 +SHOW GLOBAL VARIABLES LIKE 'thread_handling'; +Variable_name Value +thread_handling no-threads diff --git a/mysql-test/t/no-threads.test b/mysql-test/t/no-threads.test index 806cf24e961..31ea6406ee9 100644 --- a/mysql-test/t/no-threads.test +++ b/mysql-test/t/no-threads.test @@ -3,3 +3,4 @@ # select 1+1; select 1+2; +SHOW GLOBAL VARIABLES LIKE 'thread_handling'; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 4cf6e05751f..f65fee872ed 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -7745,12 +7745,13 @@ mysqld_get_one_option(int optid, break; } case OPT_ONE_THREAD: - global_system_variables.thread_handling= 2; + global_system_variables.thread_handling= + SCHEDULER_ONE_THREAD_PER_CONNECTION; break; case OPT_THREAD_HANDLING: { global_system_variables.thread_handling= - find_type_or_exit(argument, &thread_handling_typelib, opt->name); + find_type_or_exit(argument, &thread_handling_typelib, opt->name)-1; break; } case OPT_FT_BOOLEAN_SYNTAX: diff --git a/sql/scheduler.h b/sql/scheduler.h index 8351cefda4c..46bbd300cbb 100644 --- a/sql/scheduler.h +++ b/sql/scheduler.h @@ -40,7 +40,7 @@ public: enum scheduler_types { - SCHEDULER_ONE_THREAD_PER_CONNECTION=1, + SCHEDULER_ONE_THREAD_PER_CONNECTION=0, SCHEDULER_NO_THREADS, SCHEDULER_POOL_OF_THREADS }; From e8343ca83df952a0901a5a1621130c4f89920f8b Mon Sep 17 00:00:00 2001 From: "anozdrin/alik@station." <> Date: Thu, 15 Nov 2007 15:35:35 +0300 Subject: [PATCH 06/16] A patch for BUG#19723: kill of active connection yields different error code depending on platform. On Mac OS X, KILL statement issued to kill the current connection would return a different error code and message than on other platforms ('MySQL server has gone away' instead of 'Shutdown in progress'). The reason for this difference was that on Mac OS X we have macro SIGNAL_WITH_VIO_CLOSE defined. This macro forces KILL implementation to close the communication socket of the thread that is being killed. SIGNAL_WITH_VIO_CLOSE macro is defined on platforms where just sending a signal is not a reliable mechanism to interrupt the thread from sleeping on a blocking system call. In a nutshell, closing the socket is a hack to work around an operating system bug and awake the blocked thread no matter what. However, if the thread that is being killed is the same thread that issued KILL statement, closing the socket leads to a prematurely lost connection. At the same time it is not necessary to close the socket in this case, since the thread in question is not inside a blocking system call. The fix, therefore, is to not close the socket if the thread that is being killed is the same that issued KILL statement, even with defined SIGNAL_WITH_VIO_CLOSE. --- mysql-test/r/kill.result | 9 +++++++++ mysql-test/t/kill.test | 16 ++++++++++++++++ sql/sql_class.cc | 15 ++++++++++++++- 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/kill.result b/mysql-test/r/kill.result index a08be429a83..8376eb7c0de 100644 --- a/mysql-test/r/kill.result +++ b/mysql-test/r/kill.result @@ -125,3 +125,12 @@ drop function bug27563; drop procedure proc27563; PREPARE stmt FROM 'EXPLAIN SELECT * FROM t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17,t18,t19,t20,t21,t22,t23,t24,t25,t26,t27,t28,t29,t30,t31,t32,t33,t34,t35,t36,t37,t38,t39,t40 WHERE a1=a2 AND a2=a3 AND a3=a4 AND a4=a5 AND a5=a6 AND a6=a7 AND a7=a8 AND a8=a9 AND a9=a10 AND a10=a11 AND a11=a12 AND a12=a13 AND a13=a14 AND a14=a15 AND a15=a16 AND a16=a17 AND a17=a18 AND a18=a19 AND a19=a20 AND a20=a21 AND a21=a22 AND a22=a23 AND a23=a24 AND a24=a25 AND a25=a26 AND a26=a27 AND a27=a28 AND a28=a29 AND a29=a30 AND a30=a31 AND a31=a32 AND a32=a33 AND a33=a34 AND a34=a35 AND a35=a36 AND a36=a37 AND a37=a38 AND a38=a39 AND a39=a40 '; EXECUTE stmt; +# +# Bug#19723: kill of active connection yields different error code +# depending on platform. +# + +# Connection: con2. +KILL CONNECTION_ID(); +SELECT 1; +ERROR HY000: Lost connection to MySQL server during query diff --git a/mysql-test/t/kill.test b/mysql-test/t/kill.test index 5d5095f7d61..219412e5afa 100644 --- a/mysql-test/t/kill.test +++ b/mysql-test/t/kill.test @@ -304,3 +304,19 @@ while ($i) dec $i ; } --enable_query_log + +########################################################################### + +--echo # +--echo # Bug#19723: kill of active connection yields different error code +--echo # depending on platform. +--echo # + +--echo +--echo # Connection: con2. +--connection con2 + +KILL CONNECTION_ID(); + +--error 2013 +SELECT 1; diff --git a/sql/sql_class.cc b/sql/sql_class.cc index a904023cbff..368ed897a4d 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -818,7 +818,20 @@ void THD::awake(THD::killed_state state_to_set) if (!slave_thread) thread_scheduler.post_kill_notification(this); #ifdef SIGNAL_WITH_VIO_CLOSE - close_active_vio(); + if (this != current_thd) + { + /* + In addition to a signal, let's close the socket of the thread that + is being killed. This is to make sure it does not block if the + signal is lost. This needs to be done only on platforms where + signals are not a reliable interruption mechanism. + + If we're killing ourselves, we know that we're not blocked, so this + hack is not used. + */ + + close_active_vio(); + } #endif } if (mysys_var) From 1794242b24cc0f958af48db9019d95aed06cf589 Mon Sep 17 00:00:00 2001 From: "thek@adventure.(none)" <> Date: Mon, 19 Nov 2007 17:59:44 +0100 Subject: [PATCH 07/16] Bug #31153 calling stored procedure crashes server if available memory is low When the server was out of memory it crashed because of invalid memory access. This patch adds detection for failed memory allocations and make the server output a proper error message. --- sql/mysqld.cc | 14 ++++- sql/sp_head.cc | 38 +++++++++--- sql/sp_head.h | 6 +- sql/sql_base.cc | 3 +- sql/sql_lex.h | 5 +- sql/sql_prepare.cc | 2 +- sql/sql_yacc.yy | 149 +++++++++++++++++++++++++++++++++++---------- 7 files changed, 168 insertions(+), 49 deletions(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 08c2b60fa79..89d7f3272ad 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -2489,7 +2489,12 @@ static int my_message_sql(uint error, const char *str, myf MyFlags) thd->query_error= 1; // needed to catch query errors during replication if (!thd->no_warnings_for_error) + { + thd->no_warnings_for_error= TRUE; push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, error, str); + thd->no_warnings_for_error= FALSE; + } + /* thd->lex->current_select == 0 if lex structure is not inited (not query command (COM_QUERY)) @@ -4295,8 +4300,13 @@ pthread_handler_t handle_connections_sockets(void *arg __attribute__((unused))) sock == unix_sock ? VIO_LOCALHOST: 0)) || my_net_init(&thd->net,vio_tmp)) { - if (vio_tmp) - vio_delete(vio_tmp); + /* + Only delete the temporary vio if we didn't already attach it to the + NET object. The destructor in THD will delete any initialized net + structure. + */ + if (vio_tmp && thd->net.vio != vio_tmp) + vio_delete(vio_tmp); else { (void) shutdown(new_sock, SHUT_RDWR); diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 5ad6625efb8..3049ae5ccd3 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -411,14 +411,16 @@ check_routine_name(LEX_STRING ident) */ void * -sp_head::operator new(size_t size) +sp_head::operator new(size_t size) throw() { DBUG_ENTER("sp_head::operator new"); MEM_ROOT own_root; sp_head *sp; - init_alloc_root(&own_root, MEM_ROOT_BLOCK_SIZE, MEM_ROOT_PREALLOC); + init_sql_alloc(&own_root, MEM_ROOT_BLOCK_SIZE, MEM_ROOT_PREALLOC); sp= (sp_head *) alloc_root(&own_root, size); + if (sp == NULL) + return NULL; sp->main_mem_root= own_root; DBUG_PRINT("info", ("mem_root 0x%lx", (ulong) &sp->mem_root)); DBUG_RETURN(sp); @@ -429,6 +431,10 @@ sp_head::operator delete(void *ptr, size_t size) { DBUG_ENTER("sp_head::operator delete"); MEM_ROOT own_root; + + if (ptr == NULL) + DBUG_VOID_RETURN; + sp_head *sp= (sp_head *) ptr; /* Make a copy of main_mem_root as free_root will free the sp */ @@ -472,6 +478,9 @@ sp_head::init(LEX *lex) lex->spcont= m_pcont= new sp_pcontext(); + if (!lex->spcont) + DBUG_VOID_RETURN; + /* Altough trg_table_fields list is used only in triggers we init for all types of stored procedures to simplify reset_lex()/restore_lex() code. @@ -973,7 +982,7 @@ sp_head::execute(THD *thd) DBUG_RETURN(TRUE); /* init per-instruction memroot */ - init_alloc_root(&execute_mem_root, MEM_ROOT_BLOCK_SIZE, 0); + init_sql_alloc(&execute_mem_root, MEM_ROOT_BLOCK_SIZE, 0); DBUG_ASSERT(!(m_flags & IS_INVOKED)); m_flags|= IS_INVOKED; @@ -1795,16 +1804,29 @@ sp_head::execute_procedure(THD *thd, List *args) } -// Reset lex during parsing, before we parse a sub statement. -void +/** + @brief Reset lex during parsing, before we parse a sub statement. + + @param thd Thread handler. + + @return Error state + @retval true An error occurred. + @retval false Success. +*/ + +bool sp_head::reset_lex(THD *thd) { DBUG_ENTER("sp_head::reset_lex"); LEX *sublex; LEX *oldlex= thd->lex; + sublex= new (thd->mem_root)st_lex_local; + if (sublex == 0) + DBUG_RETURN(TRUE); + + thd->lex= sublex; (void)m_lex.push_front(oldlex); - thd->lex= sublex= new st_lex; /* Reset most stuff. */ lex_start(thd); @@ -1827,7 +1849,7 @@ sp_head::reset_lex(THD *thd) sublex->interval_list.empty(); sublex->type= 0; - DBUG_VOID_RETURN; + DBUG_RETURN(FALSE); } // Restore lex during parsing, after we have parsed a sub statement. @@ -3703,7 +3725,7 @@ sp_add_to_query_tables(THD *thd, LEX *lex, if (!(table= (TABLE_LIST *)thd->calloc(sizeof(TABLE_LIST)))) { - my_error(ER_OUTOFMEMORY, MYF(0), sizeof(TABLE_LIST)); + thd->fatal_error(); return NULL; } table->db_length= strlen(db); diff --git a/sql/sp_head.h b/sql/sp_head.h index ebe40ce9c87..cb243dd2503 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -191,10 +191,10 @@ public: Security_context m_security_ctx; static void * - operator new(size_t size); + operator new(size_t size) throw (); static void - operator delete(void *ptr, size_t size); + operator delete(void *ptr, size_t size) throw (); sp_head(); @@ -254,7 +254,7 @@ public: } // Resets lex in 'thd' and keeps a copy of the old one. - void + bool reset_lex(THD *thd); // Restores lex in 'thd' from our copy, but keeps some status from the diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 289924ff418..7ceed4e15d2 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -80,7 +80,6 @@ bool Prelock_error_handler::safely_trapped_errors() return ((m_handled_errors > 0) && (m_unhandled_errors == 0)); } - TABLE *unused_tables; /* Used by mysql_test */ HASH open_cache; /* Used by mysql_test */ @@ -2643,7 +2642,7 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags) temporary mem_root for new .frm parsing. TODO: variables for size */ - init_alloc_root(&new_frm_mem, 8024, 8024); + init_sql_alloc(&new_frm_mem, 8024, 8024); thd->current_tablenr= 0; restart: diff --git a/sql/sql_lex.h b/sql/sql_lex.h index ce56be79744..f216f51b0e4 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1283,11 +1283,11 @@ typedef struct st_lex : public Query_tables_list struct st_lex_local: public st_lex { - static void *operator new(size_t size) + static void *operator new(size_t size) throw() { return (void*) sql_alloc((uint) size); } - static void *operator new(size_t size, MEM_ROOT *mem_root) + static void *operator new(size_t size, MEM_ROOT *mem_root) throw() { return (void*) alloc_root(mem_root, (uint) size); } @@ -1303,3 +1303,4 @@ extern void lex_start(THD *thd); extern void lex_end(LEX *lex); extern int MYSQLlex(void *arg, void *yythd); extern char *skip_rear_comments(CHARSET_INFO *cs, char *begin, char *end); + diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index af3da834a7a..74cbd2c5505 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -2659,7 +2659,7 @@ Prepared_statement::Prepared_statement(THD *thd_arg, Protocol *protocol_arg) last_errno(0), flags((uint) IS_IN_USE) { - init_alloc_root(&main_mem_root, thd_arg->variables.query_alloc_block_size, + init_sql_alloc(&main_mem_root, thd_arg->variables.query_alloc_block_size, thd_arg->variables.query_prealloc_size); *last_error= '\0'; } diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 553cc6d24d5..3140ae4f7e3 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1628,6 +1628,8 @@ create_function_tail: } /* Order is important here: new - reset - init */ sp= new sp_head(); + if (sp == NULL) + MYSQL_YYABORT; sp->reset_thd_mem_root(thd); sp->init(lex); sp->init_sp_name(thd, lex->spname); @@ -1929,7 +1931,8 @@ sp_decl: { LEX *lex= Lex; - lex->sphead->reset_lex(YYTHD); + if (lex->sphead->reset_lex(YYTHD)) + MYSQL_YYABORT; lex->spcont->declare_var_boundary($2); } type @@ -1937,6 +1940,10 @@ sp_decl: { LEX *lex= Lex; sp_pcontext *pctx= lex->spcont; + if (pctx == 0) + { + MYSQL_YYABORT; + } uint num_vars= pctx->context_var_count(); enum enum_field_types var_type= (enum enum_field_types) $4; Item *dflt_value_item= $5; @@ -2022,12 +2029,15 @@ sp_decl: { i= new sp_instr_hreturn(sp->instructions(), ctx, ctx->current_var_count()); + if (i == NULL ) + MYSQL_YYABORT; sp->add_instr(i); } else { /* EXIT or UNDO handler, just jump to the end of the block */ i= new sp_instr_hreturn(sp->instructions(), ctx, 0); - + if (i == NULL) + MYSQL_YYABORT; sp->add_instr(i); sp->push_backpatch(i, lex->spcont->last_label()); /* Block end */ } @@ -2055,7 +2065,9 @@ sp_decl: } i= new sp_instr_cpush(sp->instructions(), ctx, $5, ctx->current_cursor_count()); - sp->add_instr(i); + if ( i==NULL ) + MYSQL_YYABORT; + sp->add_instr(i); ctx->push_cursor(&$2); $$.vars= $$.conds= $$.hndlrs= 0; $$.curs= 1; @@ -2064,7 +2076,8 @@ sp_decl: sp_cursor_stmt: { - Lex->sphead->reset_lex(YYTHD); + if(Lex->sphead->reset_lex(YYTHD)) + MYSQL_YYABORT; /* We use statement here just be able to get a better error message. Using 'select' works too, but will then @@ -2230,7 +2243,8 @@ sp_proc_stmt: LEX *lex= thd->lex; Lex_input_stream *lip= thd->m_lip; - lex->sphead->reset_lex(thd); + if (lex->sphead->reset_lex(thd)) + MYSQL_YYABORT; lex->sphead->m_tmp_query= lip->tok_start; } statement @@ -2255,9 +2269,10 @@ sp_proc_stmt: lex->var_list.is_empty()); if (lex->sql_command != SQLCOM_SET_OPTION) { - sp_instr_stmt *i=new sp_instr_stmt(sp->instructions(), + sp_instr_stmt *i= new sp_instr_stmt(sp->instructions(), lex->spcont, lex); - + if (i == NULL) + MYSQL_YYABORT; /* Extract the query statement from the tokenizer. The end is either lex->ptr, if there was no lookahead, @@ -2275,7 +2290,10 @@ sp_proc_stmt: sp->restore_lex(thd); } | RETURN_SYM - { Lex->sphead->reset_lex(YYTHD); } + { + if(Lex->sphead->reset_lex(YYTHD)) + MYSQL_YYABORT; + } expr { LEX *lex= Lex; @@ -2292,6 +2310,8 @@ sp_proc_stmt: i= new sp_instr_freturn(sp->instructions(), lex->spcont, $3, sp->m_return_field_def.sql_type, lex); + if (i == NULL) + MYSQL_YYABORT; sp->add_instr(i); sp->m_flags|= sp_head::HAS_RETURN; } @@ -2334,12 +2354,23 @@ sp_proc_stmt: uint n; n= ctx->diff_handlers(lab->ctx, TRUE); /* Exclusive the dest. */ + if (n) - sp->add_instr(new sp_instr_hpop(ip++, ctx, n)); + { + sp_instr_hpop *hpop= new sp_instr_hpop(ip++, ctx, n); + if (hpop == NULL) + MYSQL_YYABORT; + sp->add_instr(hpop); + } n= ctx->diff_cursors(lab->ctx, TRUE); /* Exclusive the dest. */ if (n) - sp->add_instr(new sp_instr_cpop(ip++, ctx, n)); + { + sp_instr_cpop *cpop= new sp_instr_cpop(ip++, ctx, n); + sp->add_instr(cpop); + } i= new sp_instr_jump(ip, ctx); + if (i == NULL) + MYSQL_YYABORT; sp->push_backpatch(i, lab); /* Jumping forward */ sp->add_instr(i); } @@ -2364,11 +2395,19 @@ sp_proc_stmt: n= ctx->diff_handlers(lab->ctx, FALSE); /* Inclusive the dest. */ if (n) - sp->add_instr(new sp_instr_hpop(ip++, ctx, n)); + { + sp_instr_hpop *hpop= new sp_instr_hpop(ip++, ctx, n); + sp->add_instr(hpop); + } n= ctx->diff_cursors(lab->ctx, FALSE); /* Inclusive the dest. */ if (n) - sp->add_instr(new sp_instr_cpop(ip++, ctx, n)); + { + sp_instr_cpop *cpop= new sp_instr_cpop(ip++, ctx, n); + sp->add_instr(cpop); + } i= new sp_instr_jump(ip, ctx, lab->ip); /* Jump back */ + if (i == NULL) + MYSQL_YYABORT; sp->add_instr(i); } } @@ -2385,6 +2424,8 @@ sp_proc_stmt: MYSQL_YYABORT; } i= new sp_instr_copen(sp->instructions(), lex->spcont, offset); + if (i == NULL) + MYSQL_YYABORT; sp->add_instr(i); } | FETCH_SYM sp_opt_fetch_noise ident INTO @@ -2400,6 +2441,8 @@ sp_proc_stmt: MYSQL_YYABORT; } i= new sp_instr_cfetch(sp->instructions(), lex->spcont, offset); + if (i == NULL) + MYSQL_YYABORT; sp->add_instr(i); } sp_fetch_list @@ -2417,6 +2460,8 @@ sp_proc_stmt: MYSQL_YYABORT; } i= new sp_instr_cclose(sp->instructions(), lex->spcont, offset); + if (i == NULL) + MYSQL_YYABORT; sp->add_instr(i); } ; @@ -2472,7 +2517,10 @@ sp_fetch_list: ; sp_if: - { Lex->sphead->reset_lex(YYTHD); } + { + if (Lex->sphead->reset_lex(YYTHD)) + MYSQL_YYABORT; + } expr THEN_SYM { LEX *lex= Lex; @@ -2481,7 +2529,8 @@ sp_if: uint ip= sp->instructions(); sp_instr_jump_if_not *i = new sp_instr_jump_if_not(ip, ctx, $2, lex); - + if (i == NULL) + MYSQL_YYABORT; sp->push_backpatch(i, ctx->push_label((char *)"", 0)); sp->add_cont_backpatch(i); sp->add_instr(i); @@ -2493,7 +2542,8 @@ sp_if: sp_pcontext *ctx= Lex->spcont; uint ip= sp->instructions(); sp_instr_jump *i = new sp_instr_jump(ip, ctx); - + if (i == NULL) + MYSQL_YYABORT; sp->add_instr(i); sp->backpatch(ctx->pop_label()); sp->push_backpatch(i, ctx->push_label((char *)"", 0)); @@ -2522,7 +2572,8 @@ simple_case_stmt: { LEX *lex= Lex; case_stmt_action_case(lex); - lex->sphead->reset_lex(YYTHD); /* For expr $3 */ + if (lex->sphead->reset_lex(YYTHD)) + MYSQL_YYABORT; /* For expr $3 */ } expr { @@ -2571,7 +2622,8 @@ searched_when_clause_list: simple_when_clause: WHEN_SYM { - Lex->sphead->reset_lex(YYTHD); /* For expr $3 */ + if (Lex->sphead->reset_lex(YYTHD)) + MYSQL_YYABORT; /* For expr $3 */ } expr { @@ -2592,7 +2644,8 @@ simple_when_clause: searched_when_clause: WHEN_SYM { - Lex->sphead->reset_lex(YYTHD); /* For expr $3 */ + if (Lex->sphead->reset_lex(YYTHD)) + MYSQL_YYABORT; /* For expr $3 */ } expr { @@ -2616,6 +2669,8 @@ else_clause_opt: uint ip= sp->instructions(); sp_instr_error *i= new sp_instr_error(ip, lex->spcont, ER_SP_CASE_NOT_FOUND); + if (i == NULL) + MYSQL_YYABORT; sp->add_instr(i); } | ELSE sp_proc_stmts1 @@ -2685,11 +2740,21 @@ sp_unlabeled_control: sp->backpatch(ctx->last_label()); /* We always have a label */ if ($3.hndlrs) - sp->add_instr(new sp_instr_hpop(sp->instructions(), ctx, - $3.hndlrs)); + { + sp_instr_hpop *hpop= new sp_instr_hpop(sp->instructions(), ctx, + $3.hndlrs); + if (hpop == NULL) + MYSQL_YYABORT; + sp->add_instr(hpop); + } if ($3.curs) - sp->add_instr(new sp_instr_cpop(sp->instructions(), ctx, - $3.curs)); + { + sp_instr_cpop *cpop= new sp_instr_cpop(sp->instructions(), ctx, + $3.curs); + if (cpop == NULL) + MYSQL_YYABORT; + sp->add_instr(cpop); + } lex->spcont= ctx->pop_context(); } | LOOP_SYM @@ -2699,11 +2764,15 @@ sp_unlabeled_control: uint ip= lex->sphead->instructions(); sp_label_t *lab= lex->spcont->last_label(); /* Jumping back */ sp_instr_jump *i = new sp_instr_jump(ip, lex->spcont, lab->ip); - + if (i == NULL) + MYSQL_YYABORT; lex->sphead->add_instr(i); } | WHILE_SYM - { Lex->sphead->reset_lex(YYTHD); } + { + if (Lex->sphead->reset_lex(YYTHD)) + MYSQL_YYABORT; + } expr DO_SYM { LEX *lex= Lex; @@ -2711,7 +2780,8 @@ sp_unlabeled_control: uint ip= sp->instructions(); sp_instr_jump_if_not *i = new sp_instr_jump_if_not(ip, lex->spcont, $3, lex); - + if (i == NULL) + MYSQL_YYABORT; /* Jumping forward */ sp->push_backpatch(i, lex->spcont->last_label()); sp->new_cont_backpatch(i); @@ -2724,12 +2794,16 @@ sp_unlabeled_control: uint ip= lex->sphead->instructions(); sp_label_t *lab= lex->spcont->last_label(); /* Jumping back */ sp_instr_jump *i = new sp_instr_jump(ip, lex->spcont, lab->ip); - + if (i == NULL) + MYSQL_YYABORT; lex->sphead->add_instr(i); lex->sphead->do_cont_backpatch(); } | REPEAT_SYM sp_proc_stmts1 UNTIL_SYM - { Lex->sphead->reset_lex(YYTHD); } + { + if (Lex->sphead->reset_lex(YYTHD)) + MYSQL_YYABORT; + } expr END REPEAT_SYM { LEX *lex= Lex; @@ -2738,6 +2812,8 @@ sp_unlabeled_control: sp_instr_jump_if_not *i = new sp_instr_jump_if_not(ip, lex->spcont, $5, lab->ip, lex); + if (i == NULL) + MYSQL_YYABORT; lex->sphead->add_instr(i); lex->sphead->restore_lex(YYTHD); /* We can shortcut the cont_backpatch here */ @@ -4271,6 +4347,8 @@ select_init2: select_part2 { LEX *lex= Lex; + if (lex == NULL) + MYSQL_YYABORT; SELECT_LEX * sel= lex->current_select; if (lex->current_select->set_braces(0)) { @@ -4624,6 +4702,8 @@ predicate: $7->push_front($5); $7->push_front($1); Item_func_in *item = new (YYTHD->mem_root) Item_func_in(*$7); + if (item == NULL) + MYSQL_YYABORT; item->negate(); $$= item; } @@ -5084,7 +5164,8 @@ simple_expr: { LEX *lex= Lex; sp_name *name= new sp_name($1, $3, true); - + if (name == NULL) + MYSQL_YYABORT; name->init_qname(YYTHD); sp_add_used_routine(lex, YYTHD, name, TYPE_ENUM_FUNCTION); if ($5) @@ -5199,8 +5280,9 @@ simple_expr: if (lex->copy_db_to(&db.str, &db.length)) MYSQL_YYABORT; sp_name *name= new sp_name(db, $1, false); - if (name) - name->init_qname(thd); + if (name == NULL) + MYSQL_YYABORT; + name->init_qname(thd); sp_add_used_routine(lex, YYTHD, name, TYPE_ENUM_FUNCTION); if ($4) @@ -8422,7 +8504,8 @@ option_type_value: QQ: May be we should simply prohibit group assignments in SP? */ - Lex->sphead->reset_lex(thd); + if (Lex->sphead->reset_lex(thd)) + MYSQL_YYABORT; lex= thd->lex; /* Set new LEX as if we at start of set rule. */ @@ -8587,6 +8670,8 @@ sys_option_value: it= spv->dflt; else it= new Item_null(); + if (it == NULL) + MYSQL_YYABORT; sp_set= new sp_instr_set(lex->sphead->instructions(), ctx, spv->offset, it, spv->type, lex, TRUE); lex->sphead->add_instr(sp_set); @@ -9832,6 +9917,8 @@ sp_tail: /* Order is important here: new - reset - init */ sp= new sp_head(); + if (sp == NULL) + MYSQL_YYABORT; sp->reset_thd_mem_root(YYTHD); sp->init(lex); sp->m_type= TYPE_ENUM_PROCEDURE; From 94e6e4ff4451b9fc7e48bdaf26183ce057f40eed Mon Sep 17 00:00:00 2001 From: "davi@endora.local" <> Date: Tue, 20 Nov 2007 15:17:53 -0200 Subject: [PATCH 08/16] Bug#31397 Inconsistent drop table behavior of handler tables. The problem is that DROP TABLE and other DDL statements failed to automatically close handlers associated with tables that were marked for reopen (FLUSH TABLES). The current implementation fails to properly discard handlers of dropped tables (that were marked for reopen) because it searches on the open handler tables list and using the current alias of the table being dropped. The problem is that it must not use the open handler tables list to search because the table might have been closed (marked for reopen) by a flush tables command and also it must not use the current table alias at all since multiple different aliases may be associated with a single table. This is specially visible when a user has two open handlers (using alias) of a same table and a flush tables command is issued before the table is dropped (see test case). Scanning the handler table list is also useless for dropping handlers associated with temporary tables, because temporary tables are not kept in the THD::handler_tables list. The solution is to simple scan the handlers hash table searching for, and deleting all handlers with matching table names if the reopen flag is not passed to the flush function, indicating that the handlers should be deleted. All matching handlers are deleted even if the associated the table is not open. --- mysql-test/include/handler.inc | 94 +++++++++++ mysql-test/r/handler_innodb.result | 91 +++++++++++ mysql-test/r/handler_myisam.result | 91 +++++++++++ sql/mysql_priv.h | 9 +- sql/sql_base.cc | 8 +- sql/sql_class.cc | 4 +- sql/sql_handler.cc | 249 +++++++++++++---------------- sql/sql_rename.cc | 2 + sql/sql_table.cc | 18 +-- 9 files changed, 401 insertions(+), 165 deletions(-) diff --git a/mysql-test/include/handler.inc b/mysql-test/include/handler.inc index 79e21382d4c..485b2e881d3 100644 --- a/mysql-test/include/handler.inc +++ b/mysql-test/include/handler.inc @@ -598,3 +598,97 @@ handler a2 read a last; handler a2 read a prev; handler a2 close; drop table t1; + +# +# Bug#31397 Inconsistent drop table behavior of handler tables. +# + +--disable_warnings +drop table if exists t1,t2; +--enable_warnings +create table t1 (a int); +handler t1 open as t1_alias; +drop table t1; +create table t1 (a int); +handler t1 open as t1_alias; +flush tables; +drop table t1; +create table t1 (a int); +handler t1 open as t1_alias; +handler t1_alias close; +drop table t1; +create table t1 (a int); +handler t1 open as t1_alias; +handler t1_alias read first; +drop table t1; +--error ER_UNKNOWN_TABLE +handler t1_alias read next; + +# Test that temporary tables associated with handlers are properly dropped. + +create table t1 (a int); +create temporary table t2 (a int, key(a)); +handler t1 open as a1; +handler t2 open as a2; +handler a2 read a first; +drop table t1, t2; +--error ER_UNKNOWN_TABLE +handler a2 read a next; +--error ER_UNKNOWN_TABLE +handler a1 close; + +# Alter table drop handlers + +create table t1 (a int, key(a)); +create table t2 like t1; +handler t1 open as a1; +handler t2 open as a2; +handler a1 read a first; +handler a2 read a first; +alter table t1 add b int; +--error ER_UNKNOWN_TABLE +handler a1 close; +handler a2 close; +drop table t1, t2; + +# Rename table drop handlers + +create table t1 (a int, key(a)); +handler t1 open as a1; +handler a1 read a first; +rename table t1 to t2; +--error ER_UNKNOWN_TABLE +handler a1 read a first; +drop table t2; + +# Optimize table drop handlers + +create table t1 (a int, key(a)); +create table t2 like t1; +handler t1 open as a1; +handler t2 open as a2; +handler a1 read a first; +handler a2 read a first; +optimize table t1; +--error ER_UNKNOWN_TABLE +handler a1 close; +handler a2 close; +drop table t1, t2; + +# Flush tables causes handlers reopen + +create table t1 (a int, b char(1), key a(a), key b(a,b)); +insert into t1 values (0,"a"),(1,"b"),(2,"c"),(3,"d"),(4,"e"), + (5,"f"),(6,"g"),(7,"h"),(8,"i"),(9,"j"); +handler t1 open; +handler t1 read a first; +handler t1 read a next; +flush tables; +handler t1 read a next; +handler t1 read a next; +flush tables with read lock; +handler t1 read a next; +unlock tables; +drop table t1; +--error ER_UNKNOWN_TABLE +handler t1 read a next; diff --git a/mysql-test/r/handler_innodb.result b/mysql-test/r/handler_innodb.result index d9a1a0aa12b..9d269f78d10 100644 --- a/mysql-test/r/handler_innodb.result +++ b/mysql-test/r/handler_innodb.result @@ -637,3 +637,94 @@ a b 8 i handler a2 close; drop table t1; +drop table if exists t1,t2; +create table t1 (a int); +handler t1 open as t1_alias; +drop table t1; +create table t1 (a int); +handler t1 open as t1_alias; +flush tables; +drop table t1; +create table t1 (a int); +handler t1 open as t1_alias; +handler t1_alias close; +drop table t1; +create table t1 (a int); +handler t1 open as t1_alias; +handler t1_alias read first; +a +drop table t1; +handler t1_alias read next; +ERROR 42S02: Unknown table 't1_alias' in HANDLER +create table t1 (a int); +create temporary table t2 (a int, key(a)); +handler t1 open as a1; +handler t2 open as a2; +handler a2 read a first; +a +drop table t1, t2; +handler a2 read a next; +ERROR 42S02: Unknown table 'a2' in HANDLER +handler a1 close; +ERROR 42S02: Unknown table 'a1' in HANDLER +create table t1 (a int, key(a)); +create table t2 like t1; +handler t1 open as a1; +handler t2 open as a2; +handler a1 read a first; +a +handler a2 read a first; +a +alter table t1 add b int; +handler a1 close; +ERROR 42S02: Unknown table 'a1' in HANDLER +handler a2 close; +drop table t1, t2; +create table t1 (a int, key(a)); +handler t1 open as a1; +handler a1 read a first; +a +rename table t1 to t2; +handler a1 read a first; +ERROR 42S02: Unknown table 'a1' in HANDLER +drop table t2; +create table t1 (a int, key(a)); +create table t2 like t1; +handler t1 open as a1; +handler t2 open as a2; +handler a1 read a first; +a +handler a2 read a first; +a +optimize table t1; +Table Op Msg_type Msg_text +test.t1 optimize status OK +handler a1 close; +ERROR 42S02: Unknown table 'a1' in HANDLER +handler a2 close; +drop table t1, t2; +create table t1 (a int, b char(1), key a(a), key b(a,b)); +insert into t1 values (0,"a"),(1,"b"),(2,"c"),(3,"d"),(4,"e"), +(5,"f"),(6,"g"),(7,"h"),(8,"i"),(9,"j"); +handler t1 open; +handler t1 read a first; +a b +0 a +handler t1 read a next; +a b +1 b +flush tables; +handler t1 read a next; +a b +0 a +handler t1 read a next; +a b +1 b +flush tables with read lock; +handler t1 read a next; +a b +0 a +unlock tables; +drop table t1; +handler t1 read a next; +ERROR 42S02: Unknown table 't1' in HANDLER diff --git a/mysql-test/r/handler_myisam.result b/mysql-test/r/handler_myisam.result index b42fdc864fe..0b27b07c4d2 100644 --- a/mysql-test/r/handler_myisam.result +++ b/mysql-test/r/handler_myisam.result @@ -637,3 +637,94 @@ a b 8 i handler a2 close; drop table t1; +drop table if exists t1,t2; +create table t1 (a int); +handler t1 open as t1_alias; +drop table t1; +create table t1 (a int); +handler t1 open as t1_alias; +flush tables; +drop table t1; +create table t1 (a int); +handler t1 open as t1_alias; +handler t1_alias close; +drop table t1; +create table t1 (a int); +handler t1 open as t1_alias; +handler t1_alias read first; +a +drop table t1; +handler t1_alias read next; +ERROR 42S02: Unknown table 't1_alias' in HANDLER +create table t1 (a int); +create temporary table t2 (a int, key(a)); +handler t1 open as a1; +handler t2 open as a2; +handler a2 read a first; +a +drop table t1, t2; +handler a2 read a next; +ERROR 42S02: Unknown table 'a2' in HANDLER +handler a1 close; +ERROR 42S02: Unknown table 'a1' in HANDLER +create table t1 (a int, key(a)); +create table t2 like t1; +handler t1 open as a1; +handler t2 open as a2; +handler a1 read a first; +a +handler a2 read a first; +a +alter table t1 add b int; +handler a1 close; +ERROR 42S02: Unknown table 'a1' in HANDLER +handler a2 close; +drop table t1, t2; +create table t1 (a int, key(a)); +handler t1 open as a1; +handler a1 read a first; +a +rename table t1 to t2; +handler a1 read a first; +ERROR 42S02: Unknown table 'a1' in HANDLER +drop table t2; +create table t1 (a int, key(a)); +create table t2 like t1; +handler t1 open as a1; +handler t2 open as a2; +handler a1 read a first; +a +handler a2 read a first; +a +optimize table t1; +Table Op Msg_type Msg_text +test.t1 optimize status Table is already up to date +handler a1 close; +ERROR 42S02: Unknown table 'a1' in HANDLER +handler a2 close; +drop table t1, t2; +create table t1 (a int, b char(1), key a(a), key b(a,b)); +insert into t1 values (0,"a"),(1,"b"),(2,"c"),(3,"d"),(4,"e"), +(5,"f"),(6,"g"),(7,"h"),(8,"i"),(9,"j"); +handler t1 open; +handler t1 read a first; +a b +0 a +handler t1 read a next; +a b +1 b +flush tables; +handler t1 read a next; +a b +0 a +handler t1 read a next; +a b +1 b +flush tables with read lock; +handler t1 read a next; +a b +0 a +unlock tables; +drop table t1; +handler t1 read a next; +ERROR 42S02: Unknown table 't1' in HANDLER diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 12838317646..f19e11357cd 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -1289,12 +1289,9 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen); bool mysql_ha_close(THD *thd, TABLE_LIST *tables); bool mysql_ha_read(THD *, TABLE_LIST *,enum enum_ha_read_modes,char *, List *,enum ha_rkey_function,Item *,ha_rows,ha_rows); -int mysql_ha_flush(THD *thd, TABLE_LIST *tables, uint mode_flags, - bool is_locked); -/* mysql_ha_flush mode_flags bits */ -#define MYSQL_HA_CLOSE_FINAL 0x00 -#define MYSQL_HA_REOPEN_ON_USAGE 0x01 -#define MYSQL_HA_FLUSH_ALL 0x02 +void mysql_ha_flush(THD *thd); +void mysql_ha_rm_tables(THD *thd, TABLE_LIST *tables); +void mysql_ha_cleanup(THD *thd); /* sql_base.cc */ #define TMP_TABLE_KEY_EXTRA 8 diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 66d0cda2155..5e2b0285a1c 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -929,8 +929,8 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh, thd->proc_info="Flushing tables"; close_old_data_files(thd,thd->open_tables,1,1); - mysql_ha_flush(thd, tables, MYSQL_HA_REOPEN_ON_USAGE | MYSQL_HA_FLUSH_ALL, - TRUE); + mysql_ha_flush(thd); + bool found=1; /* Wait until all threads has closed all the tables we had locked */ DBUG_PRINT("info", @@ -2516,7 +2516,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, deadlock may occur. */ if (thd->handler_tables) - mysql_ha_flush(thd, (TABLE_LIST*) NULL, MYSQL_HA_REOPEN_ON_USAGE, TRUE); + mysql_ha_flush(thd); /* Actually try to find the table in the open_cache. @@ -3136,7 +3136,7 @@ bool wait_for_tables(THD *thd) { thd->some_tables_deleted=0; close_old_data_files(thd,thd->open_tables,0,dropping_tables != 0); - mysql_ha_flush(thd, (TABLE_LIST*) NULL, MYSQL_HA_REOPEN_ON_USAGE, TRUE); + mysql_ha_flush(thd); if (!table_is_used(thd->open_tables,1)) break; (void) pthread_cond_wait(&COND_refresh,&LOCK_open); diff --git a/sql/sql_class.cc b/sql/sql_class.cc index a904023cbff..a8bac731b87 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -678,9 +678,7 @@ void THD::cleanup(void) lock=locked_tables; locked_tables=0; close_thread_tables(this); } - mysql_ha_flush(this, (TABLE_LIST*) 0, - MYSQL_HA_CLOSE_FINAL | MYSQL_HA_FLUSH_ALL, FALSE); - hash_free(&handler_tables_hash); + mysql_ha_cleanup(this); delete_dynamic(&user_var_events); hash_free(&user_vars); close_temporary_tables(this); diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index 19a99f9d12b..31d6b28a73c 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -65,9 +65,6 @@ static enum enum_ha_read_modes rkey_to_rnext[]= { RNEXT_SAME, RNEXT, RPREV, RNEXT, RPREV, RNEXT, RPREV, RPREV }; -static int mysql_ha_flush_table(THD *thd, TABLE **table_ptr, uint mode_flags); - - /* Get hash key and hash key length. @@ -119,13 +116,15 @@ static void mysql_ha_hash_free(TABLE_LIST *tables) @param thd Thread identifier. @param tables A list of tables with the first entry to close. + @param is_locked If LOCK_open is locked. @note Though this function takes a list of tables, only the first list entry will be closed. - @note Broadcasts refresh if it closed the table. + @note Broadcasts refresh if it closed a table with old version. */ -static void mysql_ha_close_table(THD *thd, TABLE_LIST *tables) +static void mysql_ha_close_table(THD *thd, TABLE_LIST *tables, + bool is_locked) { TABLE **table_ptr; @@ -143,13 +142,15 @@ static void mysql_ha_close_table(THD *thd, TABLE_LIST *tables) if (*table_ptr) { (*table_ptr)->file->ha_index_or_rnd_end(); - VOID(pthread_mutex_lock(&LOCK_open)); + if (! is_locked) + VOID(pthread_mutex_lock(&LOCK_open)); if (close_thread_table(thd, table_ptr)) { /* Tell threads waiting for refresh that something has happened */ broadcast_refresh(); } - VOID(pthread_mutex_unlock(&LOCK_open)); + if (! is_locked) + VOID(pthread_mutex_unlock(&LOCK_open)); } else if (tables->table) { @@ -305,7 +306,7 @@ err: if (hash_tables) my_free((char*) hash_tables, MYF(0)); if (tables->table) - mysql_ha_close_table(thd, tables); + mysql_ha_close_table(thd, tables, FALSE); DBUG_PRINT("exit",("ERROR")); DBUG_RETURN(TRUE); } @@ -339,7 +340,7 @@ bool mysql_ha_close(THD *thd, TABLE_LIST *tables) (uchar*) tables->alias, strlen(tables->alias) + 1))) { - mysql_ha_close_table(thd, hash_tables); + mysql_ha_close_table(thd, hash_tables, FALSE); hash_delete(&thd->handler_tables_hash, (uchar*) hash_tables); } else @@ -478,7 +479,7 @@ retry: if (need_reopen) { - mysql_ha_close_table(thd, tables); + mysql_ha_close_table(thd, tables, FALSE); hash_tables->table= NULL; /* The lock might have been aborted, we need to manually reset @@ -669,163 +670,131 @@ err0: } -/* - Flush (close) a list of HANDLER tables. +/** + Scan the handler tables hash for matching tables. - SYNOPSIS - mysql_ha_flush() - thd Thread identifier. - tables The list of tables to close. If NULL, - close all HANDLER tables [marked as flushed]. - mode_flags MYSQL_HA_CLOSE_FINAL finally close the table. - MYSQL_HA_REOPEN_ON_USAGE mark for reopen. - MYSQL_HA_FLUSH_ALL flush all tables, not only - those marked for flush. - is_locked If LOCK_open is locked. + @param thd Thread identifier. + @param tables The list of tables to remove. - DESCRIPTION - The list of HANDLER tables may be NULL, in which case all HANDLER - tables are closed (if MYSQL_HA_FLUSH_ALL) is set. - If 'tables' is NULL and MYSQL_HA_FLUSH_ALL is not set, - all HANDLER tables marked for flush are closed. - Broadcasts refresh for every table closed. - - NOTE - Since mysql_ha_flush() is called when the base table has to be closed, - we compare real table names, not aliases. Hence, database names matter. - - RETURN - 0 ok + @return Pointer to head of linked list (TABLE_LIST::next_local) of matching + TABLE_LIST elements from handler_tables_hash. Otherwise, NULL if no + table was matched. */ -int mysql_ha_flush(THD *thd, TABLE_LIST *tables, uint mode_flags, - bool is_locked) +static TABLE_LIST *mysql_ha_find(THD *thd, TABLE_LIST *tables) { - TABLE_LIST *tmp_tables; - TABLE **table_ptr; - bool did_lock= FALSE; - DBUG_ENTER("mysql_ha_flush"); - DBUG_PRINT("enter", ("tables: 0x%lx mode_flags: 0x%02x", - (long) tables, mode_flags)); + TABLE_LIST *hash_tables, *head= NULL, *first= tables; + DBUG_ENTER("mysql_ha_find"); - if (tables) + /* search for all handlers with matching table names */ + for (uint i= 0; i < thd->handler_tables_hash.records; i++) { - /* Close all tables in the list. */ - for (tmp_tables= tables ; tmp_tables; tmp_tables= tmp_tables->next_local) + hash_tables= (TABLE_LIST*) hash_element(&thd->handler_tables_hash, i); + for (tables= first; tables; tables= tables->next_local) { - DBUG_PRINT("info-in-tables-list",("'%s'.'%s' as '%s'", - tmp_tables->db, tmp_tables->table_name, - tmp_tables->alias)); - /* Close all currently open handler tables with the same base table. */ - table_ptr= &(thd->handler_tables); - while (*table_ptr) - { - if ((!*tmp_tables->db || - !my_strcasecmp(&my_charset_latin1, (*table_ptr)->s->db.str, - tmp_tables->db)) && - ! my_strcasecmp(&my_charset_latin1, - (*table_ptr)->s->table_name.str, - tmp_tables->table_name)) - { - DBUG_PRINT("info",("*table_ptr '%s'.'%s' as '%s'", - (*table_ptr)->s->db.str, - (*table_ptr)->s->table_name.str, - (*table_ptr)->alias)); - /* The first time it is required, lock for close_thread_table(). */ - if (! did_lock && ! is_locked) - { - VOID(pthread_mutex_lock(&LOCK_open)); - did_lock= TRUE; - } - mysql_ha_flush_table(thd, table_ptr, mode_flags); - continue; - } - table_ptr= &(*table_ptr)->next; - } - /* end of handler_tables list */ + if ((! *tables->db || + ! my_strcasecmp(&my_charset_latin1, hash_tables->db, tables->db)) && + ! my_strcasecmp(&my_charset_latin1, hash_tables->table_name, + tables->table_name)) + break; } - /* end of flush tables list */ - } - else - { - /* Close all currently open tables [which are marked for flush]. */ - table_ptr= &(thd->handler_tables); - while (*table_ptr) + if (tables) { - if ((mode_flags & MYSQL_HA_FLUSH_ALL) || - (*table_ptr)->needs_reopen_or_name_lock()) - { - /* The first time it is required, lock for close_thread_table(). */ - if (! did_lock && ! is_locked) - { - VOID(pthread_mutex_lock(&LOCK_open)); - did_lock= TRUE; - } - mysql_ha_flush_table(thd, table_ptr, mode_flags); - continue; - } - table_ptr= &(*table_ptr)->next; + hash_tables->next_local= head; + head= hash_tables; } } - /* Release the lock if it was taken by this function. */ - if (did_lock) - VOID(pthread_mutex_unlock(&LOCK_open)); - - DBUG_RETURN(0); + DBUG_RETURN(head); } -/* - Flush (close) a table. - SYNOPSIS - mysql_ha_flush_table() - thd Thread identifier. - table The table to close. - mode_flags MYSQL_HA_CLOSE_FINAL finally close the table. - MYSQL_HA_REOPEN_ON_USAGE mark for reopen. +/** + Remove matching tables from the HANDLER's hash table. - DESCRIPTION - Broadcasts refresh if it closed the table. - The caller must lock LOCK_open. + @param thd Thread identifier. + @param tables The list of tables to remove. - RETURN - 0 ok + @note Broadcasts refresh if it closed a table with old version. */ -static int mysql_ha_flush_table(THD *thd, TABLE **table_ptr, uint mode_flags) +void mysql_ha_rm_tables(THD *thd, TABLE_LIST *tables) { - TABLE_LIST *hash_tables; - TABLE *table= *table_ptr; - DBUG_ENTER("mysql_ha_flush_table"); - DBUG_PRINT("enter",("'%s'.'%s' as '%s' flags: 0x%02x", - table->s->db.str, table->s->table_name.str, - table->alias, mode_flags)); + TABLE_LIST *hash_tables, *next; + DBUG_ENTER("mysql_ha_rm_tables"); - if ((hash_tables= (TABLE_LIST*) hash_search(&thd->handler_tables_hash, - (uchar*) table->alias, - strlen(table->alias) + 1))) + safe_mutex_assert_not_owner(&LOCK_open); + + DBUG_ASSERT(tables); + + hash_tables= mysql_ha_find(thd, tables); + + while (hash_tables) { - if (! (mode_flags & MYSQL_HA_REOPEN_ON_USAGE)) - { - /* This is a final close. Remove from hash. */ - hash_delete(&thd->handler_tables_hash, (uchar*) hash_tables); - } - else + next= hash_tables->next_local; + if (hash_tables->table) + mysql_ha_close_table(thd, hash_tables, FALSE); + hash_delete(&thd->handler_tables_hash, (uchar*) hash_tables); + hash_tables= next; + } + + DBUG_VOID_RETURN; +} + + +/** + Flush (close and mark for re-open) all tables that should be should + be reopen. + + @param thd Thread identifier. + + @note Broadcasts refresh if it closed a table with old version. +*/ + +void mysql_ha_flush(THD *thd) +{ + TABLE_LIST *hash_tables; + DBUG_ENTER("mysql_ha_flush"); + + safe_mutex_assert_owner(&LOCK_open); + + for (uint i= 0; i < thd->handler_tables_hash.records; i++) + { + hash_tables= (TABLE_LIST*) hash_element(&thd->handler_tables_hash, i); + if (hash_tables->table && hash_tables->table->needs_reopen_or_name_lock()) { + mysql_ha_close_table(thd, hash_tables, TRUE); /* Mark table as closed, ready for re-open. */ hash_tables->table= NULL; } - } - - safe_mutex_assert_owner(&LOCK_open); - (*table_ptr)->file->ha_index_or_rnd_end(); - safe_mutex_assert_owner(&LOCK_open); - if (close_thread_table(thd, table_ptr)) - { - /* Tell threads waiting for refresh that something has happened */ - broadcast_refresh(); } - DBUG_RETURN(0); + DBUG_VOID_RETURN; } + + +/** + Close all HANDLER's tables. + + @param thd Thread identifier. + + @note Broadcasts refresh if it closed a table with old version. +*/ + +void mysql_ha_cleanup(THD *thd) +{ + TABLE_LIST *hash_tables; + DBUG_ENTER("mysql_ha_cleanup"); + + for (uint i= 0; i < thd->handler_tables_hash.records; i++) + { + hash_tables= (TABLE_LIST*) hash_element(&thd->handler_tables_hash, i); + if (hash_tables->table) + mysql_ha_close_table(thd, hash_tables, FALSE); + } + + hash_free(&thd->handler_tables_hash); + + DBUG_VOID_RETURN; +} + diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc index 750bcd50479..66d89edc146 100644 --- a/sql/sql_rename.cc +++ b/sql/sql_rename.cc @@ -51,6 +51,8 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent) DBUG_RETURN(1); } + mysql_ha_rm_tables(thd, table_list); + if (wait_if_global_read_lock(thd,0,1)) DBUG_RETURN(1); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index bf4a02ae5cc..9d26273e809 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1521,6 +1521,8 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, built_query.append("DROP TABLE "); } + mysql_ha_rm_tables(thd, tables); + pthread_mutex_lock(&LOCK_open); /* @@ -1562,8 +1564,6 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, handlerton *table_type; enum legacy_db_type frm_db_type; - mysql_ha_flush(thd, table, MYSQL_HA_CLOSE_FINAL, 1); - error= drop_temporary_table(thd, table); switch (error) { @@ -1572,13 +1572,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, tmp_table_deleted= 1; continue; case -1: - // table already in use - /* - XXX: This branch should never be taken outside of SF, trigger or - prelocked mode. - - DBUG_ASSERT(thd->in_sub_stmt); - */ + DBUG_ASSERT(thd->in_sub_stmt); error= 1; goto err_with_placeholders; default: @@ -4025,7 +4019,8 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) DBUG_RETURN(TRUE); - mysql_ha_flush(thd, tables, MYSQL_HA_CLOSE_FINAL, FALSE); + mysql_ha_rm_tables(thd, tables); + for (table= tables; table; table= table->next_local) { char table_name[NAME_LEN*2+2]; @@ -5766,8 +5761,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, build_table_filename(reg_path, sizeof(reg_path), db, table_name, reg_ext, 0); build_table_filename(path, sizeof(path), db, table_name, "", 0); - - mysql_ha_flush(thd, table_list, MYSQL_HA_CLOSE_FINAL, FALSE); + mysql_ha_rm_tables(thd, table_list); /* DISCARD/IMPORT TABLESPACE is always alone in an ALTER TABLE */ if (alter_info->tablespace_op != NO_TABLESPACE_OP) From d06b46e83fcbbf1d04e28db0ae734e3d1230abf2 Mon Sep 17 00:00:00 2001 From: "davi@endora.local" <> Date: Tue, 20 Nov 2007 17:45:49 -0200 Subject: [PATCH 09/16] This issue was fixed in Bug 30904 which includes a similar test case. --- mysql-test/t/sp_notembedded.test | 23 +---------------------- 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/mysql-test/t/sp_notembedded.test b/mysql-test/t/sp_notembedded.test index b5037b469ae..4a747b9c614 100644 --- a/mysql-test/t/sp_notembedded.test +++ b/mysql-test/t/sp_notembedded.test @@ -45,27 +45,9 @@ call bug4902_2()| call bug4902_2()| drop procedure bug4902_2| - -# Disable until bug#17244 is fixed ---disable_parsing # -# BUG#5278: Stored procedure packets out of order if SET PASSWORD. +# BUG#3583: query cache doesn't work for stored procedures # ---disable_warnings -drop function if exists bug5278| ---enable_warnings -create function bug5278 () returns char -begin - SET PASSWORD FOR 'bob'@'%.loc.gov' = PASSWORD('newpass'); - return 'okay'; -end| - ---error 1133 -select bug5278()| ---error 1133 -select bug5278()| -drop function bug5278| ---enable_parsing --disable_warnings drop table if exists t1| @@ -74,9 +56,6 @@ create table t1 ( id char(16) not null default '', data int not null )| -# -# BUG#3583: query cache doesn't work for stored procedures -# --disable_warnings drop procedure if exists bug3583| --enable_warnings From 04bf5743b4bbe67429f9ef6442f1b3e00e4bb45b Mon Sep 17 00:00:00 2001 From: "kostja@bodhi.(none)" <> Date: Thu, 22 Nov 2007 03:48:51 +0300 Subject: [PATCH 10/16] Update the failing kill test in the team tree. --- mysql-test/r/kill.result | 4 +++- mysql-test/t/kill.test | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/kill.result b/mysql-test/r/kill.result index 8376eb7c0de..3ea5bbd20bc 100644 --- a/mysql-test/r/kill.result +++ b/mysql-test/r/kill.result @@ -132,5 +132,7 @@ EXECUTE stmt; # Connection: con2. KILL CONNECTION_ID(); +# CR_SERVER_LOST, CR_SERVER_GONE_ERROR, depending on the timing +# of close of the connection socket SELECT 1; -ERROR HY000: Lost connection to MySQL server during query +Got one of the listed errors diff --git a/mysql-test/t/kill.test b/mysql-test/t/kill.test index 219412e5afa..3da4232502d 100644 --- a/mysql-test/t/kill.test +++ b/mysql-test/t/kill.test @@ -318,5 +318,7 @@ while ($i) KILL CONNECTION_ID(); ---error 2013 +--echo # CR_SERVER_LOST, CR_SERVER_GONE_ERROR, depending on the timing +--echo # of close of the connection socket +--error 2013, 2006 SELECT 1; From c9d81cabd3e384f7936c29eecc347cd66df58ced Mon Sep 17 00:00:00 2001 From: "kostja@bodhi.(none)" <> Date: Thu, 22 Nov 2007 14:48:03 +0300 Subject: [PATCH 11/16] Add a test case for Bug#29817. The bug was fixed by the patch for Bug#28318. --- mysql-test/r/skip_grants.result | 6 ++++++ mysql-test/t/skip_grants.test | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/mysql-test/r/skip_grants.result b/mysql-test/r/skip_grants.result index 6bb8cbea2f1..38e017af7ad 100644 --- a/mysql-test/r/skip_grants.result +++ b/mysql-test/r/skip_grants.result @@ -72,3 +72,9 @@ count(*) select count(*) from information_schema.USER_PRIVILEGES; count(*) 0 +# +# Bug#29817 Queries with UDF fail with non-descriptive error +# if mysql.proc is missing +# +select no_such_function(1); +ERROR 42000: FUNCTION test.no_such_function does not exist diff --git a/mysql-test/t/skip_grants.test b/mysql-test/t/skip_grants.test index 5e0fc65bc34..8e543b9e38c 100644 --- a/mysql-test/t/skip_grants.test +++ b/mysql-test/t/skip_grants.test @@ -122,3 +122,9 @@ select count(*) from information_schema.COLUMN_PRIVILEGES; select count(*) from information_schema.SCHEMA_PRIVILEGES; select count(*) from information_schema.TABLE_PRIVILEGES; select count(*) from information_schema.USER_PRIVILEGES; +--echo # +--echo # Bug#29817 Queries with UDF fail with non-descriptive error +--echo # if mysql.proc is missing +--echo # +--error ER_SP_DOES_NOT_EXIST +select no_such_function(1); From 351c47415314cad3623be6689e4205bc6f31ca0c Mon Sep 17 00:00:00 2001 From: "davi@endora.local" <> Date: Thu, 22 Nov 2007 10:18:19 -0200 Subject: [PATCH 12/16] Bug#32528 Global read lock with a low priority write lock causes a server crash FLUSH TABLES WITH READ LOCK fails to properly detect write locked tables when running under low priority updates. The problem is that when trying to aspire a global read lock, the reload_acl_and_cache() function fails to properly check if the thread has a low priority write lock, which later my cause a server crash or deadlock. The solution is to simple check if the thread has any type of the possible exclusive write locks. --- mysql-test/r/flush.result | 17 +++++++++++++++++ mysql-test/t/flush.test | 31 +++++++++++++++++++++++++++++++ sql/sql_parse.cc | 2 +- 3 files changed, 49 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/flush.result b/mysql-test/r/flush.result index 7eb7fd16edb..ce64e09c1d3 100644 --- a/mysql-test/r/flush.result +++ b/mysql-test/r/flush.result @@ -55,3 +55,20 @@ flush tables with read lock; insert into t2 values(1); unlock tables; drop table t1, t2; +drop table if exists t1, t2; +set session low_priority_updates=1; +create table t1 (a int); +create table t2 (b int); +lock tables t1 write; +flush tables with read lock; +ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction +unlock tables; +lock tables t1 read, t2 write; +flush tables with read lock; +ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction +unlock tables; +lock tables t1 read; +flush tables with read lock; +unlock tables; +drop table t1, t2; +set session low_priority_updates=default; diff --git a/mysql-test/t/flush.test b/mysql-test/t/flush.test index 3a4f2f2f5f2..72efa8a2ee6 100644 --- a/mysql-test/t/flush.test +++ b/mysql-test/t/flush.test @@ -133,4 +133,35 @@ disconnect con3; connection default; drop table t1, t2; +# +# Bug#32528 Global read lock with a low priority write lock causes a server crash +# + +--disable_warnings +drop table if exists t1, t2; +--enable_warnings + +set session low_priority_updates=1; + +create table t1 (a int); +create table t2 (b int); + +lock tables t1 write; +--error ER_LOCK_OR_ACTIVE_TRANSACTION +flush tables with read lock; +unlock tables; + +lock tables t1 read, t2 write; +--error ER_LOCK_OR_ACTIVE_TRANSACTION +flush tables with read lock; +unlock tables; + +lock tables t1 read; +flush tables with read lock; +unlock tables; + +drop table t1, t2; + +set session low_priority_updates=default; + # End of 5.0 tests diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 0a8b92d28c0..e587a9f3561 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -7054,7 +7054,7 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables, for (; lock_p < end_p; lock_p++) { - if ((*lock_p)->type == TL_WRITE) + if ((*lock_p)->type >= TL_WRITE_ALLOW_WRITE) { my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0)); return 1; From 95bfde3d016b244d9d2cd8077401ece526484919 Mon Sep 17 00:00:00 2001 From: "thek@adventure.(none)" <> Date: Mon, 26 Nov 2007 15:44:05 +0100 Subject: [PATCH 13/16] Bug #32436 KILL QUERY completely deadlocks mysqld Sending several "KILL QUERY" statements to target a connection running "SELECT SLEEP" could freeze the server. The locking order in Item_func_sleep was wrong and this could lead to a dead lock. This patch solves the issue by resolving the locking order properly. --- sql/item_func.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sql/item_func.cc b/sql/item_func.cc index d03d497dfd0..a0824f2a146 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -3732,13 +3732,12 @@ longlong Item_func_sleep::val_int() break; error= 0; } - + pthread_mutex_unlock(&LOCK_user_locks); pthread_mutex_lock(&thd->mysys_var->mutex); thd->mysys_var->current_mutex= 0; thd->mysys_var->current_cond= 0; pthread_mutex_unlock(&thd->mysys_var->mutex); - pthread_mutex_unlock(&LOCK_user_locks); pthread_cond_destroy(&cond); return test(!error); // Return 1 killed From cdad8669dfcc82515a83e188627d58f702a54aa5 Mon Sep 17 00:00:00 2001 From: "davi@mysql.com/endora.local" <> Date: Mon, 26 Nov 2007 14:09:37 -0200 Subject: [PATCH 14/16] Bug#29592 SQL Injection issue Remove the mysql_odbc_escape_string() function. The function has multi-byte character escaping issues, doesn't honor the NO_BACKSLASH_ESCAPES mode and is not used anymore by the Connector/ODBC as of 3.51.17. --- include/mysql.h | 10 - include/mysql_h.ic | 816 ++++++++++++++++++++-------------------- libmysql/libmysql.c | 72 ---- libmysql/libmysql.def | 1 - libmysqld/libmysqld.def | 1 - 5 files changed, 407 insertions(+), 493 deletions(-) diff --git a/include/mysql.h b/include/mysql.h index b3e0dc45496..f2303abb241 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -550,16 +550,6 @@ unsigned long STDCALL mysql_real_escape_string(MYSQL *mysql, char *to,const char *from, unsigned long length); void STDCALL mysql_debug(const char *debug); -char * STDCALL mysql_odbc_escape_string(MYSQL *mysql, - char *to, - unsigned long to_length, - const char *from, - unsigned long from_length, - void *param, - char * - (*extend_buffer) - (void *, char *to, - unsigned long *length)); void STDCALL myodbc_remove_escape(MYSQL *mysql,char *name); unsigned int STDCALL mysql_thread_safe(void); my_bool STDCALL mysql_embedded(void); diff --git a/include/mysql_h.ic b/include/mysql_h.ic index 5a9daee6f9f..1d4f3ce2758 100644 --- a/include/mysql_h.ic +++ b/include/mysql_h.ic @@ -32,65 +32,65 @@ enum mysql_option; enum mysql_protocol_type; enum mysql_rpl_type; enum mysql_status; -# 134 "mysql.h" +# 138 "mysql.h" typedef struct st_mysql_rows MYSQL_ROWS; -# 24 "my_list.h" +# 23 "my_list.h" typedef struct st_list LIST; -# 35 "my_alloc.h" +# 34 "my_alloc.h" typedef struct st_mem_root MEM_ROOT; -# 251 "mysql.h" +# 255 "mysql.h" typedef struct st_mysql MYSQL; -# 653 "mysql.h" +# 647 "mysql.h" typedef struct st_mysql_bind MYSQL_BIND; -# 93 "mysql.h" +# 97 "mysql.h" typedef struct st_mysql_field MYSQL_FIELD; -# 117 "mysql.h" +# 121 "mysql.h" typedef unsigned int MYSQL_FIELD_OFFSET; -# 340 "mysql.h" +# 344 "mysql.h" typedef struct st_mysql_manager MYSQL_MANAGER; -# 354 "mysql.h" +# 358 "mysql.h" typedef struct st_mysql_parameters MYSQL_PARAMETERS; -# 309 "mysql.h" +# 313 "mysql.h" typedef struct st_mysql_res MYSQL_RES; -# 116 "mysql.h" +# 120 "mysql.h" typedef char * * MYSQL_ROW; -# 140 "mysql.h" -typedef MYSQL_ROWS * MYSQL_ROW_OFFSET; -# 681 "mysql.h" -typedef struct st_mysql_stmt MYSQL_STMT; -# 236 "mysql.h" -typedef struct character_set MY_CHARSET_INFO; -# 180 "mysql_com.h" -typedef struct st_net NET; -# 23 "typelib.h" -typedef struct st_typelib TYPELIB; -# 170 "mysql_com.h" -typedef struct st_vio Vio; -# 57 "mysql.h" -typedef char * gptr; -# 29 "my_list.h" -typedef int (* list_walk_action)(void *, void *); -# 48 "mysql.h" -typedef char my_bool; -# 63 "mysql.h" -typedef int my_socket; -# 125 "mysql.h" -typedef unsigned long long int my_ulonglong; # 144 "mysql.h" +typedef MYSQL_ROWS * MYSQL_ROW_OFFSET; +# 675 "mysql.h" +typedef struct st_mysql_stmt MYSQL_STMT; +# 240 "mysql.h" +typedef struct character_set MY_CHARSET_INFO; +# 179 "mysql_com.h" +typedef struct st_net NET; +# 22 "typelib.h" +typedef struct st_typelib TYPELIB; +# 169 "mysql_com.h" +typedef struct st_vio Vio; +# 60 "mysql.h" +typedef char * gptr; +# 28 "my_list.h" +typedef int (* list_walk_action)(void *, void *); +# 51 "mysql.h" +typedef char my_bool; +# 66 "mysql.h" +typedef int my_socket; +# 129 "mysql.h" +typedef unsigned long long int my_ulonglong; +# 148 "mysql.h" typedef struct embedded_query_result EMBEDDED_QUERY_RESULT; -# 145 "mysql.h" +# 149 "mysql.h" typedef struct st_mysql_data MYSQL_DATA; -# 750 "mysql.h" +# 744 "mysql.h" typedef struct st_mysql_methods MYSQL_METHODS; -# 48 "mysql_time.h" +# 47 "mysql_time.h" typedef struct st_mysql_time MYSQL_TIME; -# 371 "mysql_com.h" +# 375 "mysql_com.h" typedef struct st_udf_args UDF_ARGS; -# 384 "mysql_com.h" +# 388 "mysql_com.h" typedef struct st_udf_init UDF_INIT; -# 27 "my_alloc.h" +# 26 "my_alloc.h" typedef struct st_used_mem USED_MEM; -# 236 "mysql.h" +# 240 "mysql.h" struct __attribute__((aligned(__alignof__(unsigned int)), aligned(__alignof__(void *)))) character_set { unsigned int number; @@ -102,7 +102,7 @@ struct __attribute__((aligned(__alignof__(unsigned int)), aligned(__alignof__(vo unsigned int mbminlen; unsigned int mbmaxlen; }; -# 357 "mysql_com.h" +# 361 "mysql_com.h" struct __attribute__((aligned(__alignof__(unsigned long int)), aligned(__alignof__(double)))) rand_struct { unsigned long int seed1; @@ -110,14 +110,14 @@ struct __attribute__((aligned(__alignof__(unsigned long int)), aligned(__alignof unsigned long int max_value; double max_value_dbl; }; -# 24 "my_list.h" +# 23 "my_list.h" struct __attribute__((aligned(__alignof__(void *)))) st_list { struct st_list * prev; struct st_list * next; void * data; }; -# 35 "my_alloc.h" +# 34 "my_alloc.h" struct __attribute__((aligned(__alignof__(void *)), aligned(__alignof__(unsigned int)))) st_mem_root { USED_MEM * free; @@ -129,7 +129,7 @@ struct __attribute__((aligned(__alignof__(void *)), aligned(__alignof__(unsigned unsigned int first_block_usage; void (* error_handler)(void); }; -# 251 "mysql.h" +# 255 "mysql.h" struct __attribute__((aligned(__alignof__(void *)), aligned(__alignof__(unsigned long long int)))) st_mysql { NET net; @@ -173,7 +173,7 @@ struct __attribute__((aligned(__alignof__(void *)), aligned(__alignof__(unsigned void * thd; my_bool * unbuffered_fetch_owner; }; -# 653 "mysql.h" +# 647 "mysql.h" struct __attribute__((aligned(__alignof__(void *)), aligned(__alignof__(unsigned long int)))) st_mysql_bind { unsigned long int * length; @@ -195,7 +195,7 @@ struct __attribute__((aligned(__alignof__(void *)), aligned(__alignof__(unsigned void (* fetch_result)(struct st_mysql_bind *, MYSQL_FIELD *, unsigned char * * row); void (* skip_result)(struct st_mysql_bind *, MYSQL_FIELD *, unsigned char * * row); }; -# 145 "mysql.h" +# 149 "mysql.h" struct __attribute__((aligned(__alignof__(unsigned long long int)), aligned(__alignof__(void *)))) st_mysql_data { my_ulonglong rows; @@ -204,7 +204,7 @@ struct __attribute__((aligned(__alignof__(unsigned long long int)), aligned(__al MEM_ROOT alloc; struct embedded_query_result * embedded_info; }; -# 93 "mysql.h" +# 97 "mysql.h" struct __attribute__((aligned(__alignof__(void *)), aligned(__alignof__(unsigned long int)))) st_mysql_field { char * name; @@ -228,7 +228,7 @@ struct __attribute__((aligned(__alignof__(void *)), aligned(__alignof__(unsigned unsigned int charsetnr; enum enum_field_types type; }; -# 340 "mysql.h" +# 344 "mysql.h" struct __attribute__((aligned(__alignof__(void *)), aligned(__alignof__(unsigned long int)))) st_mysql_manager { NET net; @@ -246,7 +246,7 @@ struct __attribute__((aligned(__alignof__(void *)), aligned(__alignof__(unsigned int net_buf_size; char last_error[256]; }; -# 750 "mysql.h" +# 744 "mysql.h" struct __attribute__((aligned(__alignof__(void *)))) st_mysql_methods { my_bool (* read_query_result)(MYSQL * mysql); @@ -266,7 +266,7 @@ struct __attribute__((aligned(__alignof__(void *)))) st_mysql_methods int (* read_change_user_result)(MYSQL * mysql, char * buff, char const * passwd); int (* read_rows_from_cursor)(MYSQL_STMT * stmt); }; -# 167 "mysql.h" +# 171 "mysql.h" struct __attribute__((aligned(__alignof__(unsigned long int)), aligned(__alignof__(void *)))) st_mysql_options { unsigned int connect_timeout; @@ -309,13 +309,13 @@ struct __attribute__((aligned(__alignof__(unsigned long int)), aligned(__alignof int (* local_infile_error)(void *, char *, unsigned int); void * local_infile_userdata; }; -# 354 "mysql.h" +# 358 "mysql.h" struct __attribute__((aligned(__alignof__(void *)))) st_mysql_parameters { unsigned long int * p_max_allowed_packet; unsigned long int * p_net_buffer_length; }; -# 309 "mysql.h" +# 313 "mysql.h" struct __attribute__((aligned(__alignof__(unsigned long long int)), aligned(__alignof__(void *)))) st_mysql_res { my_ulonglong row_count; @@ -333,14 +333,14 @@ struct __attribute__((aligned(__alignof__(unsigned long long int)), aligned(__al my_bool unbuffered_fetch_cancelled; struct st_mysql_methods const * methods; }; -# 134 "mysql.h" +# 138 "mysql.h" struct __attribute__((aligned(__alignof__(void *)), aligned(__alignof__(unsigned long int)))) st_mysql_rows { struct st_mysql_rows * next; MYSQL_ROW data; unsigned long int length; }; -# 681 "mysql.h" +# 675 "mysql.h" struct __attribute__((aligned(__alignof__(void *)), aligned(__alignof__(unsigned long long int)))) st_mysql_stmt { MEM_ROOT mem_root; @@ -370,7 +370,7 @@ struct __attribute__((aligned(__alignof__(void *)), aligned(__alignof__(unsigned my_bool unbuffered_fetch_cancelled; my_bool update_max_length; }; -# 48 "mysql_time.h" +# 47 "mysql_time.h" struct __attribute__((aligned(__alignof__(unsigned long int)))) st_mysql_time { unsigned int year; @@ -383,7 +383,7 @@ struct __attribute__((aligned(__alignof__(unsigned long int)))) st_mysql_time my_bool neg; enum enum_mysql_timestamp_type time_type; }; -# 180 "mysql_com.h" +# 179 "mysql_com.h" struct __attribute__((aligned(__alignof__(void *)), aligned(__alignof__(unsigned long int)))) st_net { Vio * vio; @@ -419,7 +419,7 @@ struct __attribute__((aligned(__alignof__(void *)), aligned(__alignof__(unsigned my_bool report_error; my_bool return_errno; }; -# 23 "typelib.h" +# 22 "typelib.h" struct __attribute__((aligned(__alignof__(unsigned int)), aligned(__alignof__(void *)))) st_typelib { unsigned int count; @@ -427,7 +427,7 @@ struct __attribute__((aligned(__alignof__(unsigned int)), aligned(__alignof__(vo char const * * type_names; unsigned int * type_lengths; }; -# 371 "mysql_com.h" +# 375 "mysql_com.h" struct __attribute__((aligned(__alignof__(unsigned int)), aligned(__alignof__(void *)))) st_udf_args { unsigned int arg_count; @@ -438,7 +438,7 @@ struct __attribute__((aligned(__alignof__(unsigned int)), aligned(__alignof__(vo char * * attributes; unsigned long int * attribute_lengths; }; -# 384 "mysql_com.h" +# 388 "mysql_com.h" struct __attribute__((aligned(__alignof__(unsigned long int)), aligned(__alignof__(void *)))) st_udf_init { my_bool maybe_null; @@ -447,14 +447,14 @@ struct __attribute__((aligned(__alignof__(unsigned long int)), aligned(__alignof char * ptr; my_bool const_item; }; -# 27 "my_alloc.h" +# 26 "my_alloc.h" struct __attribute__((aligned(__alignof__(void *)), aligned(__alignof__(unsigned int)))) st_used_mem { struct st_used_mem * next; unsigned int left; unsigned int size; }; -# 368 "mysql_com.h" +# 372 "mysql_com.h" enum Item_result { STRING_RESULT = 0, @@ -463,7 +463,7 @@ enum Item_result ROW_RESULT = 3, DECIMAL_RESULT = 4, }; -# 314 "mysql_com.h" +# 313 "mysql_com.h" enum enum_cursor_type { CURSOR_TYPE_NO_CURSOR = 0, @@ -471,7 +471,7 @@ enum enum_cursor_type CURSOR_TYPE_FOR_UPDATE = 2, CURSOR_TYPE_SCROLLABLE = 4, }; -# 227 "mysql_com.h" +# 226 "mysql_com.h" enum enum_field_types { MYSQL_TYPE_DECIMAL = 0, @@ -502,13 +502,13 @@ enum enum_field_types MYSQL_TYPE_STRING = 254, MYSQL_TYPE_GEOMETRY = 255, }; -# 324 "mysql_com.h" +# 323 "mysql_com.h" enum enum_mysql_set_option { MYSQL_OPTION_MULTI_STATEMENTS_ON = 0, MYSQL_OPTION_MULTI_STATEMENTS_OFF = 1, }; -# 583 "mysql.h" +# 577 "mysql.h" enum enum_mysql_stmt_state { MYSQL_STMT_INIT_DONE = 1, @@ -516,7 +516,7 @@ enum enum_mysql_stmt_state MYSQL_STMT_EXECUTE_DONE = 3, MYSQL_STMT_FETCH_DONE = 4, }; -# 29 "mysql_time.h" +# 28 "mysql_time.h" enum enum_mysql_timestamp_type { MYSQL_TIMESTAMP_NONE = -(2), @@ -525,7 +525,7 @@ enum enum_mysql_timestamp_type MYSQL_TIMESTAMP_DATETIME = 1, MYSQL_TIMESTAMP_TIME = 2, }; -# 52 "mysql_com.h" +# 51 "mysql_com.h" enum enum_server_command { COM_SLEEP = 0, @@ -559,14 +559,14 @@ enum enum_server_command COM_STMT_FETCH = 28, COM_END = 29, }; -# 727 "mysql.h" +# 721 "mysql.h" enum enum_stmt_attr_type { STMT_ATTR_UPDATE_MAX_LENGTH = 0, STMT_ATTR_CURSOR_TYPE = 1, STMT_ATTR_PREFETCH_ROWS = 2, }; -# 289 "mysql_com.h" +# 288 "mysql_com.h" enum mysql_enum_shutdown_level { SHUTDOWN_DEFAULT = 0, @@ -578,7 +578,7 @@ enum mysql_enum_shutdown_level KILL_QUERY = 254, KILL_CONNECTION = 255, }; -# 154 "mysql.h" +# 158 "mysql.h" enum mysql_option { MYSQL_OPT_CONNECT_TIMEOUT = 0, @@ -604,7 +604,7 @@ enum mysql_option MYSQL_OPT_RECONNECT = 20, MYSQL_OPT_SSL_VERIFY_SERVER_CERT = 21, }; -# 221 "mysql.h" +# 225 "mysql.h" enum mysql_protocol_type { MYSQL_PROTOCOL_DEFAULT = 0, @@ -613,357 +613,355 @@ enum mysql_protocol_type MYSQL_PROTOCOL_PIPE = 3, MYSQL_PROTOCOL_MEMORY = 4, }; -# 231 "mysql.h" +# 235 "mysql.h" enum mysql_rpl_type { MYSQL_RPL_MASTER = 0, MYSQL_RPL_SLAVE = 1, MYSQL_RPL_ADMIN = 2, }; -# 216 "mysql.h" +# 220 "mysql.h" enum mysql_status { MYSQL_STATUS_READY = 0, MYSQL_STATUS_GET_RESULT = 1, MYSQL_STATUS_USE_RESULT = 2, }; -# 423 "mysql_com.h" -extern my_bool check_scramble(char const * reply, char const * message, unsigned char const * hash_stage2); -# 416 "mysql_com.h" -extern my_bool check_scramble_323(char const *, char const * message, unsigned long int * salt); -# 33 "typelib.h" -extern TYPELIB * copy_typelib(MEM_ROOT * root, TYPELIB * from); -# 411 "mysql_com.h" -extern void create_random_string(char * to, unsigned int, struct rand_struct * rand_st); -# 30 "typelib.h" -extern int find_type(char * x, TYPELIB * typelib, unsigned int); -# 425 "mysql_com.h" -extern void get_salt_from_password(unsigned char * res, char const * password); -# 418 "mysql_com.h" -extern void get_salt_from_password_323(unsigned long int * res, char const * password); -# 431 "mysql_com.h" -extern char * get_tty_password(char * opt_message); -# 32 "typelib.h" -extern char const * get_type(TYPELIB * typelib, unsigned int); -# 413 "mysql_com.h" -extern void hash_password(unsigned long int * to, char const * password, unsigned int); -# 31 "my_list.h" -extern LIST * list_add(LIST * root, LIST * element); -# 33 "my_list.h" -extern LIST * list_cons(void * data, LIST * root); -# 32 "my_list.h" -extern LIST * list_delete(LIST * root, LIST * element); -# 35 "my_list.h" -extern void list_free(LIST * root, unsigned int); -# 36 "my_list.h" -extern unsigned int list_length(LIST *); -# 34 "my_list.h" -extern LIST * list_reverse(LIST * root); -# 37 "my_list.h" -extern int list_walk(LIST *, list_walk_action, gptr); -# 440 "mysql_com.h" -extern int load_defaults(char const * conf_file, char const * * groups, int * argc, char * * * argv); -# 426 "mysql_com.h" -extern void make_password_from_salt(char * to, unsigned char const * hash_stage2); -# 419 "mysql_com.h" -extern void make_password_from_salt_323(char * to, unsigned long int const * salt); -# 421 "mysql_com.h" -extern void make_scrambled_password(char * to, char const * password); -# 414 "mysql_com.h" -extern void make_scrambled_password_323(char * to, char const * password); -# 31 "typelib.h" -extern void make_type(char * to, unsigned int, TYPELIB * typelib); -# 437 "mysql_com.h" -extern int modify_defaults_file(char const * file_location, char const * option, char const * option_value, char const * section_name, int); -# 354 "mysql_com.h" -extern int my_connect(my_socket, struct sockaddr const * name, unsigned int, unsigned int); -# 436 "mysql_com.h" -extern my_bool my_init(void); -# 336 "mysql_com.h" -extern my_bool my_net_init(NET * net, Vio * vio); -# 337 "mysql_com.h" -extern void my_net_local_init(NET * net); -# 347 "mysql_com.h" -extern unsigned long int my_net_read(NET * net); -# 342 "mysql_com.h" -extern my_bool my_net_write(NET * net, char const * packet, unsigned long int); -# 410 "mysql_com.h" -extern double my_rnd(struct rand_struct *); -# 443 "mysql_com.h" -extern void my_thread_end(void); -# 442 "mysql_com.h" -extern my_bool my_thread_init(void); -# 559 "mysql.h" -extern void myodbc_remove_escape(MYSQL * mysql, char * name); -# 501 "mysql.h" -extern int mysql_add_slave(MYSQL * mysql, char const * host, unsigned int, char const * user, char const * passwd); -# 410 "mysql.h" -extern my_ulonglong mysql_affected_rows(MYSQL * mysql); -# 823 "mysql.h" -extern my_bool mysql_autocommit(MYSQL * mysql, my_bool); -# 426 "mysql.h" -extern my_bool mysql_change_user(MYSQL * mysql, char const * user, char const * passwd, char const * db); -# 418 "mysql.h" -extern char const * mysql_character_set_name(MYSQL * mysql); -# 826 "mysql.h" -extern void mysql_close(MYSQL * sock); -# 821 "mysql.h" -extern my_bool mysql_commit(MYSQL * mysql); -# 530 "mysql.h" -extern void mysql_data_seek(MYSQL_RES * result, my_ulonglong); -# 548 "mysql.h" -extern void mysql_debug(char const * debug); -# 487 "mysql.h" -extern void mysql_disable_reads_from_master(MYSQL * mysql); -# 481 "mysql.h" -extern void mysql_disable_rpl_parse(MYSQL * mysql); -# 509 "mysql.h" -extern int mysql_dump_debug_info(MYSQL * mysql); -# 561 "mysql.h" -extern my_bool mysql_embedded(void); -# 486 "mysql.h" -extern void mysql_enable_reads_from_master(MYSQL * mysql); -# 480 "mysql.h" -extern void mysql_enable_rpl_parse(MYSQL * mysql); -# 402 "mysql.h" -extern my_bool mysql_eof(MYSQL_RES * res); -# 412 "mysql.h" -extern unsigned int mysql_errno(MYSQL * mysql); -# 432 "mysql_com.h" -extern char const * mysql_errno_to_sqlstate(unsigned int); -# 413 "mysql.h" -extern char const * mysql_error(MYSQL * mysql); -# 541 "mysql.h" -extern unsigned long int mysql_escape_string(char * to, char const * from, unsigned long int); -# 538 "mysql.h" -extern MYSQL_FIELD * mysql_fetch_field(MYSQL_RES * result); -# 403 "mysql.h" -extern MYSQL_FIELD * mysql_fetch_field_direct(MYSQL_RES * res, unsigned int); -# 405 "mysql.h" -extern MYSQL_FIELD * mysql_fetch_fields(MYSQL_RES * res); -# 537 "mysql.h" -extern unsigned long int * mysql_fetch_lengths(MYSQL_RES * result); -# 536 "mysql.h" -extern MYSQL_ROW mysql_fetch_row(MYSQL_RES * result); -# 409 "mysql.h" -extern unsigned int mysql_field_count(MYSQL * mysql); -# 534 "mysql.h" -extern MYSQL_FIELD_OFFSET mysql_field_seek(MYSQL_RES * result, MYSQL_FIELD_OFFSET); -# 407 "mysql.h" -extern MYSQL_FIELD_OFFSET mysql_field_tell(MYSQL_RES * res); -# 529 "mysql.h" -extern void mysql_free_result(MYSQL_RES * result); -# 454 "mysql.h" -extern void mysql_get_character_set_info(MYSQL * mysql, MY_CHARSET_INFO * charset); -# 519 "mysql.h" -extern char const * mysql_get_client_info(void); -# 520 "mysql.h" -extern unsigned long int mysql_get_client_version(void); -# 521 "mysql.h" -extern char const * mysql_get_host_info(MYSQL * mysql); -# 384 "mysql.h" -extern MYSQL_PARAMETERS * mysql_get_parameters(void); -# 523 "mysql.h" -extern unsigned int mysql_get_proto_info(MYSQL * mysql); -# 518 "mysql.h" -extern char const * mysql_get_server_info(MYSQL * mysql); -# 522 "mysql.h" -extern unsigned long int mysql_get_server_version(MYSQL * mysql); -# 425 "mysql.h" -extern char const * mysql_get_ssl_cipher(MYSQL * mysql); -# 543 "mysql.h" -extern unsigned long int mysql_hex_string(char * to, char const * from, unsigned long int); -# 416 "mysql.h" -extern char const * mysql_info(MYSQL * mysql); -# 421 "mysql.h" -extern MYSQL * mysql_init(MYSQL * mysql); -# 411 "mysql.h" -extern my_ulonglong mysql_insert_id(MYSQL * mysql); -# 512 "mysql.h" -extern int mysql_kill(MYSQL * mysql, unsigned long int); -# 524 "mysql.h" -extern MYSQL_RES * mysql_list_dbs(MYSQL * mysql, char const * wild); -# 539 "mysql.h" -extern MYSQL_RES * mysql_list_fields(MYSQL * mysql, char const * table, char const * wild); -# 526 "mysql.h" -extern MYSQL_RES * mysql_list_processes(MYSQL * mysql); -# 525 "mysql.h" -extern MYSQL_RES * mysql_list_tables(MYSQL * mysql, char const * wild); -# 568 "mysql.h" -extern void mysql_manager_close(MYSQL_MANAGER * con); -# 569 "mysql.h" -extern int mysql_manager_command(MYSQL_MANAGER * con, char const * cmd, int); -# 563 "mysql.h" -extern MYSQL_MANAGER * mysql_manager_connect(MYSQL_MANAGER * con, char const * host, char const * user, char const * passwd, unsigned int); -# 571 "mysql.h" -extern int mysql_manager_fetch_line(MYSQL_MANAGER * con, char * res_buf, int); -# 562 "mysql.h" -extern MYSQL_MANAGER * mysql_manager_init(MYSQL_MANAGER * con); -# 445 "mysql.h" -extern my_bool mysql_master_query(MYSQL * mysql, char const * q, unsigned long int); -# 447 "mysql.h" -extern my_bool mysql_master_send_query(MYSQL * mysql, char const * q, unsigned long int); -# 824 "mysql.h" -extern my_bool mysql_more_results(MYSQL * mysql); -# 825 "mysql.h" -extern int mysql_next_result(MYSQL * mysql); -# 401 "mysql.h" -extern unsigned int mysql_num_fields(MYSQL_RES * res); -# 400 "mysql.h" -extern my_ulonglong mysql_num_rows(MYSQL_RES * res); -# 549 "mysql.h" -extern char * mysql_odbc_escape_string(MYSQL * mysql, char * to, unsigned long int, char const * from, unsigned long int, void * param, char * (* extend_buffer)(void *, char * to, unsigned long int * length)); -# 527 "mysql.h" -extern int mysql_options(MYSQL * mysql, enum mysql_option, char const * arg); -# 516 "mysql.h" -extern int mysql_ping(MYSQL * mysql); -# 75 "mysql.h" -extern unsigned int mysql_port; -# 436 "mysql.h" -extern int mysql_query(MYSQL * mysql, char const * q); -# 574 "mysql.h" -extern my_bool mysql_read_query_result(MYSQL * mysql); -# 489 "mysql.h" -extern my_bool mysql_reads_from_master_enabled(MYSQL * mysql); -# 428 "mysql.h" -extern MYSQL * mysql_real_connect(MYSQL * mysql, char const * host, char const * user, char const * passwd, char const * db, unsigned int, char const * unix_socket, unsigned long int); -# 545 "mysql.h" -extern unsigned long int mysql_real_escape_string(MYSQL * mysql, char * to, char const * from, unsigned long int); -# 439 "mysql.h" -extern int mysql_real_query(MYSQL * mysql, char const * q, unsigned long int); -# 510 "mysql.h" -extern int mysql_refresh(MYSQL * mysql, unsigned int); -# 822 "mysql.h" -extern my_bool mysql_rollback(MYSQL * mysql); -# 532 "mysql.h" -extern MYSQL_ROW_OFFSET mysql_row_seek(MYSQL_RES * result, MYSQL_ROW_OFFSET); -# 406 "mysql.h" -extern MYSQL_ROW_OFFSET mysql_row_tell(MYSQL_RES * res); -# 483 "mysql.h" -extern int mysql_rpl_parse_enabled(MYSQL * mysql); -# 494 "mysql.h" -extern my_bool mysql_rpl_probe(MYSQL * mysql); -# 491 "mysql.h" -extern enum mysql_rpl_type mysql_rpl_query_type(char const * q, int); -# 435 "mysql.h" -extern int mysql_select_db(MYSQL * mysql, char const * db); -# 437 "mysql.h" -extern int mysql_send_query(MYSQL * mysql, char const * q, unsigned long int); -# 371 "mysql.h" -extern void mysql_server_end(void); -# 370 "mysql.h" -extern int mysql_server_init(int, char * * argv, char * * groups); -# 419 "mysql.h" -extern int mysql_set_character_set(MYSQL * mysql, char const * csname); -# 472 "mysql.h" -extern void mysql_set_local_infile_default(MYSQL * mysql); -# 461 "mysql.h" -extern void mysql_set_local_infile_handler(MYSQL * mysql, int (* local_infile_init)(void * *, char const *, void *), int (* local_infile_read)(void *, char *, unsigned int), void (* local_infile_end)(void), int (* local_infile_error)(void *, char *, unsigned int), void *); -# 497 "mysql.h" -extern int mysql_set_master(MYSQL * mysql, char const * host, unsigned int, char const * user, char const * passwd); -# 513 "mysql.h" -extern int mysql_set_server_option(MYSQL * mysql, enum enum_mysql_set_option); -# 506 "mysql.h" -extern int mysql_shutdown(MYSQL * mysql, enum mysql_enum_shutdown_level); -# 450 "mysql.h" -extern my_bool mysql_slave_query(MYSQL * mysql, char const * q, unsigned long int); -# 452 "mysql.h" -extern my_bool mysql_slave_send_query(MYSQL * mysql, char const * q, unsigned long int); -# 414 "mysql.h" -extern char const * mysql_sqlstate(MYSQL * mysql); -# 422 "mysql.h" -extern my_bool mysql_ssl_set(MYSQL * mysql, char const * key, char const * cert, char const * ca, char const * capath, char const * cipher); -# 517 "mysql.h" -extern char const * mysql_stat(MYSQL * mysql); -# 817 "mysql.h" -extern my_ulonglong mysql_stmt_affected_rows(MYSQL_STMT * stmt); -# 795 "mysql.h" -extern my_bool mysql_stmt_attr_get(MYSQL_STMT * stmt, enum enum_stmt_attr_type, void * attr); -# 792 "mysql.h" -extern my_bool mysql_stmt_attr_set(MYSQL_STMT * stmt, enum enum_stmt_attr_type, void const * attr); -# 798 "mysql.h" -extern my_bool mysql_stmt_bind_param(MYSQL_STMT * stmt, MYSQL_BIND * bnd); -# 799 "mysql.h" -extern my_bool mysql_stmt_bind_result(MYSQL_STMT * stmt, MYSQL_BIND * bnd); -# 800 "mysql.h" -extern my_bool mysql_stmt_close(MYSQL_STMT * stmt); -# 815 "mysql.h" -extern void mysql_stmt_data_seek(MYSQL_STMT * stmt, my_ulonglong); -# 809 "mysql.h" -extern unsigned int mysql_stmt_errno(MYSQL_STMT * stmt); -# 810 "mysql.h" -extern char const * mysql_stmt_error(MYSQL_STMT * stmt); -# 785 "mysql.h" -extern int mysql_stmt_execute(MYSQL_STMT * stmt); -# 786 "mysql.h" -extern int mysql_stmt_fetch(MYSQL_STMT * stmt); -# 787 "mysql.h" -extern int mysql_stmt_fetch_column(MYSQL_STMT * stmt, MYSQL_BIND * bind, unsigned int, unsigned long int); -# 819 "mysql.h" -extern unsigned int mysql_stmt_field_count(MYSQL_STMT * stmt); -# 802 "mysql.h" -extern my_bool mysql_stmt_free_result(MYSQL_STMT * stmt); -# 782 "mysql.h" -extern MYSQL_STMT * mysql_stmt_init(MYSQL * mysql); -# 818 "mysql.h" -extern my_ulonglong mysql_stmt_insert_id(MYSQL_STMT * stmt); -# 816 "mysql.h" -extern my_ulonglong mysql_stmt_num_rows(MYSQL_STMT * stmt); -# 791 "mysql.h" -extern unsigned long int mysql_stmt_param_count(MYSQL_STMT * stmt); -# 808 "mysql.h" -extern MYSQL_RES * mysql_stmt_param_metadata(MYSQL_STMT * stmt); -# 783 "mysql.h" -extern int mysql_stmt_prepare(MYSQL_STMT * stmt, char const * query, unsigned long int); -# 801 "mysql.h" -extern my_bool mysql_stmt_reset(MYSQL_STMT * stmt); -# 807 "mysql.h" -extern MYSQL_RES * mysql_stmt_result_metadata(MYSQL_STMT * stmt); -# 812 "mysql.h" -extern MYSQL_ROW_OFFSET mysql_stmt_row_seek(MYSQL_STMT * stmt, MYSQL_ROW_OFFSET); -# 814 "mysql.h" -extern MYSQL_ROW_OFFSET mysql_stmt_row_tell(MYSQL_STMT * stmt); -# 803 "mysql.h" -extern my_bool mysql_stmt_send_long_data(MYSQL_STMT * stmt, unsigned int, char const * data, unsigned long int); -# 811 "mysql.h" -extern char const * mysql_stmt_sqlstate(MYSQL_STMT * stmt); -# 790 "mysql.h" -extern int mysql_stmt_store_result(MYSQL_STMT * stmt); -# 441 "mysql.h" -extern MYSQL_RES * mysql_store_result(MYSQL * mysql); -# 393 "mysql.h" -extern void mysql_thread_end(void); -# 417 "mysql.h" -extern unsigned long int mysql_thread_id(MYSQL * mysql); -# 392 "mysql.h" -extern my_bool mysql_thread_init(void); -# 560 "mysql.h" -extern unsigned int mysql_thread_safe(void); -# 76 "mysql.h" -extern char * mysql_unix_port; -# 442 "mysql.h" -extern MYSQL_RES * mysql_use_result(MYSQL * mysql); -# 415 "mysql.h" -extern unsigned int mysql_warning_count(MYSQL * mysql); -# 339 "mysql_com.h" -extern void net_clear(NET * net); -# 338 "mysql_com.h" -extern void net_end(NET * net); -# 341 "mysql_com.h" -extern my_bool net_flush(NET * net); -# 346 "mysql_com.h" -extern int net_real_write(NET * net, char const * packet, unsigned long int); -# 340 "mysql_com.h" -extern my_bool net_realloc(NET * net, unsigned long int); -# 343 "mysql_com.h" -extern my_bool net_write_command(NET * net, unsigned char, char const * header, unsigned long int, char const * packet, unsigned long int); # 427 "mysql_com.h" -extern char * octet2hex(char * to, char const * str, unsigned int); -# 408 "mysql_com.h" -extern void randominit(struct rand_struct *, unsigned long int, unsigned long int); -# 422 "mysql_com.h" -extern void scramble(char * to, char const * message, char const * password); +extern my_bool check_scramble(char const * reply, char const * message, unsigned char const * hash_stage2); +# 420 "mysql_com.h" +extern my_bool check_scramble_323(char const *, char const * message, unsigned long int * salt); +# 32 "typelib.h" +extern TYPELIB * copy_typelib(MEM_ROOT * root, TYPELIB * from); # 415 "mysql_com.h" +extern void create_random_string(char * to, unsigned int, struct rand_struct * rand_st); +# 29 "typelib.h" +extern int find_type(char * x, TYPELIB * typelib, unsigned int); +# 429 "mysql_com.h" +extern void get_salt_from_password(unsigned char * res, char const * password); +# 422 "mysql_com.h" +extern void get_salt_from_password_323(unsigned long int * res, char const * password); +# 435 "mysql_com.h" +extern char * get_tty_password(char * opt_message); +# 31 "typelib.h" +extern char const * get_type(TYPELIB * typelib, unsigned int); +# 417 "mysql_com.h" +extern void hash_password(unsigned long int * to, char const * password, unsigned int); +# 30 "my_list.h" +extern LIST * list_add(LIST * root, LIST * element); +# 32 "my_list.h" +extern LIST * list_cons(void * data, LIST * root); +# 31 "my_list.h" +extern LIST * list_delete(LIST * root, LIST * element); +# 34 "my_list.h" +extern void list_free(LIST * root, unsigned int); +# 35 "my_list.h" +extern unsigned int list_length(LIST *); +# 33 "my_list.h" +extern LIST * list_reverse(LIST * root); +# 36 "my_list.h" +extern int list_walk(LIST *, list_walk_action, gptr); +# 444 "mysql_com.h" +extern int load_defaults(char const * conf_file, char const * * groups, int * argc, char * * * argv); +# 430 "mysql_com.h" +extern void make_password_from_salt(char * to, unsigned char const * hash_stage2); +# 423 "mysql_com.h" +extern void make_password_from_salt_323(char * to, unsigned long int const * salt); +# 425 "mysql_com.h" +extern void make_scrambled_password(char * to, char const * password); +# 418 "mysql_com.h" +extern void make_scrambled_password_323(char * to, char const * password); +# 30 "typelib.h" +extern void make_type(char * to, unsigned int, TYPELIB * typelib); +# 441 "mysql_com.h" +extern int modify_defaults_file(char const * file_location, char const * option, char const * option_value, char const * section_name, int); +# 358 "mysql_com.h" +extern int my_connect(my_socket, struct sockaddr const * name, unsigned int, unsigned int); +# 440 "mysql_com.h" +extern my_bool my_init(void); +# 335 "mysql_com.h" +extern my_bool my_net_init(NET * net, Vio * vio); +# 336 "mysql_com.h" +extern void my_net_local_init(NET * net); +# 346 "mysql_com.h" +extern unsigned long int my_net_read(NET * net); +# 341 "mysql_com.h" +extern my_bool my_net_write(NET * net, char const * packet, unsigned long int); +# 414 "mysql_com.h" +extern double my_rnd(struct rand_struct *); +# 447 "mysql_com.h" +extern void my_thread_end(void); +# 446 "mysql_com.h" +extern my_bool my_thread_init(void); +# 553 "mysql.h" +extern void myodbc_remove_escape(MYSQL * mysql, char * name); +# 505 "mysql.h" +extern int mysql_add_slave(MYSQL * mysql, char const * host, unsigned int, char const * user, char const * passwd); +# 414 "mysql.h" +extern my_ulonglong mysql_affected_rows(MYSQL * mysql); +# 817 "mysql.h" +extern my_bool mysql_autocommit(MYSQL * mysql, my_bool); +# 430 "mysql.h" +extern my_bool mysql_change_user(MYSQL * mysql, char const * user, char const * passwd, char const * db); +# 422 "mysql.h" +extern char const * mysql_character_set_name(MYSQL * mysql); +# 820 "mysql.h" +extern void mysql_close(MYSQL * sock); +# 815 "mysql.h" +extern my_bool mysql_commit(MYSQL * mysql); +# 534 "mysql.h" +extern void mysql_data_seek(MYSQL_RES * result, my_ulonglong); +# 552 "mysql.h" +extern void mysql_debug(char const * debug); +# 491 "mysql.h" +extern void mysql_disable_reads_from_master(MYSQL * mysql); +# 485 "mysql.h" +extern void mysql_disable_rpl_parse(MYSQL * mysql); +# 513 "mysql.h" +extern int mysql_dump_debug_info(MYSQL * mysql); +# 555 "mysql.h" +extern my_bool mysql_embedded(void); +# 490 "mysql.h" +extern void mysql_enable_reads_from_master(MYSQL * mysql); +# 484 "mysql.h" +extern void mysql_enable_rpl_parse(MYSQL * mysql); +# 406 "mysql.h" +extern my_bool mysql_eof(MYSQL_RES * res); +# 416 "mysql.h" +extern unsigned int mysql_errno(MYSQL * mysql); +# 436 "mysql_com.h" +extern char const * mysql_errno_to_sqlstate(unsigned int); +# 417 "mysql.h" +extern char const * mysql_error(MYSQL * mysql); +# 545 "mysql.h" +extern unsigned long int mysql_escape_string(char * to, char const * from, unsigned long int); +# 542 "mysql.h" +extern MYSQL_FIELD * mysql_fetch_field(MYSQL_RES * result); +# 407 "mysql.h" +extern MYSQL_FIELD * mysql_fetch_field_direct(MYSQL_RES * res, unsigned int); +# 409 "mysql.h" +extern MYSQL_FIELD * mysql_fetch_fields(MYSQL_RES * res); +# 541 "mysql.h" +extern unsigned long int * mysql_fetch_lengths(MYSQL_RES * result); +# 540 "mysql.h" +extern MYSQL_ROW mysql_fetch_row(MYSQL_RES * result); +# 413 "mysql.h" +extern unsigned int mysql_field_count(MYSQL * mysql); +# 538 "mysql.h" +extern MYSQL_FIELD_OFFSET mysql_field_seek(MYSQL_RES * result, MYSQL_FIELD_OFFSET); +# 411 "mysql.h" +extern MYSQL_FIELD_OFFSET mysql_field_tell(MYSQL_RES * res); +# 533 "mysql.h" +extern void mysql_free_result(MYSQL_RES * result); +# 458 "mysql.h" +extern void mysql_get_character_set_info(MYSQL * mysql, MY_CHARSET_INFO * charset); +# 523 "mysql.h" +extern char const * mysql_get_client_info(void); +# 524 "mysql.h" +extern unsigned long int mysql_get_client_version(void); +# 525 "mysql.h" +extern char const * mysql_get_host_info(MYSQL * mysql); +# 388 "mysql.h" +extern MYSQL_PARAMETERS * mysql_get_parameters(void); +# 527 "mysql.h" +extern unsigned int mysql_get_proto_info(MYSQL * mysql); +# 522 "mysql.h" +extern char const * mysql_get_server_info(MYSQL * mysql); +# 526 "mysql.h" +extern unsigned long int mysql_get_server_version(MYSQL * mysql); +# 429 "mysql.h" +extern char const * mysql_get_ssl_cipher(MYSQL * mysql); +# 547 "mysql.h" +extern unsigned long int mysql_hex_string(char * to, char const * from, unsigned long int); +# 420 "mysql.h" +extern char const * mysql_info(MYSQL * mysql); +# 425 "mysql.h" +extern MYSQL * mysql_init(MYSQL * mysql); +# 415 "mysql.h" +extern my_ulonglong mysql_insert_id(MYSQL * mysql); +# 516 "mysql.h" +extern int mysql_kill(MYSQL * mysql, unsigned long int); +# 528 "mysql.h" +extern MYSQL_RES * mysql_list_dbs(MYSQL * mysql, char const * wild); +# 543 "mysql.h" +extern MYSQL_RES * mysql_list_fields(MYSQL * mysql, char const * table, char const * wild); +# 530 "mysql.h" +extern MYSQL_RES * mysql_list_processes(MYSQL * mysql); +# 529 "mysql.h" +extern MYSQL_RES * mysql_list_tables(MYSQL * mysql, char const * wild); +# 562 "mysql.h" +extern void mysql_manager_close(MYSQL_MANAGER * con); +# 563 "mysql.h" +extern int mysql_manager_command(MYSQL_MANAGER * con, char const * cmd, int); +# 557 "mysql.h" +extern MYSQL_MANAGER * mysql_manager_connect(MYSQL_MANAGER * con, char const * host, char const * user, char const * passwd, unsigned int); +# 565 "mysql.h" +extern int mysql_manager_fetch_line(MYSQL_MANAGER * con, char * res_buf, int); +# 556 "mysql.h" +extern MYSQL_MANAGER * mysql_manager_init(MYSQL_MANAGER * con); +# 449 "mysql.h" +extern my_bool mysql_master_query(MYSQL * mysql, char const * q, unsigned long int); +# 451 "mysql.h" +extern my_bool mysql_master_send_query(MYSQL * mysql, char const * q, unsigned long int); +# 818 "mysql.h" +extern my_bool mysql_more_results(MYSQL * mysql); +# 819 "mysql.h" +extern int mysql_next_result(MYSQL * mysql); +# 405 "mysql.h" +extern unsigned int mysql_num_fields(MYSQL_RES * res); +# 404 "mysql.h" +extern my_ulonglong mysql_num_rows(MYSQL_RES * res); +# 531 "mysql.h" +extern int mysql_options(MYSQL * mysql, enum mysql_option, char const * arg); +# 520 "mysql.h" +extern int mysql_ping(MYSQL * mysql); +# 78 "mysql.h" +extern unsigned int mysql_port; +# 440 "mysql.h" +extern int mysql_query(MYSQL * mysql, char const * q); +# 568 "mysql.h" +extern my_bool mysql_read_query_result(MYSQL * mysql); +# 493 "mysql.h" +extern my_bool mysql_reads_from_master_enabled(MYSQL * mysql); +# 432 "mysql.h" +extern MYSQL * mysql_real_connect(MYSQL * mysql, char const * host, char const * user, char const * passwd, char const * db, unsigned int, char const * unix_socket, unsigned long int); +# 549 "mysql.h" +extern unsigned long int mysql_real_escape_string(MYSQL * mysql, char * to, char const * from, unsigned long int); +# 443 "mysql.h" +extern int mysql_real_query(MYSQL * mysql, char const * q, unsigned long int); +# 514 "mysql.h" +extern int mysql_refresh(MYSQL * mysql, unsigned int); +# 816 "mysql.h" +extern my_bool mysql_rollback(MYSQL * mysql); +# 536 "mysql.h" +extern MYSQL_ROW_OFFSET mysql_row_seek(MYSQL_RES * result, MYSQL_ROW_OFFSET); +# 410 "mysql.h" +extern MYSQL_ROW_OFFSET mysql_row_tell(MYSQL_RES * res); +# 487 "mysql.h" +extern int mysql_rpl_parse_enabled(MYSQL * mysql); +# 498 "mysql.h" +extern my_bool mysql_rpl_probe(MYSQL * mysql); +# 495 "mysql.h" +extern enum mysql_rpl_type mysql_rpl_query_type(char const * q, int); +# 439 "mysql.h" +extern int mysql_select_db(MYSQL * mysql, char const * db); +# 441 "mysql.h" +extern int mysql_send_query(MYSQL * mysql, char const * q, unsigned long int); +# 375 "mysql.h" +extern void mysql_server_end(void); +# 374 "mysql.h" +extern int mysql_server_init(int, char * * argv, char * * groups); +# 423 "mysql.h" +extern int mysql_set_character_set(MYSQL * mysql, char const * csname); +# 476 "mysql.h" +extern void mysql_set_local_infile_default(MYSQL * mysql); +# 465 "mysql.h" +extern void mysql_set_local_infile_handler(MYSQL * mysql, int (* local_infile_init)(void * *, char const *, void *), int (* local_infile_read)(void *, char *, unsigned int), void (* local_infile_end)(void), int (* local_infile_error)(void *, char *, unsigned int), void *); +# 501 "mysql.h" +extern int mysql_set_master(MYSQL * mysql, char const * host, unsigned int, char const * user, char const * passwd); +# 517 "mysql.h" +extern int mysql_set_server_option(MYSQL * mysql, enum enum_mysql_set_option); +# 510 "mysql.h" +extern int mysql_shutdown(MYSQL * mysql, enum mysql_enum_shutdown_level); +# 454 "mysql.h" +extern my_bool mysql_slave_query(MYSQL * mysql, char const * q, unsigned long int); +# 456 "mysql.h" +extern my_bool mysql_slave_send_query(MYSQL * mysql, char const * q, unsigned long int); +# 418 "mysql.h" +extern char const * mysql_sqlstate(MYSQL * mysql); +# 426 "mysql.h" +extern my_bool mysql_ssl_set(MYSQL * mysql, char const * key, char const * cert, char const * ca, char const * capath, char const * cipher); +# 521 "mysql.h" +extern char const * mysql_stat(MYSQL * mysql); +# 811 "mysql.h" +extern my_ulonglong mysql_stmt_affected_rows(MYSQL_STMT * stmt); +# 789 "mysql.h" +extern my_bool mysql_stmt_attr_get(MYSQL_STMT * stmt, enum enum_stmt_attr_type, void * attr); +# 786 "mysql.h" +extern my_bool mysql_stmt_attr_set(MYSQL_STMT * stmt, enum enum_stmt_attr_type, void const * attr); +# 792 "mysql.h" +extern my_bool mysql_stmt_bind_param(MYSQL_STMT * stmt, MYSQL_BIND * bnd); +# 793 "mysql.h" +extern my_bool mysql_stmt_bind_result(MYSQL_STMT * stmt, MYSQL_BIND * bnd); +# 794 "mysql.h" +extern my_bool mysql_stmt_close(MYSQL_STMT * stmt); +# 809 "mysql.h" +extern void mysql_stmt_data_seek(MYSQL_STMT * stmt, my_ulonglong); +# 803 "mysql.h" +extern unsigned int mysql_stmt_errno(MYSQL_STMT * stmt); +# 804 "mysql.h" +extern char const * mysql_stmt_error(MYSQL_STMT * stmt); +# 779 "mysql.h" +extern int mysql_stmt_execute(MYSQL_STMT * stmt); +# 780 "mysql.h" +extern int mysql_stmt_fetch(MYSQL_STMT * stmt); +# 781 "mysql.h" +extern int mysql_stmt_fetch_column(MYSQL_STMT * stmt, MYSQL_BIND * bind_arg, unsigned int, unsigned long int); +# 813 "mysql.h" +extern unsigned int mysql_stmt_field_count(MYSQL_STMT * stmt); +# 796 "mysql.h" +extern my_bool mysql_stmt_free_result(MYSQL_STMT * stmt); +# 776 "mysql.h" +extern MYSQL_STMT * mysql_stmt_init(MYSQL * mysql); +# 812 "mysql.h" +extern my_ulonglong mysql_stmt_insert_id(MYSQL_STMT * stmt); +# 810 "mysql.h" +extern my_ulonglong mysql_stmt_num_rows(MYSQL_STMT * stmt); +# 785 "mysql.h" +extern unsigned long int mysql_stmt_param_count(MYSQL_STMT * stmt); +# 802 "mysql.h" +extern MYSQL_RES * mysql_stmt_param_metadata(MYSQL_STMT * stmt); +# 777 "mysql.h" +extern int mysql_stmt_prepare(MYSQL_STMT * stmt, char const * query, unsigned long int); +# 795 "mysql.h" +extern my_bool mysql_stmt_reset(MYSQL_STMT * stmt); +# 801 "mysql.h" +extern MYSQL_RES * mysql_stmt_result_metadata(MYSQL_STMT * stmt); +# 806 "mysql.h" +extern MYSQL_ROW_OFFSET mysql_stmt_row_seek(MYSQL_STMT * stmt, MYSQL_ROW_OFFSET); +# 808 "mysql.h" +extern MYSQL_ROW_OFFSET mysql_stmt_row_tell(MYSQL_STMT * stmt); +# 797 "mysql.h" +extern my_bool mysql_stmt_send_long_data(MYSQL_STMT * stmt, unsigned int, char const * data, unsigned long int); +# 805 "mysql.h" +extern char const * mysql_stmt_sqlstate(MYSQL_STMT * stmt); +# 784 "mysql.h" +extern int mysql_stmt_store_result(MYSQL_STMT * stmt); +# 445 "mysql.h" +extern MYSQL_RES * mysql_store_result(MYSQL * mysql); +# 397 "mysql.h" +extern void mysql_thread_end(void); +# 421 "mysql.h" +extern unsigned long int mysql_thread_id(MYSQL * mysql); +# 396 "mysql.h" +extern my_bool mysql_thread_init(void); +# 554 "mysql.h" +extern unsigned int mysql_thread_safe(void); +# 79 "mysql.h" +extern char * mysql_unix_port; +# 446 "mysql.h" +extern MYSQL_RES * mysql_use_result(MYSQL * mysql); +# 419 "mysql.h" +extern unsigned int mysql_warning_count(MYSQL * mysql); +# 338 "mysql_com.h" +extern void net_clear(NET * net); +# 337 "mysql_com.h" +extern void net_end(NET * net); +# 340 "mysql_com.h" +extern my_bool net_flush(NET * net); +# 345 "mysql_com.h" +extern int net_real_write(NET * net, char const * packet, unsigned long int); +# 339 "mysql_com.h" +extern my_bool net_realloc(NET * net, unsigned long int); +# 342 "mysql_com.h" +extern my_bool net_write_command(NET * net, unsigned char, char const * header, unsigned long int, char const * packet, unsigned long int); +# 431 "mysql_com.h" +extern char * octet2hex(char * to, char const * str, unsigned int); +# 412 "mysql_com.h" +extern void randominit(struct rand_struct *, unsigned long int, unsigned long int); +# 426 "mysql_com.h" +extern void scramble(char * to, char const * message, char const * password); +# 419 "mysql_com.h" extern void scramble_323(char * to, char const * message, char const * password); -# 35 "typelib.h" +# 34 "typelib.h" extern TYPELIB sql_protocol_typelib; diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 85509b49fdd..4afc3ec5925 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -1617,78 +1617,6 @@ mysql_real_escape_string(MYSQL *mysql, char *to,const char *from, return escape_string_for_mysql(mysql->charset, to, 0, from, length); } - -char * STDCALL -mysql_odbc_escape_string(MYSQL *mysql, - char *to, ulong to_length, - const char *from, ulong from_length, - void *param, - char * (*extend_buffer) - (void *, char *, ulong *)) -{ - char *to_end=to+to_length-5; - const char *end; -#ifdef USE_MB - my_bool use_mb_flag=use_mb(mysql->charset); -#endif - - for (end=from+from_length; from != end ; from++) - { - if (to >= to_end) - { - to_length = (ulong) (end-from)+512; /* We want this much more */ - if (!(to=(*extend_buffer)(param, to, &to_length))) - return to; - to_end=to+to_length-5; - } -#ifdef USE_MB - { - int l; - if (use_mb_flag && (l = my_ismbchar(mysql->charset, from, end))) - { - while (l--) - *to++ = *from++; - from--; - continue; - } - } -#endif - switch (*from) { - case 0: /* Must be escaped for 'mysql' */ - *to++= '\\'; - *to++= '0'; - break; - case '\n': /* Must be escaped for logs */ - *to++= '\\'; - *to++= 'n'; - break; - case '\r': - *to++= '\\'; - *to++= 'r'; - break; - case '\\': - *to++= '\\'; - *to++= '\\'; - break; - case '\'': - *to++= '\\'; - *to++= '\''; - break; - case '"': /* Better safe than sorry */ - *to++= '\\'; - *to++= '"'; - break; - case '\032': /* This gives problems on Win32 */ - *to++= '\\'; - *to++= 'Z'; - break; - default: - *to++= *from; - } - } - return to; -} - void STDCALL myodbc_remove_escape(MYSQL *mysql,char *name) { diff --git a/libmysql/libmysql.def b/libmysql/libmysql.def index 8c6b71d9553..81f86dc8726 100644 --- a/libmysql/libmysql.def +++ b/libmysql/libmysql.def @@ -78,7 +78,6 @@ EXPORTS mysql_next_result mysql_num_fields mysql_num_rows - mysql_odbc_escape_string mysql_options mysql_stmt_param_count mysql_stmt_param_metadata diff --git a/libmysqld/libmysqld.def b/libmysqld/libmysqld.def index 8829112fefd..8aed164a30e 100644 --- a/libmysqld/libmysqld.def +++ b/libmysqld/libmysqld.def @@ -71,7 +71,6 @@ EXPORTS mysql_next_result mysql_num_fields mysql_num_rows - mysql_odbc_escape_string mysql_options mysql_ping mysql_query From 345650212c9113e5c966307259db8698fced7bf7 Mon Sep 17 00:00:00 2001 From: "thek@adventure.(none)" <> Date: Mon, 26 Nov 2007 19:09:40 +0100 Subject: [PATCH 15/16] Bug#16470 crash on grant if old grant tables Loading 4.1 into 5.0 or 5.1 failed silently because procs_priv table missing. This caused the server to crash on any attempt to store new grants because of uninitialized structures. This patch breaks up the grant loading function into two phases to allow for procs_priv table to fail with an warning instead of crashing the server. --- mysql-test/r/grant.result | 19 +++ mysql-test/t/grant.test | 20 +++ sql/sql_acl.cc | 322 ++++++++++++++++++++++++-------------- sql/sql_parse.cc | 31 ++-- 4 files changed, 260 insertions(+), 132 deletions(-) diff --git a/mysql-test/r/grant.result b/mysql-test/r/grant.result index 0d4dad39882..7a7e90b2280 100644 --- a/mysql-test/r/grant.result +++ b/mysql-test/r/grant.result @@ -1223,3 +1223,22 @@ drop user юзер_юзер@localhost; grant select on test.* to очень_длинный_юзер@localhost; ERROR HY000: String 'очень_длинный_юзер' is too long for user name (should be no longer than 16) set names default; +FLUSH PRIVILEGES without procs_priv table. +RENAME TABLE mysql.procs_priv TO mysql.procs_gone; +FLUSH PRIVILEGES; +Warnings: +Error 1146 Table 'mysql.procs_priv' doesn't exist +Error 1547 Cannot load from mysql.mysql.procs_priv. The table is probably corrupted +Assigning privileges without procs_priv table. +CREATE DATABASE mysqltest1; +CREATE PROCEDURE mysqltest1.test() SQL SECURITY DEFINER +SELECT 1; +GRANT EXECUTE ON FUNCTION mysqltest1.test TO mysqltest_1@localhost; +ERROR 42S02: Table 'mysql.procs_priv' doesn't exist +GRANT ALL PRIVILEGES ON test.* TO mysqltest_1@localhost; +CALL mysqltest1.test(); +1 +1 +DROP DATABASE mysqltest1; +RENAME TABLE mysql.procs_gone TO mysql.procs_priv; +FLUSH PRIVILEGES; diff --git a/mysql-test/t/grant.test b/mysql-test/t/grant.test index e33712e1ebf..8e060ef5ca9 100644 --- a/mysql-test/t/grant.test +++ b/mysql-test/t/grant.test @@ -1274,3 +1274,23 @@ drop user юзер_юзер@localhost; --error ER_WRONG_STRING_LENGTH grant select on test.* to очень_длинный_юзер@localhost; set names default; + + +# +# Bug #16470 crash on grant if old grant tables +# +--echo FLUSH PRIVILEGES without procs_priv table. +RENAME TABLE mysql.procs_priv TO mysql.procs_gone; +FLUSH PRIVILEGES; +--echo Assigning privileges without procs_priv table. +CREATE DATABASE mysqltest1; +CREATE PROCEDURE mysqltest1.test() SQL SECURITY DEFINER + SELECT 1; +--error ER_NO_SUCH_TABLE +GRANT EXECUTE ON FUNCTION mysqltest1.test TO mysqltest_1@localhost; +GRANT ALL PRIVILEGES ON test.* TO mysqltest_1@localhost; +CALL mysqltest1.test(); +DROP DATABASE mysqltest1; +RENAME TABLE mysql.procs_gone TO mysql.procs_priv; +FLUSH PRIVILEGES; + diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 7e017d7d028..39df07a0cfa 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -3471,16 +3471,13 @@ void grant_free(void) } -/* - Initialize structures responsible for table/column-level privilege checking - and load information for them from tables in the 'mysql' database. +/** + @brief Initialize structures responsible for table/column-level privilege + checking and load information for them from tables in the 'mysql' database. - SYNOPSIS - grant_init() - - RETURN VALUES - 0 ok - 1 Could not initialize grant's + @return Error status + @retval 0 OK + @retval 1 Could not initialize grant subsystem. */ my_bool grant_init() @@ -3501,50 +3498,136 @@ my_bool grant_init() } -/* - Initialize structures responsible for table/column-level privilege - checking and load information about grants from open privilege tables. +/** + @brief Helper function to grant_reload_procs_priv - SYNOPSIS - grant_load() - thd Current thread - tables List containing open "mysql.tables_priv" and - "mysql.columns_priv" tables. + Reads the procs_priv table into memory hash. - RETURN VALUES - FALSE - success - TRUE - error + @param table A pointer to the procs_priv table structure. + + @see grant_reload + @see grant_reload_procs_priv + + @return Error state + @retval TRUE An error occurred + @retval FALSE Success +*/ + +static my_bool grant_load_procs_priv(TABLE *p_table) +{ + MEM_ROOT *memex_ptr; + my_bool return_val= 1; + bool check_no_resolve= specialflag & SPECIAL_NO_RESOLVE; + MEM_ROOT **save_mem_root_ptr= my_pthread_getspecific_ptr(MEM_ROOT**, + THR_MALLOC); + DBUG_ENTER("grant_load"); + (void) hash_init(&proc_priv_hash,system_charset_info, + 0,0,0, (hash_get_key) get_grant_table, + 0,0); + (void) hash_init(&func_priv_hash,system_charset_info, + 0,0,0, (hash_get_key) get_grant_table, + 0,0); + p_table->file->ha_index_init(0, 1); + p_table->use_all_columns(); + + if (!p_table->file->index_first(p_table->record[0])) + { + memex_ptr= &memex; + my_pthread_setspecific_ptr(THR_MALLOC, &memex_ptr); + do + { + GRANT_NAME *mem_check; + HASH *hash; + if (!(mem_check=new (memex_ptr) GRANT_NAME(p_table))) + { + /* This could only happen if we are out memory */ + goto end_unlock; + } + + if (check_no_resolve) + { + if (hostname_requires_resolving(mem_check->host.hostname)) + { + sql_print_warning("'procs_priv' entry '%s %s@%s' " + "ignored in --skip-name-resolve mode.", + mem_check->tname, mem_check->user, + mem_check->host.hostname ? + mem_check->host.hostname : ""); + continue; + } + } + if (p_table->field[4]->val_int() == TYPE_ENUM_PROCEDURE) + { + hash= &proc_priv_hash; + } + else + if (p_table->field[4]->val_int() == TYPE_ENUM_FUNCTION) + { + hash= &func_priv_hash; + } + else + { + sql_print_warning("'procs_priv' entry '%s' " + "ignored, bad routine type", + mem_check->tname); + continue; + } + + mem_check->privs= fix_rights_for_procedure(mem_check->privs); + if (! mem_check->ok()) + delete mem_check; + else if (my_hash_insert(hash, (uchar*) mem_check)) + { + delete mem_check; + goto end_unlock; + } + } + while (!p_table->file->index_next(p_table->record[0])); + } + /* Return ok */ + return_val= 0; + +end_unlock: + p_table->file->ha_index_end(); + my_pthread_setspecific_ptr(THR_MALLOC, save_mem_root_ptr); + DBUG_RETURN(return_val); +} + + +/** + @brief Initialize structures responsible for table/column-level privilege + checking and load information about grants from open privilege tables. + + @param thd Current thread + @param tables List containing open "mysql.tables_priv" and + "mysql.columns_priv" tables. + + @see grant_reload + + @return Error state + @retval FALSE Success + @retval TRUE Error */ static my_bool grant_load(TABLE_LIST *tables) { MEM_ROOT *memex_ptr; my_bool return_val= 1; - TABLE *t_table, *c_table, *p_table; + TABLE *t_table= 0, *c_table= 0; bool check_no_resolve= specialflag & SPECIAL_NO_RESOLVE; MEM_ROOT **save_mem_root_ptr= my_pthread_getspecific_ptr(MEM_ROOT**, THR_MALLOC); DBUG_ENTER("grant_load"); - (void) hash_init(&column_priv_hash,system_charset_info, - 0,0,0, (hash_get_key) get_grant_table, - (hash_free_key) free_grant_table,0); - (void) hash_init(&proc_priv_hash,system_charset_info, - 0,0,0, (hash_get_key) get_grant_table, - 0,0); - (void) hash_init(&func_priv_hash,system_charset_info, - 0,0,0, (hash_get_key) get_grant_table, - 0,0); - init_sql_alloc(&memex, ACL_ALLOC_BLOCK_SIZE, 0); + 0,0,0, (hash_get_key) get_grant_table, + (hash_free_key) free_grant_table,0); t_table = tables[0].table; c_table = tables[1].table; - p_table= tables[2].table; t_table->file->ha_index_init(0, 1); - p_table->file->ha_index_init(0, 1); t_table->use_all_columns(); c_table->use_all_columns(); - p_table->use_all_columns(); + if (!t_table->file->index_first(t_table->record[0])) { memex_ptr= &memex; @@ -3582,92 +3665,91 @@ static my_bool grant_load(TABLE_LIST *tables) } while (!t_table->file->index_next(t_table->record[0])); } - if (!p_table->file->index_first(p_table->record[0])) - { - memex_ptr= &memex; - my_pthread_setspecific_ptr(THR_MALLOC, &memex_ptr); - do - { - GRANT_NAME *mem_check; - HASH *hash; - if (!(mem_check=new (&memex) GRANT_NAME(p_table))) - { - /* This could only happen if we are out memory */ - goto end_unlock; - } - if (check_no_resolve) - { - if (hostname_requires_resolving(mem_check->host.hostname)) - { - sql_print_warning("'procs_priv' entry '%s %s@%s' " - "ignored in --skip-name-resolve mode.", - mem_check->tname, mem_check->user, - mem_check->host.hostname ? - mem_check->host.hostname : ""); - continue; - } - } - if (p_table->field[4]->val_int() == TYPE_ENUM_PROCEDURE) - { - hash= &proc_priv_hash; - } - else - if (p_table->field[4]->val_int() == TYPE_ENUM_FUNCTION) - { - hash= &func_priv_hash; - } - else - { - sql_print_warning("'procs_priv' entry '%s' " - "ignored, bad routine type", - mem_check->tname); - continue; - } - - mem_check->privs= fix_rights_for_procedure(mem_check->privs); - if (! mem_check->ok()) - delete mem_check; - else if (my_hash_insert(hash, (uchar*) mem_check)) - { - delete mem_check; - goto end_unlock; - } - } - while (!p_table->file->index_next(p_table->record[0])); - } return_val=0; // Return ok end_unlock: t_table->file->ha_index_end(); - p_table->file->ha_index_end(); my_pthread_setspecific_ptr(THR_MALLOC, save_mem_root_ptr); DBUG_RETURN(return_val); } -/* - Reload information about table and column level privileges if possible. +/** + @brief Helper function to grant_reload. Reloads procs_priv table is it + exists. - SYNOPSIS - grant_reload() - thd Current thread + @param thd A pointer to the thread handler object. - NOTES - Locked tables are checked by acl_reload() and doesn't have to be checked - in this call. - This function is also used for initialization of structures responsible - for table/column-level privilege checking. + @see grant_reload - RETURN VALUE - FALSE Success - TRUE Error + @return Error state + @retval FALSE Success + @retval TRUE An error has occurred. +*/ + +static my_bool grant_reload_procs_priv(THD *thd) +{ + HASH old_proc_priv_hash, old_func_priv_hash; + TABLE_LIST table; + my_bool return_val= FALSE; + DBUG_ENTER("grant_reload_procs_priv"); + + bzero((char*) &table, sizeof(table)); + table.alias= table.table_name= (char*) "procs_priv"; + table.db= (char *) "mysql"; + table.lock_type= TL_READ; + + if (simple_open_n_lock_tables(thd, &table)) + { + close_thread_tables(thd); + DBUG_RETURN(TRUE); + } + + /* Save a copy of the current hash if we need to undo the grant load */ + old_proc_priv_hash= proc_priv_hash; + old_func_priv_hash= func_priv_hash; + + rw_wrlock(&LOCK_grant); + if ((return_val= grant_load_procs_priv(table.table))) + { + /* Error; Reverting to old hash */ + DBUG_PRINT("error",("Reverting to old privileges")); + grant_free(); + proc_priv_hash= old_proc_priv_hash; + func_priv_hash= old_func_priv_hash; + } + else + { + hash_free(&old_proc_priv_hash); + hash_free(&old_func_priv_hash); + } + rw_unlock(&LOCK_grant); + + close_thread_tables(thd); + DBUG_RETURN(return_val); +} + + +/** + @brief Reload information about table and column level privileges if possible + + @param thd Current thread + + Locked tables are checked by acl_reload() and doesn't have to be checked + in this call. + This function is also used for initialization of structures responsible + for table/column-level privilege checking. + + @return Error state + @retval FALSE Success + @retval TRUE Error */ my_bool grant_reload(THD *thd) { - TABLE_LIST tables[3]; - HASH old_column_priv_hash, old_proc_priv_hash, old_func_priv_hash; + TABLE_LIST tables[2]; + HASH old_column_priv_hash; MEM_ROOT old_mem; my_bool return_val= 1; DBUG_ENTER("grant_reload"); @@ -3679,11 +3761,9 @@ my_bool grant_reload(THD *thd) bzero((char*) tables, sizeof(tables)); tables[0].alias= tables[0].table_name= (char*) "tables_priv"; tables[1].alias= tables[1].table_name= (char*) "columns_priv"; - tables[2].alias= tables[2].table_name= (char*) "procs_priv"; - tables[0].db= tables[1].db= tables[2].db= (char *) "mysql"; + tables[0].db= tables[1].db= (char *) "mysql"; tables[0].next_local= tables[0].next_global= tables+1; - tables[1].next_local= tables[1].next_global= tables+2; - tables[0].lock_type= tables[1].lock_type= tables[2].lock_type= TL_READ; + tables[0].lock_type= tables[1].lock_type= TL_READ; /* To avoid deadlocks we should obtain table locks before @@ -3693,35 +3773,45 @@ my_bool grant_reload(THD *thd) goto end; rw_wrlock(&LOCK_grant); - grant_version++; old_column_priv_hash= column_priv_hash; - old_proc_priv_hash= proc_priv_hash; - old_func_priv_hash= func_priv_hash; + + /* + Create a new memory pool but save the current memory pool to make an undo + opertion possible in case of failure. + */ old_mem= memex; + init_sql_alloc(&memex, ACL_ALLOC_BLOCK_SIZE, 0); if ((return_val= grant_load(tables))) { // Error. Revert to old hash DBUG_PRINT("error",("Reverting to old privileges")); grant_free(); /* purecov: deadcode */ column_priv_hash= old_column_priv_hash; /* purecov: deadcode */ - proc_priv_hash= old_proc_priv_hash; - func_priv_hash= old_func_priv_hash; memex= old_mem; /* purecov: deadcode */ } else { hash_free(&old_column_priv_hash); - hash_free(&old_proc_priv_hash); - hash_free(&old_func_priv_hash); free_root(&old_mem,MYF(0)); } rw_unlock(&LOCK_grant); -end: close_thread_tables(thd); + + /* + It is ok failing to load procs_priv table because we may be + working with 4.1 privilege tables. + */ + if (grant_reload_procs_priv(thd)) + my_error(ER_CANNOT_LOAD_FROM_TABLE, MYF(0), "mysql.procs_priv"); + + rw_wrlock(&LOCK_grant); + grant_version++; + rw_unlock(&LOCK_grant); + +end: DBUG_RETURN(return_val); } - /**************************************************************************** Check table level grants diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 695e923e816..4e4b30adb3b 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -6293,24 +6293,23 @@ void add_join_natural(TABLE_LIST *a, TABLE_LIST *b, List *using_fields, } -/* - Reload/resets privileges and the different caches. +/** + @brief Reload/resets privileges and the different caches. - SYNOPSIS - reload_acl_and_cache() - thd Thread handler (can be NULL!) - options What should be reset/reloaded (tables, privileges, - slave...) - tables Tables to flush (if any) - write_to_binlog Depending on 'options', it may be very bad to write the - query to the binlog (e.g. FLUSH SLAVE); this is a - pointer where reload_acl_and_cache() will put 0 if - it thinks we really should not write to the binlog. - Otherwise it will put 1. + @param thd Thread handler (can be NULL!) + @param options What should be reset/reloaded (tables, privileges, slave...) + @param tables Tables to flush (if any) + @param write_to_binlog True if we can write to the binlog. - RETURN - 0 ok - !=0 error. thd->killed or thd->net.report_error is set + @note Depending on 'options', it may be very bad to write the + query to the binlog (e.g. FLUSH SLAVE); this is a + pointer where reload_acl_and_cache() will put 0 if + it thinks we really should not write to the binlog. + Otherwise it will put 1. + + @return Error status code + @retval 0 Ok + @retval !=0 Error; thd->killed or thd->net.report_error is set */ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables, From 906697768cb5928be9eaeedbf2ac0df8ac612109 Mon Sep 17 00:00:00 2001 From: "thek@adventure.(none)" <> Date: Wed, 28 Nov 2007 09:03:21 +0100 Subject: [PATCH 16/16] Error number increased; fixing broken number. --- mysql-test/r/grant.result | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/r/grant.result b/mysql-test/r/grant.result index 34f6e0b4379..0d40778d5f2 100644 --- a/mysql-test/r/grant.result +++ b/mysql-test/r/grant.result @@ -1231,7 +1231,7 @@ RENAME TABLE mysql.procs_priv TO mysql.procs_gone; FLUSH PRIVILEGES; Warnings: Error 1146 Table 'mysql.procs_priv' doesn't exist -Error 1547 Cannot load from mysql.mysql.procs_priv. The table is probably corrupted +Error 1548 Cannot load from mysql.mysql.procs_priv. The table is probably corrupted Assigning privileges without procs_priv table. CREATE DATABASE mysqltest1; CREATE PROCEDURE mysqltest1.test() SQL SECURITY DEFINER