diff --git a/include/mysql.h b/include/mysql.h index 68cce3196a0..d114afb6c93 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -557,16 +557,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 12e16df878a..4bedb9e8050 100644 --- a/include/mysql_h.ic +++ b/include/mysql_h.ic @@ -54,7 +54,7 @@ typedef struct st_list LIST; typedef struct st_mem_root MEM_ROOT; # 258 "mysql.h" typedef struct st_mysql MYSQL; -# 664 "mysql.h" +# 654 "mysql.h" typedef struct st_mysql_bind MYSQL_BIND; # 95 "mysql.h" typedef struct st_mysql_field MYSQL_FIELD; @@ -72,17 +72,17 @@ typedef struct st_mysql_res MYSQL_RES; typedef char * * MYSQL_ROW; # 145 "mysql.h" typedef MYSQL_ROWS * MYSQL_ROW_OFFSET; -# 693 "mysql.h" +# 683 "mysql.h" typedef struct st_mysql_stmt MYSQL_STMT; # 52 "mysql/plugin.h" typedef struct st_mysql_xid MYSQL_XID; # 243 "mysql.h" typedef struct character_set MY_CHARSET_INFO; -# 187 "mysql_com.h" +# 188 "mysql_com.h" typedef struct st_net NET; # 22 "typelib.h" typedef struct st_typelib TYPELIB; -# 177 "mysql_com.h" +# 178 "mysql_com.h" typedef struct st_vio Vio; # 28 "my_list.h" typedef int (* list_walk_action)(void *, void *); @@ -92,7 +92,7 @@ typedef char my_bool; typedef int my_socket; # 128 "mysql.h" typedef unsigned long long int my_ulonglong; -# 214 "/usr/lib/gcc/i486-linux-gnu/4.1.2/include/stddef.h" +# 214 "/usr/lib/gcc/i486-linux-gnu/4.1.3/include/stddef.h" typedef unsigned int size_t; # 149 "mysql.h" typedef struct embedded_query_result EMBEDDED_QUERY_RESULT; @@ -102,13 +102,13 @@ typedef struct st_mysql_data MYSQL_DATA; typedef struct st_mysql_ftparser_boolean_info MYSQL_FTPARSER_BOOLEAN_INFO; # 557 "mysql/plugin.h" typedef struct st_mysql_ftparser_param MYSQL_FTPARSER_PARAM; -# 763 "mysql.h" +# 753 "mysql.h" typedef struct st_mysql_methods MYSQL_METHODS; # 47 "mysql_time.h" typedef struct st_mysql_time MYSQL_TIME; -# 383 "mysql_com.h" +# 384 "mysql_com.h" typedef struct st_udf_args UDF_ARGS; -# 397 "mysql_com.h" +# 398 "mysql_com.h" typedef struct st_udf_init UDF_INIT; # 26 "my_alloc.h" typedef struct st_used_mem USED_MEM; @@ -130,7 +130,7 @@ struct __attribute__((aligned(__alignof__(unsigned int)), aligned(__alignof__(vo unsigned int mbminlen; unsigned int mbmaxlen; }; -# 369 "mysql_com.h" +# 370 "mysql_com.h" struct __attribute__((aligned(__alignof__(unsigned long int)), aligned(__alignof__(double)))) rand_struct { unsigned long int seed1; @@ -203,7 +203,7 @@ struct __attribute__((aligned(__alignof__(void *)), aligned(__alignof__(unsigned char * info_buffer; void * extension; }; -# 664 "mysql.h" +# 654 "mysql.h" struct __attribute__((aligned(__alignof__(void *)), aligned(__alignof__(unsigned long int)))) st_mysql_bind { unsigned long int * length; @@ -328,7 +328,7 @@ struct __attribute__((aligned(__alignof__(void *)), aligned(__alignof__(unsigned char last_error[256]; void * extension; }; -# 763 "mysql.h" +# 753 "mysql.h" struct __attribute__((aligned(__alignof__(void *)))) st_mysql_methods { my_bool (* read_query_result)(MYSQL * mysql); @@ -448,7 +448,7 @@ struct __attribute__((aligned(__alignof__(void *)))) st_mysql_show_var char * value; enum enum_mysql_show_type type; }; -# 693 "mysql.h" +# 683 "mysql.h" struct __attribute__((aligned(__alignof__(void *)), aligned(__alignof__(unsigned long long int)))) st_mysql_stmt { MEM_ROOT mem_root; @@ -513,7 +513,7 @@ struct __attribute__((aligned(__alignof__(long int)))) st_mysql_xid long int bqual_length; char data[128]; }; -# 187 "mysql_com.h" +# 188 "mysql_com.h" struct __attribute__((aligned(__alignof__(void *)), aligned(__alignof__(unsigned long int)))) st_net { Vio * vio; @@ -558,7 +558,7 @@ struct __attribute__((aligned(__alignof__(unsigned int)), aligned(__alignof__(vo char const * * type_names; unsigned int * type_lengths; }; -# 383 "mysql_com.h" +# 384 "mysql_com.h" struct __attribute__((aligned(__alignof__(unsigned int)), aligned(__alignof__(void *)))) st_udf_args { unsigned int arg_count; @@ -570,7 +570,7 @@ struct __attribute__((aligned(__alignof__(unsigned int)), aligned(__alignof__(vo unsigned long int * attribute_lengths; void * extension; }; -# 397 "mysql_com.h" +# 398 "mysql_com.h" struct __attribute__((aligned(__alignof__(unsigned long int)), aligned(__alignof__(void *)))) st_udf_init { my_bool maybe_null; @@ -587,7 +587,7 @@ struct __attribute__((aligned(__alignof__(void *)), aligned(__alignof__(unsigned unsigned int left; unsigned int size; }; -# 380 "mysql_com.h" +# 381 "mysql_com.h" enum Item_result { STRING_RESULT = 0, @@ -596,7 +596,7 @@ enum Item_result ROW_RESULT = 3, DECIMAL_RESULT = 4, }; -# 321 "mysql_com.h" +# 322 "mysql_com.h" enum enum_cursor_type { CURSOR_TYPE_NO_CURSOR = 0, @@ -604,7 +604,7 @@ enum enum_cursor_type CURSOR_TYPE_FOR_UPDATE = 2, CURSOR_TYPE_SCROLLABLE = 4, }; -# 234 "mysql_com.h" +# 235 "mysql_com.h" enum enum_field_types { MYSQL_TYPE_DECIMAL = 0, @@ -651,7 +651,7 @@ enum enum_ftparser_mode MYSQL_FTPARSER_WITH_STOPWORDS = 1, MYSQL_FTPARSER_FULL_BOOLEAN_INFO = 2, }; -# 331 "mysql_com.h" +# 332 "mysql_com.h" enum enum_mysql_set_option { MYSQL_OPTION_MULTI_STATEMENTS_ON = 0, @@ -671,7 +671,7 @@ enum enum_mysql_show_type SHOW_FUNC = 8, SHOW_DOUBLE = 9, }; -# 594 "mysql.h" +# 584 "mysql.h" enum enum_mysql_stmt_state { MYSQL_STMT_INIT_DONE = 1, @@ -723,14 +723,14 @@ enum enum_server_command COM_DAEMON = 29, COM_END = 30, }; -# 740 "mysql.h" +# 730 "mysql.h" enum enum_stmt_attr_type { STMT_ATTR_UPDATE_MAX_LENGTH = 0, STMT_ATTR_CURSOR_TYPE = 1, STMT_ATTR_PREFETCH_ROWS = 2, }; -# 296 "mysql_com.h" +# 297 "mysql_com.h" enum mysql_enum_shutdown_level { SHUTDOWN_DEFAULT = 0, @@ -790,13 +790,13 @@ enum mysql_status MYSQL_STATUS_GET_RESULT = 1, MYSQL_STATUS_USE_RESULT = 2, }; -# 438 "mysql_com.h" +# 439 "mysql_com.h" extern my_bool check_scramble(char const * reply, char const * message, unsigned char const * hash_stage2); -# 431 "mysql_com.h" +# 432 "mysql_com.h" extern my_bool check_scramble_323(char const *, char const * message, unsigned long int * salt); # 35 "typelib.h" extern TYPELIB * copy_typelib(MEM_ROOT * root, TYPELIB * from); -# 426 "mysql_com.h" +# 427 "mysql_com.h" extern void create_random_string(char * to, unsigned int, struct rand_struct * rand_st); # 32 "typelib.h" extern int find_type(char * x, TYPELIB const * typelib, unsigned int); @@ -804,15 +804,15 @@ extern int find_type(char * x, TYPELIB const * typelib, unsigned int); extern int find_type_or_exit(char const * x, TYPELIB * typelib, char const * option); # 29 "typelib.h" extern my_ulonglong find_typeset(char * x, TYPELIB * typelib, int * error_position); -# 440 "mysql_com.h" +# 441 "mysql_com.h" extern void get_salt_from_password(unsigned char * res, char const * password); -# 433 "mysql_com.h" +# 434 "mysql_com.h" extern void get_salt_from_password_323(unsigned long int * res, char const * password); -# 446 "mysql_com.h" +# 447 "mysql_com.h" extern char * get_tty_password(char const * opt_message); # 34 "typelib.h" extern char const * get_type(TYPELIB * typelib, unsigned int); -# 428 "mysql_com.h" +# 429 "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); @@ -828,47 +828,47 @@ extern unsigned int list_length(LIST *); extern LIST * list_reverse(LIST * root); # 36 "my_list.h" extern int list_walk(LIST *, list_walk_action, unsigned char * argument); -# 441 "mysql_com.h" +# 442 "mysql_com.h" extern void make_password_from_salt(char * to, unsigned char const * hash_stage2); -# 434 "mysql_com.h" +# 435 "mysql_com.h" extern void make_password_from_salt_323(char * to, unsigned long int const * salt); -# 436 "mysql_com.h" +# 437 "mysql_com.h" extern void make_scrambled_password(char * to, char const * password); -# 429 "mysql_com.h" +# 430 "mysql_com.h" extern void make_scrambled_password_323(char * to, char const * password); # 33 "typelib.h" extern void make_type(char * to, unsigned int, TYPELIB * typelib); -# 366 "mysql_com.h" +# 367 "mysql_com.h" extern int my_connect(my_socket, struct sockaddr const * name, unsigned int, unsigned int); -# 343 "mysql_com.h" -extern my_bool my_net_init(NET * net, Vio * vio); # 344 "mysql_com.h" +extern my_bool my_net_init(NET * net, Vio * vio); +# 345 "mysql_com.h" extern void my_net_local_init(NET * net); -# 354 "mysql_com.h" +# 355 "mysql_com.h" extern unsigned long int my_net_read(NET * net); -# 349 "mysql_com.h" +# 350 "mysql_com.h" extern my_bool my_net_write(NET * net, unsigned char const * packet, size_t); -# 425 "mysql_com.h" +# 426 "mysql_com.h" extern double my_rnd(struct rand_struct *); -# 452 "mysql_com.h" +# 453 "mysql_com.h" extern void my_thread_end(void); -# 451 "mysql_com.h" +# 452 "mysql_com.h" extern my_bool my_thread_init(void); -# 570 "mysql.h" +# 560 "mysql.h" extern void myodbc_remove_escape(MYSQL * mysql, char * name); # 512 "mysql.h" extern int mysql_add_slave(MYSQL * mysql, char const * host, unsigned int, char const * user, char const * passwd); # 421 "mysql.h" extern my_ulonglong mysql_affected_rows(MYSQL * mysql); -# 836 "mysql.h" +# 826 "mysql.h" extern my_bool mysql_autocommit(MYSQL * mysql, my_bool); # 437 "mysql.h" extern my_bool mysql_change_user(MYSQL * mysql, char const * user, char const * passwd, char const * db); # 429 "mysql.h" extern char const * mysql_character_set_name(MYSQL * mysql); -# 839 "mysql.h" +# 829 "mysql.h" extern void mysql_close(MYSQL * sock); -# 834 "mysql.h" +# 824 "mysql.h" extern my_bool mysql_commit(MYSQL * mysql); # 541 "mysql.h" extern void mysql_data_seek(MYSQL_RES * result, my_ulonglong); @@ -880,7 +880,7 @@ extern void mysql_disable_reads_from_master(MYSQL * mysql); extern void mysql_disable_rpl_parse(MYSQL * mysql); # 520 "mysql.h" extern int mysql_dump_debug_info(MYSQL * mysql); -# 572 "mysql.h" +# 562 "mysql.h" extern my_bool mysql_embedded(void); # 497 "mysql.h" extern void mysql_enable_reads_from_master(MYSQL * mysql); @@ -890,7 +890,7 @@ extern void mysql_enable_rpl_parse(MYSQL * mysql); extern my_bool mysql_eof(MYSQL_RES * res); # 423 "mysql.h" extern unsigned int mysql_errno(MYSQL * mysql); -# 447 "mysql_com.h" +# 448 "mysql_com.h" extern char const * mysql_errno_to_sqlstate(unsigned int); # 424 "mysql.h" extern char const * mysql_error(MYSQL * mysql); @@ -950,30 +950,28 @@ extern MYSQL_RES * mysql_list_fields(MYSQL * mysql, char const * table, char con extern MYSQL_RES * mysql_list_processes(MYSQL * mysql); # 536 "mysql.h" extern MYSQL_RES * mysql_list_tables(MYSQL * mysql, char const * wild); -# 579 "mysql.h" +# 569 "mysql.h" extern void mysql_manager_close(MYSQL_MANAGER * con); -# 580 "mysql.h" +# 570 "mysql.h" extern int mysql_manager_command(MYSQL_MANAGER * con, char const * cmd, int); -# 574 "mysql.h" +# 564 "mysql.h" extern MYSQL_MANAGER * mysql_manager_connect(MYSQL_MANAGER * con, char const * host, char const * user, char const * passwd, unsigned int); -# 582 "mysql.h" +# 572 "mysql.h" extern int mysql_manager_fetch_line(MYSQL_MANAGER * con, char * res_buf, int); -# 573 "mysql.h" +# 563 "mysql.h" extern MYSQL_MANAGER * mysql_manager_init(MYSQL_MANAGER * con); # 456 "mysql.h" extern my_bool mysql_master_query(MYSQL * mysql, char const * q, unsigned long int); # 458 "mysql.h" extern my_bool mysql_master_send_query(MYSQL * mysql, char const * q, unsigned long int); -# 837 "mysql.h" +# 827 "mysql.h" extern my_bool mysql_more_results(MYSQL * mysql); -# 838 "mysql.h" +# 828 "mysql.h" extern int mysql_next_result(MYSQL * mysql); # 412 "mysql.h" extern unsigned int mysql_num_fields(MYSQL_RES * res); # 411 "mysql.h" extern my_ulonglong mysql_num_rows(MYSQL_RES * res); -# 560 "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)); # 538 "mysql.h" extern int mysql_options(MYSQL * mysql, enum mysql_option, void const * arg); # 527 "mysql.h" @@ -984,7 +982,7 @@ extern unsigned int mysql_port; extern int mysql_query(MYSQL * mysql, char const * q); # 780 "mysql/plugin.h" extern void mysql_query_cache_invalidate4(void * thd, char const * key, unsigned int, int); -# 585 "mysql.h" +# 575 "mysql.h" extern my_bool mysql_read_query_result(MYSQL * mysql); # 500 "mysql.h" extern my_bool mysql_reads_from_master_enabled(MYSQL * mysql); @@ -996,7 +994,7 @@ extern unsigned long int mysql_real_escape_string(MYSQL * mysql, char * to, char extern int mysql_real_query(MYSQL * mysql, char const * q, unsigned long int); # 521 "mysql.h" extern int mysql_refresh(MYSQL * mysql, unsigned int); -# 835 "mysql.h" +# 825 "mysql.h" extern my_bool mysql_rollback(MYSQL * mysql); # 543 "mysql.h" extern MYSQL_ROW_OFFSET mysql_row_seek(MYSQL_RES * result, MYSQL_ROW_OFFSET); @@ -1038,59 +1036,59 @@ extern char const * mysql_sqlstate(MYSQL * mysql); extern my_bool mysql_ssl_set(MYSQL * mysql, char const * key, char const * cert, char const * ca, char const * capath, char const * cipher); # 528 "mysql.h" extern char const * mysql_stat(MYSQL * mysql); -# 830 "mysql.h" -extern my_ulonglong mysql_stmt_affected_rows(MYSQL_STMT * stmt); -# 808 "mysql.h" -extern my_bool mysql_stmt_attr_get(MYSQL_STMT * stmt, enum enum_stmt_attr_type, void * attr); -# 805 "mysql.h" -extern my_bool mysql_stmt_attr_set(MYSQL_STMT * stmt, enum enum_stmt_attr_type, void const * attr); -# 811 "mysql.h" -extern my_bool mysql_stmt_bind_param(MYSQL_STMT * stmt, MYSQL_BIND * bnd); -# 812 "mysql.h" -extern my_bool mysql_stmt_bind_result(MYSQL_STMT * stmt, MYSQL_BIND * bnd); -# 813 "mysql.h" -extern my_bool mysql_stmt_close(MYSQL_STMT * stmt); -# 828 "mysql.h" -extern void mysql_stmt_data_seek(MYSQL_STMT * stmt, my_ulonglong); -# 822 "mysql.h" -extern unsigned int mysql_stmt_errno(MYSQL_STMT * stmt); -# 823 "mysql.h" -extern char const * mysql_stmt_error(MYSQL_STMT * stmt); -# 798 "mysql.h" -extern int mysql_stmt_execute(MYSQL_STMT * stmt); -# 799 "mysql.h" -extern int mysql_stmt_fetch(MYSQL_STMT * stmt); -# 800 "mysql.h" -extern int mysql_stmt_fetch_column(MYSQL_STMT * stmt, MYSQL_BIND * bind_arg, unsigned int, unsigned long int); -# 832 "mysql.h" -extern unsigned int mysql_stmt_field_count(MYSQL_STMT * stmt); -# 815 "mysql.h" -extern my_bool mysql_stmt_free_result(MYSQL_STMT * stmt); -# 795 "mysql.h" -extern MYSQL_STMT * mysql_stmt_init(MYSQL * mysql); -# 831 "mysql.h" -extern my_ulonglong mysql_stmt_insert_id(MYSQL_STMT * stmt); -# 829 "mysql.h" -extern my_ulonglong mysql_stmt_num_rows(MYSQL_STMT * stmt); -# 804 "mysql.h" -extern unsigned long int mysql_stmt_param_count(MYSQL_STMT * stmt); -# 821 "mysql.h" -extern MYSQL_RES * mysql_stmt_param_metadata(MYSQL_STMT * stmt); -# 796 "mysql.h" -extern int mysql_stmt_prepare(MYSQL_STMT * stmt, char const * query, unsigned long int); -# 814 "mysql.h" -extern my_bool mysql_stmt_reset(MYSQL_STMT * stmt); # 820 "mysql.h" -extern MYSQL_RES * mysql_stmt_result_metadata(MYSQL_STMT * stmt); -# 825 "mysql.h" -extern MYSQL_ROW_OFFSET mysql_stmt_row_seek(MYSQL_STMT * stmt, MYSQL_ROW_OFFSET); -# 827 "mysql.h" -extern MYSQL_ROW_OFFSET mysql_stmt_row_tell(MYSQL_STMT * stmt); -# 816 "mysql.h" -extern my_bool mysql_stmt_send_long_data(MYSQL_STMT * stmt, unsigned int, char const * data, unsigned long int); -# 824 "mysql.h" -extern char const * mysql_stmt_sqlstate(MYSQL_STMT * stmt); +extern my_ulonglong mysql_stmt_affected_rows(MYSQL_STMT * stmt); +# 798 "mysql.h" +extern my_bool mysql_stmt_attr_get(MYSQL_STMT * stmt, enum enum_stmt_attr_type, void * attr); +# 795 "mysql.h" +extern my_bool mysql_stmt_attr_set(MYSQL_STMT * stmt, enum enum_stmt_attr_type, void const * attr); +# 801 "mysql.h" +extern my_bool mysql_stmt_bind_param(MYSQL_STMT * stmt, MYSQL_BIND * bnd); +# 802 "mysql.h" +extern my_bool mysql_stmt_bind_result(MYSQL_STMT * stmt, MYSQL_BIND * bnd); # 803 "mysql.h" +extern my_bool mysql_stmt_close(MYSQL_STMT * stmt); +# 818 "mysql.h" +extern void mysql_stmt_data_seek(MYSQL_STMT * stmt, my_ulonglong); +# 812 "mysql.h" +extern unsigned int mysql_stmt_errno(MYSQL_STMT * stmt); +# 813 "mysql.h" +extern char const * mysql_stmt_error(MYSQL_STMT * stmt); +# 788 "mysql.h" +extern int mysql_stmt_execute(MYSQL_STMT * stmt); +# 789 "mysql.h" +extern int mysql_stmt_fetch(MYSQL_STMT * stmt); +# 790 "mysql.h" +extern int mysql_stmt_fetch_column(MYSQL_STMT * stmt, MYSQL_BIND * bind_arg, unsigned int, unsigned long int); +# 822 "mysql.h" +extern unsigned int mysql_stmt_field_count(MYSQL_STMT * stmt); +# 805 "mysql.h" +extern my_bool mysql_stmt_free_result(MYSQL_STMT * stmt); +# 785 "mysql.h" +extern MYSQL_STMT * mysql_stmt_init(MYSQL * mysql); +# 821 "mysql.h" +extern my_ulonglong mysql_stmt_insert_id(MYSQL_STMT * stmt); +# 819 "mysql.h" +extern my_ulonglong mysql_stmt_num_rows(MYSQL_STMT * stmt); +# 794 "mysql.h" +extern unsigned long int mysql_stmt_param_count(MYSQL_STMT * stmt); +# 811 "mysql.h" +extern MYSQL_RES * mysql_stmt_param_metadata(MYSQL_STMT * stmt); +# 786 "mysql.h" +extern int mysql_stmt_prepare(MYSQL_STMT * stmt, char const * query, unsigned long int); +# 804 "mysql.h" +extern my_bool mysql_stmt_reset(MYSQL_STMT * stmt); +# 810 "mysql.h" +extern MYSQL_RES * mysql_stmt_result_metadata(MYSQL_STMT * stmt); +# 815 "mysql.h" +extern MYSQL_ROW_OFFSET mysql_stmt_row_seek(MYSQL_STMT * stmt, MYSQL_ROW_OFFSET); +# 817 "mysql.h" +extern MYSQL_ROW_OFFSET mysql_stmt_row_tell(MYSQL_STMT * stmt); +# 806 "mysql.h" +extern my_bool mysql_stmt_send_long_data(MYSQL_STMT * stmt, unsigned int, char const * data, unsigned long int); +# 814 "mysql.h" +extern char const * mysql_stmt_sqlstate(MYSQL_STMT * stmt); +# 793 "mysql.h" extern int mysql_stmt_store_result(MYSQL_STMT * stmt); # 452 "mysql.h" extern MYSQL_RES * mysql_store_result(MYSQL * mysql); @@ -1100,7 +1098,7 @@ extern void mysql_thread_end(void); extern unsigned long int mysql_thread_id(MYSQL * mysql); # 403 "mysql.h" extern my_bool mysql_thread_init(void); -# 571 "mysql.h" +# 561 "mysql.h" extern unsigned int mysql_thread_safe(void); # 699 "mysql/plugin.h" extern int mysql_tmpfile(char const * prefix); @@ -1110,25 +1108,25 @@ extern char * mysql_unix_port; extern MYSQL_RES * mysql_use_result(MYSQL * mysql); # 426 "mysql.h" extern unsigned int mysql_warning_count(MYSQL * mysql); -# 346 "mysql_com.h" -extern void net_clear(NET * net, my_bool); -# 345 "mysql_com.h" -extern void net_end(NET * net); -# 348 "mysql_com.h" -extern my_bool net_flush(NET * net); -# 353 "mysql_com.h" -extern int net_real_write(NET * net, unsigned char const * packet, size_t); # 347 "mysql_com.h" +extern void net_clear(NET * net, my_bool); +# 346 "mysql_com.h" +extern void net_end(NET * net); +# 349 "mysql_com.h" +extern my_bool net_flush(NET * net); +# 354 "mysql_com.h" +extern int net_real_write(NET * net, unsigned char const * packet, size_t); +# 348 "mysql_com.h" extern my_bool net_realloc(NET * net, size_t); -# 350 "mysql_com.h" +# 351 "mysql_com.h" extern my_bool net_write_command(NET * net, unsigned char, unsigned char const * header, size_t, unsigned char const * packet, size_t); -# 442 "mysql_com.h" +# 443 "mysql_com.h" extern char * octet2hex(char * to, char const * str, unsigned int); -# 423 "mysql_com.h" +# 424 "mysql_com.h" extern void randominit(struct rand_struct *, unsigned long int, unsigned long int); -# 437 "mysql_com.h" +# 438 "mysql_com.h" extern void scramble(char * to, char const * message, char const * password); -# 430 "mysql_com.h" +# 431 "mysql_com.h" extern void scramble_323(char * to, char const * message, char const * password); # 37 "typelib.h" extern TYPELIB sql_protocol_typelib; diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index cb326fa4685..bf5dd7d63eb 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -1629,78 +1629,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 78ff08e510a..2aa75c0b23c 100644 --- a/libmysqld/libmysqld.def +++ b/libmysqld/libmysqld.def @@ -78,7 +78,6 @@ EXPORTS mysql_next_result mysql_num_fields mysql_num_rows - mysql_odbc_escape_string mysql_options mysql_ping mysql_query 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/events_bugs.result b/mysql-test/r/events_bugs.result index 83609856393..b91e7e88d64 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/r/flush.result b/mysql-test/r/flush.result index dcbffd6f7c8..f1b6c471943 100644 --- a/mysql-test/r/flush.result +++ b/mysql-test/r/flush.result @@ -55,6 +55,23 @@ 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; End of 5.0 tests set @old_general_log= @@general_log; set @old_read_only= @@read_only; diff --git a/mysql-test/r/grant.result b/mysql-test/r/grant.result index 4d402d7d0e9..0d40778d5f2 100644 --- a/mysql-test/r/grant.result +++ b/mysql-test/r/grant.result @@ -1226,3 +1226,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 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 +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/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/mysql-test/r/kill.result b/mysql-test/r/kill.result index a08be429a83..3ea5bbd20bc 100644 --- a/mysql-test/r/kill.result +++ b/mysql-test/r/kill.result @@ -125,3 +125,14 @@ 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(); +# CR_SERVER_LOST, CR_SERVER_GONE_ERROR, depending on the timing +# of close of the connection socket +SELECT 1; +Got one of the listed errors diff --git a/mysql-test/r/log_tables.result b/mysql-test/r/log_tables.result index a31f2047670..0a7634df85a 100644 --- a/mysql-test/r/log_tables.result +++ b/mysql-test/r/log_tables.result @@ -605,6 +605,7 @@ DROP PROCEDURE IF EXISTS `db_17876.archiveGeneralLog`; DROP DATABASE IF EXISTS `db_17876`; SET GLOBAL general_log = @old_general_log_state; SET GLOBAL slow_query_log = @old_slow_log_state; +select CONNECTION_ID() into @thread_id; truncate table mysql.general_log; set @old_general_log_state = @@global.general_log; set global general_log = on; @@ -711,7 +712,7 @@ set @lparam = "000 001 002 003 004 005 006 007 008 009" prepare long_query from "select ? as long_query"; execute long_query using @lparam; set global general_log = off; -select command_type, argument from mysql.general_log; +select command_type, argument from mysql.general_log where thread_id = @thread_id; command_type argument Query set @lparam = "000 001 002 003 004 005 006 007 008 009" "010 011 012 013 014 015 016 017 018 019" 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/r/parser.result b/mysql-test/r/parser.result index 76326f65f08..ef53f227ec0 100644 --- a/mysql-test/r/parser.result +++ b/mysql-test/r/parser.result @@ -484,3 +484,46 @@ select atan(10, 20 "p2"); ERROR 42000: Incorrect parameters in the call to native function 'atan' select atan(10 AS p1, 20 AS p2); ERROR 42000: Incorrect parameters in the call to native function 'atan' +DROP TABLE IF EXISTS t1; +SELECT STR_TO_DATE('10:00 PM', '%h:%i %p') + INTERVAL 10 MINUTE; +STR_TO_DATE('10:00 PM', '%h:%i %p') + INTERVAL 10 MINUTE +NULL +SELECT STR_TO_DATE('10:00 PM', '%h:%i %p') + INTERVAL (INTERVAL(1,2,3) + 1) MINUTE; +STR_TO_DATE('10:00 PM', '%h:%i %p') + INTERVAL (INTERVAL(1,2,3) + 1) MINUTE +NULL +SELECT "1997-12-31 23:59:59" + INTERVAL 1 SECOND; +"1997-12-31 23:59:59" + INTERVAL 1 SECOND +1998-01-01 00:00:00 +SELECT 1 + INTERVAL(1,0,1,2) + 1; +1 + INTERVAL(1,0,1,2) + 1 +4 +SELECT INTERVAL(1^1,0,1,2) + 1; +INTERVAL(1^1,0,1,2) + 1 +2 +SELECT INTERVAL(1,0+1,2,3) * 5.5; +INTERVAL(1,0+1,2,3) * 5.5 +5.5 +SELECT INTERVAL(3,3,1+3,4+4) / 0.5; +INTERVAL(3,3,1+3,4+4) / 0.5 +2.0000 +SELECT (INTERVAL(1,0,1,2) + 5) * 7 + INTERVAL(1,0,1,2) / 2; +(INTERVAL(1,0,1,2) + 5) * 7 + INTERVAL(1,0,1,2) / 2 +50.0000 +SELECT INTERVAL(1,0,1,2) + 1, 5 * INTERVAL(1,0,1,2); +INTERVAL(1,0,1,2) + 1 5 * INTERVAL(1,0,1,2) +3 10 +SELECT INTERVAL(0,(1*5)/2) + INTERVAL(5,4,3); +INTERVAL(0,(1*5)/2) + INTERVAL(5,4,3) +2 +SELECT 1^1 + INTERVAL 1+1 SECOND & 1 + INTERVAL 1+1 SECOND; +1^1 + INTERVAL 1+1 SECOND & 1 + INTERVAL 1+1 SECOND +NULL +SELECT 1%2 - INTERVAL 1^1 SECOND | 1%2 - INTERVAL 1^1 SECOND; +1%2 - INTERVAL 1^1 SECOND | 1%2 - INTERVAL 1^1 SECOND +NULL +CREATE TABLE t1 (a INT, b DATETIME); +INSERT INTO t1 VALUES (INTERVAL(3,2,1) + 1, "1997-12-31 23:59:59" + INTERVAL 1 SECOND); +SELECT * FROM t1 WHERE a = INTERVAL(3,2,1) + 1; +a b +3 1998-01-01 00:00:00 +DROP TABLE t1; diff --git a/mysql-test/r/skip_grants.result b/mysql-test/r/skip_grants.result index cd652c03f96..bf0f16a174f 100644 --- a/mysql-test/r/skip_grants.result +++ b/mysql-test/r/skip_grants.result @@ -77,3 +77,10 @@ ERROR HY000: Can't initialize function 'a'; UDFs are unavailable with the --skip DROP FUNCTION a; ERROR 42000: FUNCTION test.a does not exist End of 5.0 tests +# +# 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 +End of 5.1 tests diff --git a/mysql-test/r/trigger.result b/mysql-test/r/trigger.result index d322d4cda76..8b384dfdc4e 100644 --- a/mysql-test/r/trigger.result +++ b/mysql-test/r/trigger.result @@ -1981,4 +1981,39 @@ drop table table_25411_b; DROP TRIGGER IF EXISTS trg; SHOW CREATE TRIGGER trg; ERROR HY000: Trigger does not exist +drop table if exists t1; +create table t1 (i int, j int); +create trigger t1_bi before insert on t1 for each row begin end; +create trigger t1_bi before insert on t1 for each row begin end; +ERROR 42000: This version of MySQL doesn't yet support 'multiple triggers with the same action time and event for one table' +drop trigger t1_bi; +drop trigger t1_bi; +ERROR HY000: Trigger does not exist +lock tables t1 read; +create trigger t1_bi before insert on t1 for each row begin end; +ERROR HY000: Table 't1' was locked with a READ lock and can't be updated +create trigger t1_bi before insert on t1 for each row begin end; +ERROR HY000: Table 't1' was locked with a READ lock and can't be updated +drop trigger t1_bi; +ERROR HY000: Trigger does not exist +unlock tables; +create trigger t1_bi before insert on t1 for each row begin end; +lock tables t1 read; +create trigger t1_bi before insert on t1 for each row begin end; +ERROR HY000: Table 't1' was locked with a READ lock and can't be updated +drop trigger t1_bi; +ERROR HY000: Table 't1' was locked with a READ lock and can't be updated +unlock tables; +drop trigger t1_bi; +lock tables t1 write; +create trigger b1_bi before insert on t1 for each row set new.i = new.i + 10; +insert into t1 values (10, 10); +drop trigger b1_bi; +insert into t1 values (10, 10); +select * from t1; +i j +20 10 +10 10 +unlock tables; +drop table t1; End of 5.1 tests. diff --git a/mysql-test/r/trigger-grant.result b/mysql-test/r/trigger_notembedded.result similarity index 99% rename from mysql-test/r/trigger-grant.result rename to mysql-test/r/trigger_notembedded.result index 14b8c98f2fa..d56f83993a6 100644 --- a/mysql-test/r/trigger-grant.result +++ b/mysql-test/r/trigger_notembedded.result @@ -448,3 +448,4 @@ DROP TABLE t1; DROP DATABASE mysqltest_db1; USE test; End of 5.0 tests. +End of 5.1 tests. diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 60c3ff68e67..2971af7347d 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -3617,4 +3617,47 @@ DROP TABLE `t-2`; DROP VIEW `v-2`; DROP DATABASE `d-1`; USE test; + +# +# Bug#26676: VIEW using old table schema in a session. +# + +DROP VIEW IF EXISTS v1; +DROP TABLE IF EXISTS t1; +CREATE TABLE t1(c1 INT, c2 INT); +INSERT INTO t1 VALUES (1, 2), (3, 4); + +SELECT * FROM t1; +c1 c2 +1 2 +3 4 + +CREATE VIEW v1 AS SELECT * FROM t1; + +SELECT * FROM v1; +c1 c2 +1 2 +3 4 + +ALTER TABLE t1 ADD COLUMN c3 INT AFTER c2; + +SELECT * FROM t1; +c1 c2 c3 +1 2 NULL +3 4 NULL + +SELECT * FROM v1; +c1 c2 +1 2 +3 4 + +SHOW CREATE VIEW v1; +View Create View character_set_client collation_connection +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`c1` AS `c1`,`t1`.`c2` AS `c2` from `t1` latin1 latin1_swedish_ci + +DROP VIEW v1; +DROP TABLE t1; + +# End of test case for Bug#26676. + End of 5.1 tests. diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index 3746d20ebd8..42fa242c7e1 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -19,7 +19,8 @@ events : Bug#32664 events.test fails randomly events_scheduling : Bug#29830 Test case 'events_scheduling' fails on Mac OS X and Windows lowercase_table3 : Bug#32667 lowercase_table3.test reports to error log kill : Bug#29149: Test "kill" fails on Windows -grant3 : Bug#32723: grant3.test fails innodb_mysql : Bug#32724: innodb_mysql.test fails randomly wait_timeout : Bug#32801 wait_timeout.test fails randomly kill : Bug#29149 Test "kill" fails on Windows +ctype_create : Bug#32965 main.ctype_create fails +status : Bug#32966 main.status fails 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/mysql-test/t/flush.test b/mysql-test/t/flush.test index d58d038c3ea..794423ca211 100644 --- a/mysql-test/t/flush.test +++ b/mysql-test/t/flush.test @@ -133,6 +133,37 @@ 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; + --echo End of 5.0 tests # diff --git a/mysql-test/t/grant.test b/mysql-test/t/grant.test index 8d909d63f51..2a1940f4326 100644 --- a/mysql-test/t/grant.test +++ b/mysql-test/t/grant.test @@ -1277,3 +1277,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/mysql-test/t/information_schema.test b/mysql-test/t/information_schema.test index 2dd19a94758..f08d216da27 100644 --- a/mysql-test/t/information_schema.test +++ b/mysql-test/t/information_schema.test @@ -1143,6 +1143,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 diff --git a/mysql-test/t/kill.test b/mysql-test/t/kill.test index 5d5095f7d61..3da4232502d 100644 --- a/mysql-test/t/kill.test +++ b/mysql-test/t/kill.test @@ -304,3 +304,21 @@ 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(); + +--echo # CR_SERVER_LOST, CR_SERVER_GONE_ERROR, depending on the timing +--echo # of close of the connection socket +--error 2013, 2006 +SELECT 1; diff --git a/mysql-test/t/log_tables.test b/mysql-test/t/log_tables.test index f02138fb30b..0c986c6d63a 100644 --- a/mysql-test/t/log_tables.test +++ b/mysql-test/t/log_tables.test @@ -811,6 +811,7 @@ SET GLOBAL slow_query_log = @old_slow_log_state; # Bug#21557 entries in the general query log truncated at 1000 characters. # +select CONNECTION_ID() into @thread_id; truncate table mysql.general_log; set @old_general_log_state = @@global.general_log; set global general_log = on; @@ -921,7 +922,7 @@ prepare long_query from "select ? as long_query"; execute long_query using @lparam; --enable_result_log set global general_log = off; -select command_type, argument from mysql.general_log; +select command_type, argument from mysql.general_log where thread_id = @thread_id; deallocate prepare long_query; set global general_log = @old_general_log_state; 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/mysql-test/t/parser.test b/mysql-test/t/parser.test index 79c9129bb74..9170308a4f2 100644 --- a/mysql-test/t/parser.test +++ b/mysql-test/t/parser.test @@ -629,3 +629,31 @@ select atan(10, 20 "p2"); -- error ER_WRONG_PARAMETERS_TO_NATIVE_FCT select atan(10 AS p1, 20 AS p2); +# +# Bug#22312 Syntax error in expression with INTERVAL() +# + +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings + +SELECT STR_TO_DATE('10:00 PM', '%h:%i %p') + INTERVAL 10 MINUTE; +SELECT STR_TO_DATE('10:00 PM', '%h:%i %p') + INTERVAL (INTERVAL(1,2,3) + 1) MINUTE; +SELECT "1997-12-31 23:59:59" + INTERVAL 1 SECOND; +SELECT 1 + INTERVAL(1,0,1,2) + 1; +SELECT INTERVAL(1^1,0,1,2) + 1; +SELECT INTERVAL(1,0+1,2,3) * 5.5; +SELECT INTERVAL(3,3,1+3,4+4) / 0.5; +SELECT (INTERVAL(1,0,1,2) + 5) * 7 + INTERVAL(1,0,1,2) / 2; +SELECT INTERVAL(1,0,1,2) + 1, 5 * INTERVAL(1,0,1,2); +SELECT INTERVAL(0,(1*5)/2) + INTERVAL(5,4,3); + +--disable_warnings +SELECT 1^1 + INTERVAL 1+1 SECOND & 1 + INTERVAL 1+1 SECOND; +SELECT 1%2 - INTERVAL 1^1 SECOND | 1%2 - INTERVAL 1^1 SECOND; +--enable_warnings + +CREATE TABLE t1 (a INT, b DATETIME); +INSERT INTO t1 VALUES (INTERVAL(3,2,1) + 1, "1997-12-31 23:59:59" + INTERVAL 1 SECOND); +SELECT * FROM t1 WHERE a = INTERVAL(3,2,1) + 1; +DROP TABLE t1; diff --git a/mysql-test/t/skip_grants.test b/mysql-test/t/skip_grants.test index 018366f705f..72a073ac541 100644 --- a/mysql-test/t/skip_grants.test +++ b/mysql-test/t/skip_grants.test @@ -122,7 +122,6 @@ 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; - # # Bug #32020: loading udfs while --skip-grant-tables is enabled causes out of # memory errors @@ -134,3 +133,12 @@ CREATE FUNCTION a RETURNS STRING SONAME ''; DROP FUNCTION a; --echo End of 5.0 tests + +--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); + +--echo End of 5.1 tests 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 diff --git a/mysql-test/t/trigger.test b/mysql-test/t/trigger.test index e1037d8bf9c..1aeac91e5ad 100644 --- a/mysql-test/t/trigger.test +++ b/mysql-test/t/trigger.test @@ -2257,4 +2257,51 @@ DROP TRIGGER IF EXISTS trg; --error ER_TRG_DOES_NOT_EXIST SHOW CREATE TRIGGER trg; +# +# Bug#23713 LOCK TABLES + CREATE TRIGGER + FLUSH TABLES WITH READ LOCK = deadlock +# +# Test of trigger creation and removal under LOCK TABLES +# + +--disable_warnings +drop table if exists t1; +--enable_warnings + +create table t1 (i int, j int); + +create trigger t1_bi before insert on t1 for each row begin end; +--error ER_NOT_SUPPORTED_YET +create trigger t1_bi before insert on t1 for each row begin end; +drop trigger t1_bi; +--error ER_TRG_DOES_NOT_EXIST +drop trigger t1_bi; + +lock tables t1 read; +--error ER_TABLE_NOT_LOCKED_FOR_WRITE +create trigger t1_bi before insert on t1 for each row begin end; +--error ER_TABLE_NOT_LOCKED_FOR_WRITE +create trigger t1_bi before insert on t1 for each row begin end; +--error ER_TRG_DOES_NOT_EXIST +drop trigger t1_bi; +unlock tables; + +create trigger t1_bi before insert on t1 for each row begin end; +lock tables t1 read; +--error ER_TABLE_NOT_LOCKED_FOR_WRITE +create trigger t1_bi before insert on t1 for each row begin end; +--error ER_TABLE_NOT_LOCKED_FOR_WRITE +drop trigger t1_bi; +unlock tables; +drop trigger t1_bi; + +lock tables t1 write; +create trigger b1_bi before insert on t1 for each row set new.i = new.i + 10; +insert into t1 values (10, 10); +drop trigger b1_bi; +insert into t1 values (10, 10); +select * from t1; +unlock tables; + +drop table t1; + --echo End of 5.1 tests. diff --git a/mysql-test/t/trigger-grant.test b/mysql-test/t/trigger_notembedded.test similarity index 96% rename from mysql-test/t/trigger-grant.test rename to mysql-test/t/trigger_notembedded.test index 8145212ed5b..748ae6e1c27 100644 --- a/mysql-test/t/trigger-grant.test +++ b/mysql-test/t/trigger_notembedded.test @@ -875,3 +875,37 @@ DROP DATABASE mysqltest_db1; USE test; --echo End of 5.0 tests. + +# +# Bug#23713 LOCK TABLES + CREATE TRIGGER + FLUSH TABLES WITH READ LOCK = deadlock +# + +# Test temporarily disable due to Bug#32395 +--disable_parsing +create table t1 (i int); +connect (flush,localhost,root,,test,,); +connection default; +--echo connection: default +lock tables t1 write; +connection flush; +--echo connection: flush +--send flush tables with read lock; +connection default; +--echo connection: default +let $wait_condition= + select count(*) = 1 from information_schema.processlist + where state = "Flushing tables"; +--source include/wait_condition.inc +create trigger t1_bi before insert on t1 for each row begin end; +unlock tables; +connection flush; +--echo connection: flush +--reap +unlock tables; +connection default; +select * from t1; +drop table t1; +disconnect flush; +--enable_parsing + +--echo End of 5.1 tests. diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index e388aa61803..7f769c50449 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -3475,4 +3475,55 @@ DROP VIEW `v-2`; DROP DATABASE `d-1`; USE test; +--echo +--echo # +--echo # Bug#26676: VIEW using old table schema in a session. +--echo # +--echo + +--disable_warnings +DROP VIEW IF EXISTS v1; +DROP TABLE IF EXISTS t1; +--enable_warnings + +CREATE TABLE t1(c1 INT, c2 INT); +INSERT INTO t1 VALUES (1, 2), (3, 4); + +--echo + +SELECT * FROM t1; + +--echo + +CREATE VIEW v1 AS SELECT * FROM t1; + +--echo + +SELECT * FROM v1; + +--echo + +ALTER TABLE t1 ADD COLUMN c3 INT AFTER c2; + +--echo + +SELECT * FROM t1; + +--echo + +SELECT * FROM v1; + +--echo + +SHOW CREATE VIEW v1; + +--echo + +DROP VIEW v1; +DROP TABLE t1; + +--echo +--echo # End of test case for Bug#26676. +--echo + --echo End of 5.1 tests. diff --git a/sql-common/client.c b/sql-common/client.c index 0ca7ef16c0d..f149442f12e 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -1097,11 +1097,16 @@ void mysql_read_default_options(struct st_mysql_options *options, my_free(options->ssl_capath, MYF(MY_ALLOW_ZERO_PTR)); options->ssl_capath = my_strdup(opt_arg, MYF(MY_WME)); break; + case 26: /* ssl_cipher */ + my_free(options->ssl_cipher, MYF(MY_ALLOW_ZERO_PTR)); + options->ssl_cipher= my_strdup(opt_arg, MYF(MY_WME)); + break; #else case 13: /* Ignore SSL options */ case 14: case 15: case 16: + case 26: break; #endif /* HAVE_OPENSSL */ case 17: /* charset-lib */ diff --git a/sql/events.cc b/sql/events.cc index 262c62bdbc8..73b8f2cda84 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; diff --git a/sql/item_func.cc b/sql/item_func.cc index 3b108812127..101832b58a9 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -3721,13 +3721,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 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; diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 2663de0b16a..cafb7487e35 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -978,7 +978,8 @@ bool check_dup(const char *db, const char *name, TABLE_LIST *tables); bool compare_record(TABLE *table); bool append_file_to_dir(THD *thd, const char **filename_ptr, const char *table_name); - +void wait_while_table_is_used(THD *thd, TABLE *table, + enum ha_extra_function function); bool table_cache_init(void); void table_cache_free(void); bool table_def_init(void); @@ -1141,6 +1142,7 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type update, uint lock_flags); TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT* mem, bool *refresh, uint flags); +bool name_lock_locked_table(THD *thd, TABLE_LIST *tables); bool reopen_name_locked_table(THD* thd, TABLE_LIST* table_list, bool link_in); TABLE *table_cache_insert_placeholder(THD *thd, const char *key, uint key_length); @@ -1291,12 +1293,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, bool is_locked); +void mysql_ha_cleanup(THD *thd); /* sql_base.cc */ #define TMP_TABLE_KEY_EXTRA 8 diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 9e947470ca1..fad2e5dcd22 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -2596,7 +2596,12 @@ int my_message_sql(uint error, const char *str, myf MyFlags) thd->is_slave_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)) @@ -4598,8 +4603,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); @@ -7744,12 +7754,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/protocol.cc b/sql/protocol.cc index bf8faec006a..713f4ed3d25 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -76,6 +76,12 @@ void net_send_error(THD *thd, uint sql_errno, const char *err) DBUG_ASSERT(!thd->spcont); + if (thd->killed == THD::KILL_QUERY || thd->killed == THD::KILL_BAD_DATA) + { + thd->killed= THD::NOT_KILLED; + thd->mysys_var->abort= 0; + } + if (net && net->no_send_error) { thd->clear_error(); 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 }; diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 9babbcd49d8..4b432cef5cd 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -466,14 +466,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); @@ -484,6 +486,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 */ @@ -537,6 +543,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. @@ -1070,7 +1079,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; @@ -1962,16 +1971,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); @@ -1992,7 +2014,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. @@ -3857,7 +3879,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 d74170534bd..86a77a434ff 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -260,10 +260,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(); @@ -326,7 +326,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_acl.cc b/sql/sql_acl.cc index 311b76c6149..519ca429aa6 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -3472,16 +3472,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() @@ -3503,50 +3500,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; @@ -3584,92 +3667,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"); @@ -3681,11 +3763,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 @@ -3695,35 +3775,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_base.cc b/sql/sql_base.cc index a7d5848dd66..ba8b7fc1330 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -87,7 +87,6 @@ bool Prelock_error_handler::safely_trapped_errors() @defgroup Data_Dictionary Data Dictionary @{ */ - TABLE *unused_tables; /* Used by mysql_test */ HASH open_cache; /* Used by mysql_test */ static HASH table_def_cache; @@ -993,8 +992,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", @@ -2200,6 +2199,41 @@ void wait_for_condition(THD *thd, pthread_mutex_t *mutex, pthread_cond_t *cond) } +/** + Exclusively name-lock a table that is already write-locked by the + current thread. + + @param thd current thread context + @param tables able list containing one table to open. + + @return FALSE on success, TRUE otherwise. +*/ + +bool name_lock_locked_table(THD *thd, TABLE_LIST *tables) +{ + DBUG_ENTER("name_lock_locked_table"); + + /* Under LOCK TABLES we must only accept write locked tables. */ + tables->table= find_locked_table(thd, tables->db, tables->table_name); + + if (!tables->table) + my_error(ER_TABLE_NOT_LOCKED, MYF(0), tables->alias); + else if (tables->table->reginfo.lock_type < TL_WRITE_LOW_PRIORITY) + my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE, MYF(0), tables->alias); + else + { + /* + Ensures that table is opened only by this thread and that no + other statement will open this table. + */ + wait_while_table_is_used(thd, tables->table, HA_EXTRA_FORCE_REOPEN); + DBUG_RETURN(FALSE); + } + + DBUG_RETURN(TRUE); +} + + /* Open table which is already name-locked by this thread. @@ -2731,7 +2765,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. @@ -3119,6 +3153,9 @@ bool reopen_table(TABLE *table) then there is only one table open and locked. This means that the function probably has to be adjusted before it can be used anywhere outside ALTER TABLE. + + @note Must not use TABLE_SHARE::table_name/db of the table being closed, + the strings are used in a loop even after the share may be freed. */ void close_data_files_and_morph_locks(THD *thd, const char *db, @@ -3388,8 +3425,8 @@ bool reopen_tables(THD *thd,bool get_locks,bool in_refresh) @param send_refresh Should we awake waiters even if we didn't close any tables? */ -void close_old_data_files(THD *thd, TABLE *table, bool morph_locks, - bool send_refresh) +static void close_old_data_files(THD *thd, TABLE *table, bool morph_locks, + bool send_refresh) { bool found= send_refresh; DBUG_ENTER("close_old_data_files"); @@ -3530,7 +3567,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); @@ -4300,7 +4337,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_class.cc b/sql/sql_class.cc index bf8413e8627..f59a848a242 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); @@ -818,7 +816,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) diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index 19a99f9d12b..a4ba6f1140b 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,130 @@ 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. + @param is_locked If LOCK_open is locked. - 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, bool is_locked) { - 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))) + 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, is_locked); + 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_lex.h b/sql/sql_lex.h index da0ff94ec96..cdae7449cc7 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1834,11 +1834,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 sql_alloc(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); } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 8ed658df90d..df425557bdf 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -788,12 +788,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, NET *net= &thd->net; bool error= 0; DBUG_ENTER("dispatch_command"); - - if (thd->killed == THD::KILL_QUERY || thd->killed == THD::KILL_BAD_DATA) - { - thd->killed= THD::NOT_KILLED; - thd->mysys_var->abort= 0; - } + DBUG_PRINT("info",("packet: '%*.s'; command: %d", packet_length, packet, command)); thd->command=command; /* @@ -6340,24 +6335,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. + + @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 - 0 ok - !=0 error. thd->killed or thd->is_error() is set + @return Error status code + @retval 0 Ok + @retval !=0 Error; thd->killed is set or thd->is_error() is true */ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables, @@ -6461,7 +6455,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; diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index b1b1502f015..9d4d62e57b6 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -2700,7 +2700,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_rename.cc b/sql/sql_rename.cc index 750bcd50479..9dd8e1b70d4 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, FALSE); + 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 91acd8d20a3..c618d170fb7 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, FALSE); + pthread_mutex_lock(&LOCK_open); /* @@ -1556,9 +1558,6 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, /* Don't give warnings for not found errors, as we already generate notes */ thd->no_warnings_for_error= 1; - /* Remove the tables from the HANDLER list, if they are in it. */ - mysql_ha_flush(thd, tables, MYSQL_HA_CLOSE_FINAL, 1); - for (table= tables; table; table= table->next_local) { char *db=table->db; @@ -1577,13 +1576,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: @@ -3712,14 +3705,16 @@ mysql_rename_table(handlerton *base, const char *old_db, Win32 clients must also have a WRITE LOCK on the table ! */ -static void wait_while_table_is_used(THD *thd,TABLE *table, - enum ha_extra_function function) +void wait_while_table_is_used(THD *thd, TABLE *table, + enum ha_extra_function function) { DBUG_ENTER("wait_while_table_is_used"); DBUG_PRINT("enter", ("table: '%s' share: 0x%lx db_stat: %u version: %lu", table->s->table_name.str, (ulong) table->s, table->db_stat, table->s->version)); + safe_mutex_assert_owner(&LOCK_open); + VOID(table->file->extra(function)); /* Mark all tables that are in use as 'old' */ mysql_lock_abort(thd, table, TRUE); /* end threads waiting on lock */ @@ -4038,7 +4033,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, FALSE); + for (table= tables; table; table= table->next_local) { char table_name[NAME_LEN*2+2]; @@ -5801,8 +5797,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, FALSE); /* DISCARD/IMPORT TABLESPACE is always alone in an ALTER TABLE */ if (alter_info->tablespace_op != NO_TABLESPACE_OP) diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index 3129bd81572..b421f57b7ab 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -323,6 +323,7 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create) TABLE *table; bool result= TRUE; String stmt_query; + bool need_start_waiting= FALSE; DBUG_ENTER("mysql_create_or_drop_trigger"); @@ -374,10 +375,12 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create) /* We don't want perform our operations while global read lock is held so we have to wait until its end and then prevent it from occurring - again until we are done. (Acquiring LOCK_open is not enough because - global read lock is held without holding LOCK_open). + again until we are done, unless we are under lock tables. (Acquiring + LOCK_open is not enough because global read lock is held without holding + LOCK_open). */ - if (wait_if_global_read_lock(thd, 0, 1)) + if (!thd->locked_tables && + !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1))) DBUG_RETURN(TRUE); VOID(pthread_mutex_lock(&LOCK_open)); @@ -433,35 +436,25 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create) goto end; } - if (lock_table_names(thd, tables)) - goto end; + /* We also don't allow creation of triggers on views. */ + tables->required_type= FRMTYPE_TABLE; - /* - If the table is under LOCK TABLES, lock_table_names() does not set - tables->table. Find the table in open_tables. - */ - if (!tables->table && thd->locked_tables) + /* Keep consistent with respect to other DDL statements */ + mysql_ha_rm_tables(thd, tables, TRUE); + + if (thd->locked_tables) { - for (table= thd->open_tables; - table && (strcmp(table->s->table_name.str, tables->table_name) || - strcmp(table->s->db.str, tables->db)); - table= table->next) {} - tables->table= table; + /* Table must be write locked */ + if (name_lock_locked_table(thd, tables)) + goto end; } - if (!tables->table) + else { - /* purecov: begin inspected */ - my_error(ER_TABLE_NOT_LOCKED, MYF(0), tables->alias); - goto end; - /* purecov: end */ - } - - /* No need to reopen the table if it is locked with LOCK TABLES. */ - if (!thd->locked_tables || (tables->table->in_use != thd)) - { - /* We also don't allow creation of triggers on views. */ - tables->required_type= FRMTYPE_TABLE; + /* Grab the name lock and insert the placeholder*/ + if (lock_table_names(thd, tables)) + goto end; + /* Convert the placeholder to a real table */ if (reopen_name_locked_table(thd, tables, TRUE)) { unlock_table_name(thd, tables); @@ -489,13 +482,20 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create) /* Under LOCK TABLES we must reopen the table to activate the trigger. */ if (!result && thd->locked_tables) { - /* - Must not use table->s->db.str or table->s->table_name.str here. - The strings are used in a loop even after the share may be freed. - */ + /* Make table suitable for reopening */ close_data_files_and_morph_locks(thd, tables->db, tables->table_name); thd->in_lock_tables= 1; - result= reopen_tables(thd, 1, 0); + if (reopen_tables(thd, 1, 1)) + { + /* To be safe remove this table from the set of LOCKED TABLES */ + unlink_open_table(thd, tables->table, FALSE); + + /* + Ignore reopen_tables errors for now. It's better not leave master/slave + in a inconsistent state. + */ + thd->clear_error(); + } thd->in_lock_tables= 0; } @@ -507,7 +507,9 @@ end: } VOID(pthread_mutex_unlock(&LOCK_open)); - start_waiting_global_read_lock(thd); + + if (need_start_waiting) + start_waiting_global_read_lock(thd); if (!result) send_ok(thd); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 5de142ca83a..80e354aef98 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -508,10 +508,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %pure_parser /* We have threads */ /* - Currently there are 280 shift/reduce conflicts. + Currently there are 177 shift/reduce conflicts. We should not introduce new conflicts any more. */ -%expect 280 +%expect 177 /* Comments for TOKENS. @@ -1157,7 +1157,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); variable variable_aux bool_pri predicate bit_expr table_wild simple_expr udf_expr - expr_or_default set_expr_or_default interval_expr + expr_or_default set_expr_or_default param_marker geometry_function signed_literal now_or_signed_literal opt_escape sp_opt_default @@ -6569,10 +6569,10 @@ bit_expr: { $$= new Item_func_plus($1,$3); } | bit_expr '-' bit_expr %prec '-' { $$= new Item_func_minus($1,$3); } - | bit_expr '+' interval_expr interval %prec '+' - { $$= new Item_date_add_interval($1,$3,$4,0); } - | bit_expr '-' interval_expr interval %prec '-' - { $$= new Item_date_add_interval($1,$3,$4,1); } + | bit_expr '+' INTERVAL_SYM expr interval %prec '+' + { $$= new Item_date_add_interval($1,$4,$5,0); } + | bit_expr '-' INTERVAL_SYM expr interval %prec '-' + { $$= new Item_date_add_interval($1,$4,$5,1); } | bit_expr '*' bit_expr %prec '*' { $$= new Item_func_mul($1,$3); } | bit_expr '/' bit_expr %prec '/' @@ -6622,11 +6622,6 @@ all_or_any: | ANY_SYM { $$ = 0; } ; -interval_expr: - INTERVAL_SYM expr %prec INTERVAL_SYM - { $$=$2; } - ; - simple_expr: simple_ident | function_call_keyword @@ -6722,18 +6717,9 @@ simple_expr: $$= new (YYTHD->mem_root) Item_insert_value(Lex->current_context(), $3); } - | interval_expr interval '+' expr + | INTERVAL_SYM expr interval '+' expr %prec INTERVAL_SYM /* we cannot put interval before - */ - { $$= new (YYTHD->mem_root) Item_date_add_interval($4,$1,$2,0); } - | interval_expr - { - if ($1->type() != Item::ROW_ITEM) - { - my_parse_error(ER(ER_SYNTAX_ERROR)); - MYSQL_YYABORT; - } - $$= new (YYTHD->mem_root) Item_func_interval((Item_row *)$1); - } + { $$= new (YYTHD->mem_root) Item_date_add_interval($5,$2,$3,0); } ; /* @@ -6761,6 +6747,23 @@ function_call_keyword: { $$= new (YYTHD->mem_root) Item_func_hour($3); } | INSERT '(' expr ',' expr ',' expr ',' expr ')' { $$= new (YYTHD->mem_root) Item_func_insert($3,$5,$7,$9); } + | INTERVAL_SYM '(' expr ',' expr ')' %prec INTERVAL_SYM + { + THD *thd= YYTHD; + List *list= new (thd->mem_root) List; + list->push_front($5); + list->push_front($3); + Item_row *item= new (thd->mem_root) Item_row(*list); + $$= new (thd->mem_root) Item_func_interval(item); + } + | INTERVAL_SYM '(' expr ',' expr ',' expr_list ')' %prec INTERVAL_SYM + { + THD *thd= YYTHD; + $7->push_front($5); + $7->push_front($3); + Item_row *item= new (thd->mem_root) Item_row(*$7); + $$= new (thd->mem_root) Item_func_interval(item); + } | LEFT '(' expr ',' expr ')' { $$= new (YYTHD->mem_root) Item_func_left($3,$5); } | MINUTE_SYM '(' expr ')' @@ -6838,10 +6841,10 @@ function_call_nonkeyword: $$= new (YYTHD->mem_root) Item_func_curtime_local($3); Lex->safe_to_cache_query=0; } - | DATE_ADD_INTERVAL '(' expr ',' interval_expr interval ')' - { $$= new (YYTHD->mem_root) Item_date_add_interval($3,$5,$6,0); } - | DATE_SUB_INTERVAL '(' expr ',' interval_expr interval ')' - { $$= new (YYTHD->mem_root) Item_date_add_interval($3,$5,$6,1); } + | DATE_ADD_INTERVAL '(' expr ',' INTERVAL_SYM expr interval ')' %prec INTERVAL_SYM + { $$= new (YYTHD->mem_root) Item_date_add_interval($3,$6,$7,0); } + | DATE_SUB_INTERVAL '(' expr ',' INTERVAL_SYM expr interval ')' %prec INTERVAL_SYM + { $$= new (YYTHD->mem_root) Item_date_add_interval($3,$6,$7,1); } | EXTRACT_SYM '(' interval FROM expr ')' { $$=new (YYTHD->mem_root) Item_extract( $3, $5); } | GET_FORMAT '(' date_time_type ',' expr ')'