diff options
author | unknown <monty@mashka.mysql.fi> | 2002-11-21 15:56:48 +0200 |
---|---|---|
committer | unknown <monty@mashka.mysql.fi> | 2002-11-21 15:56:48 +0200 |
commit | 33fc0d53b543032accea2476a4eed0522cead2bb (patch) | |
tree | d3df5d3fc1abf364dcbcc8eb2305a1cf62540192 /sql | |
parent | 2723dbdb5e2c60162ca464f65f68fdd13b7c9cef (diff) | |
parent | 70a17cd5a7aab52697b494cd8379fb78db15eeea (diff) | |
download | mariadb-git-33fc0d53b543032accea2476a4eed0522cead2bb.tar.gz |
Merge with 4.0
BitKeeper/etc/gone:
auto-union
BitKeeper/etc/ignore:
auto-union
BitKeeper/etc/logging_ok:
auto-union
BitKeeper/deleted/.del-.my_sys.h.swp~f6a4a7f8dae03f18:
Auto merged
BitKeeper/etc/config:
Auto merged
acconfig.h:
Auto merged
acinclude.m4:
Auto merged
Docs/manual.texi:
Auto merged
client/mysqlcheck.c:
Auto merged
client/mysqlshow.c:
Auto merged
include/myisam.h:
Auto merged
include/violite.h:
Auto merged
isam/pack_isam.c:
Auto merged
libmysql/libmysql.c:
Auto merged
libmysqld/lib_sql.cc:
Auto merged
myisam/Makefile.am:
Auto merged
myisam/ft_nlq_search.c:
Auto merged
myisam/mi_open.c:
Auto merged
myisam/mi_write.c:
Auto merged
myisam/sort.c:
Auto merged
mysql-test/mysql-test-run.sh:
Auto merged
mysql-test/r/fulltext.result:
Auto merged
mysql-test/r/func_test.result:
Auto merged
mysql-test/r/isam.result:
Auto merged
mysql-test/r/rpl_replicate_do.result:
Auto merged
mysql-test/r/variables.result:
Auto merged
mysql-test/t/func_test.test:
Auto merged
mysql-test/t/myisam.test:
Auto merged
mysql-test/t/rpl_rotate_logs.test:
Auto merged
mysql-test/t/variables.test:
Auto merged
mysys/hash.c:
Auto merged
mysys/tree.c:
Auto merged
scripts/Makefile.am:
Auto merged
sql/Makefile.am:
Auto merged
sql/filesort.cc:
Auto merged
sql/gen_lex_hash.cc:
Auto merged
sql/ha_berkeley.cc:
Auto merged
sql/ha_innodb.cc:
Auto merged
sql/handler.cc:
Auto merged
sql/handler.h:
Auto merged
sql/hash_filo.h:
Auto merged
sql/hostname.cc:
Auto merged
sql/item_func.cc:
Auto merged
sql/item_func.h:
Auto merged
sql/item_timefunc.cc:
Auto merged
sql/lex.h:
Auto merged
sql/lock.cc:
Auto merged
sql/log.cc:
Auto merged
sql/log_event.h:
Auto merged
sql/mini_client.cc:
Auto merged
sql/opt_range.cc:
Auto merged
sql/opt_sum.cc:
Auto merged
sql/repl_failsafe.cc:
Auto merged
sql/set_var.h:
Auto merged
sql/slave.h:
Auto merged
sql/sql_acl.cc:
Auto merged
sql/sql_analyse.cc:
Auto merged
sql/sql_cache.cc:
Auto merged
sql/sql_insert.cc:
Auto merged
sql/sql_load.cc:
Auto merged
sql/sql_rename.cc:
Auto merged
sql/sql_repl.cc:
Auto merged
sql/sql_show.cc:
Auto merged
sql/sql_table.cc:
Auto merged
sql/sql_udf.cc:
Auto merged
sql/share/czech/errmsg.txt:
Auto merged
sql/share/danish/errmsg.txt:
Auto merged
sql/share/dutch/errmsg.txt:
Auto merged
sql/share/english/errmsg.txt:
Auto merged
sql/share/estonian/errmsg.txt:
Auto merged
sql/share/french/errmsg.txt:
Auto merged
sql/share/german/errmsg.txt:
Auto merged
sql/share/greek/errmsg.txt:
Auto merged
sql/share/hungarian/errmsg.txt:
Auto merged
sql/share/italian/errmsg.txt:
Auto merged
sql/share/japanese/errmsg.txt:
Auto merged
sql/share/korean/errmsg.txt:
Auto merged
sql/share/norwegian/errmsg.txt:
Auto merged
sql/table.h:
Auto merged
sql/unireg.cc:
Auto merged
sql-bench/server-cfg.sh:
Auto merged
sql/share/norwegian-ny/errmsg.txt:
Auto merged
sql/share/polish/errmsg.txt:
Auto merged
sql/share/portuguese/errmsg.txt:
Auto merged
sql/share/romanian/errmsg.txt:
Auto merged
sql/share/russian/errmsg.txt:
Auto merged
sql/share/slovak/errmsg.txt:
Auto merged
sql/share/spanish/errmsg.txt:
Auto merged
sql/share/swedish/errmsg.txt:
Auto merged
sql/share/ukrainian/errmsg.txt:
Auto merged
sql/ha_myisam.cc:
Merge with 4.0
Removed some commented code
sql/sql_db.cc:
Merge with 4.0
Optimized the logging of the drop db call a bit
sql/sql_update.cc:
Added comment
Diffstat (limited to 'sql')
88 files changed, 1726 insertions, 1102 deletions
diff --git a/sql/field.cc b/sql/field.cc index 73ef4439bc9..f2324a0a331 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -41,6 +41,11 @@ #include <floatingpoint.h> #endif +// Maximum allowed exponent value for converting string to decimal +#define MAX_EXPONENT 1024 + + + /***************************************************************************** Instansiate templates and static variables *****************************************************************************/ @@ -392,7 +397,7 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs) const char *frac_digits_from, *frac_digits_end; /* The sign of the exponent : will be 0 (means no exponent), '+' or '-' */ char expo_sign_char=0; - uint exponent=0; // value of the exponent + uint exponent=0; // value of the exponent /* Pointers used when digits move from the left of the '.' to the right of the '.' (explained below) @@ -488,13 +493,17 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs) else expo_sign_char= '+'; /* - Read digits of the exponent and compute its value - 'exponent' overflow (e.g. if 1E10000000000000000) is not a problem - (the value of the field will be overflow anyway, or 0 anyway, - it does not change anything if the exponent is 2^32 or more + Read digits of the exponent and compute its value. We must care about + 'exponent' overflow, because as unsigned arithmetic is "modulo", big + exponents will become small (e.g. 1e4294967296 will become 1e0, and the + field will finally contain 1 instead of its max possible value). */ - for (;from!=end && my_isdigit(system_charset_info, (*from)); from++) + for (;from!=end && my_isdigit(system_charset_info, *from); from++) + { exponent=10*exponent+(*from-'0'); + if (exponent>MAX_EXPONENT) + break; + } } /* @@ -536,6 +545,13 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs) int_digits_added_zeros=2 (to make 1234500). */ + /* + Below tmp_uint cannot overflow with small enough MAX_EXPONENT setting, + as int_digits_added_zeros<=exponent<4G and + (int_digits_end-int_digits_from)<=max_allowed_packet<=2G and + (frac_digits_from-int_digits_tail_from)<=max_allowed_packet<=2G + */ + if (!expo_sign_char) tmp_uint=tmp_dec+(uint)(int_digits_end-int_digits_from); else if (expo_sign_char == '-') @@ -544,7 +560,7 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs) frac_digits_added_zeros=exponent-tmp_uint; int_digits_end -= tmp_uint; frac_digits_head_end=int_digits_end+tmp_uint; - tmp_uint=tmp_dec+(uint)(int_digits_end-int_digits_from); + tmp_uint=tmp_dec+(uint)(int_digits_end-int_digits_from); } else // (expo_sign_char=='+') { @@ -571,9 +587,9 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs) int_digits_added_zeros=0; } } - tmp_uint=(tmp_dec+(uint)(int_digits_end-int_digits_from) - +(uint)(frac_digits_from-int_digits_tail_from)+ - int_digits_added_zeros); + tmp_uint= (tmp_dec+(int_digits_end-int_digits_from)+ + (uint)(frac_digits_from-int_digits_tail_from)+ + int_digits_added_zeros); } /* @@ -584,7 +600,7 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs) If the sign is defined and '-', we need one position for it */ - if (field_length < tmp_uint + (int) (sign_char == '-')) + if (field_length < tmp_uint + (int) (sign_char == '-')) { // too big number, change to max or min number Field_decimal::overflow(sign_char == '-'); @@ -647,69 +663,67 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs) *pos--=' '; //fill with blanks } - if (tmp_dec) // This field has decimals - { - /* - Write digits of the frac_% parts ; - Depending on current_thd->count_cutted_fields, we may also want - to know if some non-zero tail of these parts will - be truncated (for example, 0.002->0.00 will generate a warning, - while 0.000->0.00 will not) - (and 0E1000000000 will not, while 1E-1000000000 will) - */ + /* + Write digits of the frac_% parts ; + Depending on current_thd->count_cutted_fields, we may also want + to know if some non-zero tail of these parts will + be truncated (for example, 0.002->0.00 will generate a warning, + while 0.000->0.00 will not) + (and 0E1000000000 will not, while 1E-1000000000 will) + */ - pos=to+(uint)(field_length-tmp_dec); // Calculate post to '.' + pos=to+(uint)(field_length-tmp_dec); // Calculate post to '.' + right_wall=to+field_length; + if (pos != right_wall) *pos++='.'; - right_wall=to+field_length; - if (expo_sign_char == '-') + if (expo_sign_char == '-') + { + while (frac_digits_added_zeros-- > 0) { - while (frac_digits_added_zeros-- > 0) + if (pos == right_wall) { - if (pos == right_wall) - { - if (current_thd->count_cuted_fields && !is_cuted_fields_incr) - break; // Go on below to see if we lose non zero digits - return 0; - } - *pos++='0'; + if (current_thd->count_cuted_fields && !is_cuted_fields_incr) + break; // Go on below to see if we lose non zero digits + return 0; } - while (int_digits_end != frac_digits_head_end) + *pos++='0'; + } + while (int_digits_end != frac_digits_head_end) + { + tmp_char= *int_digits_end++; + if (pos == right_wall) { - tmp_char= *int_digits_end++; - if (pos == right_wall) - { - if (tmp_char != '0') // Losing a non zero digit ? - { - if (!is_cuted_fields_incr) - current_thd->cuted_fields++; - return 0; - } - continue; - } - *pos++= tmp_char; + if (tmp_char != '0') // Losing a non zero digit ? + { + if (!is_cuted_fields_incr) + current_thd->cuted_fields++; + return 0; + } + continue; } + *pos++= tmp_char; } + } - for (;frac_digits_from!=frac_digits_end;) + for (;frac_digits_from!=frac_digits_end;) + { + tmp_char= *frac_digits_from++; + if (pos == right_wall) { - tmp_char= *frac_digits_from++; - if (pos == right_wall) + if (tmp_char != '0') // Losing a non zero digit ? { - if (tmp_char != '0') // Losing a non zero digit ? - { - if (!is_cuted_fields_incr) - current_thd->cuted_fields++; - return 0; - } - continue; + if (!is_cuted_fields_incr) + current_thd->cuted_fields++; + return 0; } - *pos++= tmp_char; + continue; } - - while (pos != right_wall) - *pos++='0'; // Fill with zeros at right of '.' + *pos++= tmp_char; } + + while (pos != right_wall) + *pos++='0'; // Fill with zeros at right of '.' return 0; } @@ -3930,12 +3944,12 @@ int Field_string::pack_cmp(const char *b, uint length) } -uint Field_string::packed_col_length(const char *ptr, uint length) +uint Field_string::packed_col_length(const char *data_ptr, uint length) { if (length > 255) - return uint2korr(ptr)+2; + return uint2korr(data_ptr)+2; else - return (uint) ((uchar) *ptr)+1; + return (uint) ((uchar) *data_ptr)+1; } uint Field_string::max_packed_col_length(uint max_length) @@ -4162,12 +4176,12 @@ int Field_varstring::pack_cmp(const char *b, uint key_length) (const uchar *)b,b_length); } -uint Field_varstring::packed_col_length(const char *ptr, uint length) +uint Field_varstring::packed_col_length(const char *data_ptr, uint length) { if (length > 255) - return uint2korr(ptr)+2; + return uint2korr(data_ptr)+2; else - return (uint) ((uchar) *ptr)+1; + return (uint) ((uchar) *data_ptr)+1; } uint Field_varstring::max_packed_col_length(uint max_length) @@ -4698,12 +4712,12 @@ char *Field_blob::pack_key_from_key_image(char *to, const char *from, return to+length; } -uint Field_blob::packed_col_length(const char *ptr, uint length) +uint Field_blob::packed_col_length(const char *data_ptr, uint length) { if (length > 255) - return uint2korr(ptr)+2; + return uint2korr(data_ptr)+2; else - return (uint) ((uchar) *ptr)+1; + return (uint) ((uchar) *data_ptr)+1; } uint Field_blob::max_packed_col_length(uint max_length) @@ -5294,10 +5308,11 @@ Field *make_field(char *ptr, uint32 field_length, return new Field_datetime(ptr,null_pos,null_bit, unireg_check, field_name, table, field_charset); case FIELD_TYPE_NULL: - default: // Impossible (Wrong version) return new Field_null(ptr,field_length,unireg_check,field_name,table, field_charset); + default: // Impossible (Wrong version) + break; } - return 0; // Impossible (Wrong version) + return 0; } diff --git a/sql/filesort.cc b/sql/filesort.cc index 53af60b0370..fab666a1203 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -223,7 +223,7 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length, if (error) my_error(ER_FILSORT_ABORT,MYF(ME_ERROR+ME_WAITTANG)); else - statistic_add(filesort_rows, records, &LOCK_status); + statistic_add(filesort_rows, (ulong) records, &LOCK_status); *examined_rows= param.examined_rows; #ifdef SKIP_DBUG_IN_FILESORT DBUG_POP(); /* Ok to DBUG */ @@ -724,7 +724,7 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file, org_max_rows=max_rows=param->max_rows; if (init_queue(&queue,(uint) (Tb-Fb)+1,offsetof(BUFFPEK,key),0, - (int (*) (void *, byte *,byte*)) + (queue_compare) (cmp=get_ptr_compare(sort_length)),(void*) &sort_length)) DBUG_RETURN(1); /* purecov: inspected */ for (buffpek= Fb ; buffpek <= Tb ; buffpek++) diff --git a/sql/gen_lex_hash.cc b/sql/gen_lex_hash.cc index 0d92397b616..7daab228093 100644 --- a/sql/gen_lex_hash.cc +++ b/sql/gen_lex_hash.cc @@ -320,7 +320,7 @@ and you are welcome to modify and redistribute it under the GPL license\n"); my_print_help(my_long_options); } -static my_bool +extern "C" my_bool get_one_option(int optid, const struct my_option *opt __attribute__((unused)), char *argument __attribute__((unused))) { diff --git a/sql/ha_berkeley.cc b/sql/ha_berkeley.cc index 6d5b469a913..679642ca949 100644 --- a/sql/ha_berkeley.cc +++ b/sql/ha_berkeley.cc @@ -1931,7 +1931,7 @@ int ha_berkeley::delete_table(const char *name) double ha_berkeley::scan_time() { - return records/3; + return rows2double(records/3); } ha_rows ha_berkeley::records_in_range(int keynr, @@ -2206,7 +2206,7 @@ static BDB_SHARE *get_share(const char *table_name, TABLE *table) if (!(share=(BDB_SHARE*) hash_search(&bdb_open_tables, (byte*) table_name, length))) { - ha_rows *rec_per_key; + ulong *rec_per_key; char *tmp_name; DB **key_file; u_int32_t *key_type; diff --git a/sql/ha_berkeley.h b/sql/ha_berkeley.h index 198664d0c06..f2a81d123f1 100644 --- a/sql/ha_berkeley.h +++ b/sql/ha_berkeley.h @@ -27,7 +27,8 @@ typedef struct st_berkeley_share { ulonglong auto_ident; - ha_rows rows, org_rows, *rec_per_key; + ha_rows rows, org_rows; + ulong *rec_per_key; THR_LOCK lock; pthread_mutex_t mutex; char *table_name; diff --git a/sql/ha_heap.cc b/sql/ha_heap.cc index c06421617dd..4a3b9495f6f 100644 --- a/sql/ha_heap.cc +++ b/sql/ha_heap.cc @@ -245,7 +245,7 @@ int ha_heap::create(const char *name, TABLE *table, { uint key, parts, mem_per_row= 0; uint auto_key= 0, auto_key_type= 0; - ulong max_rows; + ha_rows max_rows; HP_KEYDEF *keydef; HA_KEYSEG *seg; char buff[FN_REFLEN]; @@ -310,8 +310,8 @@ int ha_heap::create(const char *name, TABLE *table, } } mem_per_row+= MY_ALIGN(table->reclength + 1, sizeof(char*)); - max_rows = (ulong) (current_thd->variables.max_heap_table_size / - mem_per_row); + max_rows = (ha_rows) (current_thd->variables.max_heap_table_size / + mem_per_row); HP_CREATE_INFO hp_create_info; hp_create_info.auto_key= auto_key; hp_create_info.auto_key_type= auto_key_type; @@ -319,9 +319,9 @@ int ha_heap::create(const char *name, TABLE *table, create_info->auto_increment_value - 1 : 0); error= heap_create(fn_format(buff,name,"","",4+2), table->keys,keydef, table->reclength, - ((table->max_rows < max_rows && table->max_rows) ? - table->max_rows : max_rows), - table->min_rows, &hp_create_info); + (ulong) ((table->max_rows < max_rows && table->max_rows) ? + table->max_rows : max_rows), + (ulong) table->min_rows, &hp_create_info); my_free((gptr) keydef, MYF(0)); if (file) info(HA_STATUS_NO_LOCK | HA_STATUS_CONST | HA_STATUS_VARIABLE); diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 9aa63cc1435..7787b543f34 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -40,17 +40,12 @@ InnoDB */ #include "ha_innodb.h" -/* We must declare this here because we undef SAFE_MUTEX below */ pthread_mutex_t innobase_mutex; /* Store MySQL definition of 'byte': in Linux it is char while InnoDB uses unsigned char */ typedef byte mysql_byte; -#ifdef SAFE_MUTEX -#undef pthread_mutex_t -#endif - #define INSIDE_HA_INNOBASE_CC /* Include necessary InnoDB headers */ @@ -97,6 +92,8 @@ are determined in innobase_init below: */ char* innobase_data_home_dir = NULL; char* innobase_log_group_home_dir = NULL; char* innobase_log_arch_dir = NULL; +/* The following has a midleading name: starting from 4.0.5 this also +affects Windows */ char* innobase_unix_file_flush_method = NULL; /* Below we have boolean-valued start-up parameters, and their default @@ -253,6 +250,10 @@ convert_error_code_to_mysql( } else if (error == (int) DB_TOO_BIG_RECORD) { return(HA_ERR_TO_BIG_ROW); + + } else if (error == (int) DB_CORRUPTION) { + + return(HA_ERR_CRASHED); } else { return(-1); // Unknown error } @@ -346,7 +347,8 @@ check_trx_exists( trx = trx_allocate_for_mysql(); trx->mysql_thd = thd; - + trx->mysql_query_str = &((*thd).query); + thd->transaction.all.innobase_tid = trx; /* The execution of a single SQL statement is denoted by @@ -713,9 +715,10 @@ innobase_init(void) DBUG_RETURN(TRUE); } - srv_unix_file_flush_method_str = (innobase_unix_file_flush_method ? + + srv_file_flush_method_str = (innobase_unix_file_flush_method ? innobase_unix_file_flush_method : - (char*)"fdatasync"); + NULL); srv_n_log_groups = (ulint) innobase_mirrored_log_groups; srv_n_log_files = (ulint) innobase_log_files_in_group; @@ -725,8 +728,6 @@ innobase_init(void) srv_log_buffer_size = (ulint) innobase_log_buffer_size; srv_flush_log_at_trx_commit = (ulint) innobase_flush_log_at_trx_commit; - srv_use_native_aio = 0; - srv_pool_size = (ulint) innobase_buffer_pool_size; srv_mem_pool_size = (ulint) innobase_additional_mem_pool_size; @@ -750,6 +751,14 @@ innobase_init(void) default_charset_info->sort_order, 256); } + /* Since we in this module access directly the fields of a trx + struct, and due to different headers and flags it might happen that + mutex_t has a different size in this module and in InnoDB + modules, we check at run time that the size is the same in + these compilation modules. */ + + srv_sizeof_trx_t_in_ha_innodb_cc = sizeof(trx_t); + err = innobase_start_or_create_for_mysql(); if (err != DB_SUCCESS) { @@ -1147,15 +1156,15 @@ ha_innobase::open( ib_table = dict_table_get_and_increment_handle_count( norm_name, NULL); if (NULL == ib_table) { - - sql_print_error("InnoDB error:\n\ -Cannot find table %s from the internal data dictionary\n\ -of InnoDB though the .frm file for the table exists. Maybe you\n\ -have deleted and recreated InnoDB data files but have forgotten\n\ -to delete the corresponding .frm files of InnoDB tables, or you\n\ -have moved .frm files to another database?\n\ -Look from section 15.1 of http://www.innodb.com/ibman.html\n\ -how you can resolve the problem.\n", + ut_print_timestamp(stderr); + fprintf(stderr, " InnoDB error:\n" +"Cannot find table %s from the internal data dictionary\n" +"of InnoDB though the .frm file for the table exists. Maybe you\n" +"have deleted and recreated InnoDB data files but have forgotten\n" +"to delete the corresponding .frm files of InnoDB tables, or you\n" +"have moved .frm files to another database?\n" +"Look from section 15.1 of http://www.innodb.com/ibman.html\n" +"how you can resolve the problem.\n", norm_name); free_share(share); @@ -1168,7 +1177,10 @@ how you can resolve the problem.\n", ((row_prebuilt_t*)innobase_prebuilt)->mysql_row_len = table->reclength; - primary_key = MAX_KEY; + /* Looks like MySQL-3.23 sometimes has primary key number != 0 */ + + primary_key = table->primary_key; + key_used_on_scan = primary_key; /* Allocate a buffer for a 'row reference'. A row reference is a string of bytes of length ref_length which uniquely specifies @@ -1177,13 +1189,14 @@ how you can resolve the problem.\n", of length ref_length! */ if (!row_table_got_default_clust_index(ib_table)) { + if (primary_key >= MAX_KEY) { + fprintf(stderr, + "InnoDB: Error: table %s has a primary key in InnoDB\n" + "InnoDB: data dictionary, but not in MySQL!\n", name); + } ((row_prebuilt_t*)innobase_prebuilt) ->clust_index_was_generated = FALSE; - - primary_key = 0; - key_used_on_scan = 0; - /* MySQL allocates the buffer for ref. key_info->key_length includes space for all key columns + one byte for each column @@ -1192,8 +1205,14 @@ how you can resolve the problem.\n", based on ref_length. */ - ref_length = table->key_info->key_length; + ref_length = table->key_info[primary_key].key_length; } else { + if (primary_key != MAX_KEY) { + fprintf(stderr, + "InnoDB: Error: table %s has no primary key in InnoDB\n" + "InnoDB: data dictionary, but has one in MySQL!\n", name); + } + ((row_prebuilt_t*)innobase_prebuilt) ->clust_index_was_generated = TRUE; @@ -1501,7 +1520,8 @@ ha_innobase::store_key_val_for_row( are equal */ bzero(buff, (ref_length- (uint) (buff - buff_start))); - DBUG_RETURN(ref_length); + + DBUG_RETURN((uint)(buff - buff_start)); } /****************************************************************** @@ -1679,6 +1699,7 @@ ha_innobase::write_row( longlong dummy; ibool incremented_auto_inc_for_stat = FALSE; ibool incremented_auto_inc_counter = FALSE; + ibool skip_auto_inc_decr; DBUG_ENTER("ha_innobase::write_row"); @@ -1843,13 +1864,31 @@ ha_innobase::write_row( if (error != DB_SUCCESS) { /* If the insert did not succeed we restore the value of the auto-inc counter we used; note that this behavior was - introduced only in version 4.0.4 */ + introduced only in version 4.0.4. + NOTE that a REPLACE command handles a duplicate key error + itself, and we must not decrement the autoinc counter + if we are performing a REPLACE statement. + NOTE 2: if there was an error, for example a deadlock, + which caused InnoDB to roll back the whole transaction + already in the call of row_insert_for_mysql(), we may no + longer have the AUTO-INC lock, and cannot decrement + the counter here. */ + + skip_auto_inc_decr = FALSE; + + if (error == DB_DUPLICATE_KEY) { + ut_a(user_thd->query); + dict_accept(user_thd->query, "REPLACE", + &skip_auto_inc_decr); + } - if (incremented_auto_inc_counter) { + if (!skip_auto_inc_decr && incremented_auto_inc_counter + && prebuilt->trx->auto_inc_lock) { dict_table_autoinc_decrement(prebuilt->table); } - if (incremented_auto_inc_for_stat) { + if (!skip_auto_inc_decr && incremented_auto_inc_for_stat + && prebuilt->trx->auto_inc_lock) { auto_inc_counter_for_this_stat--; } } @@ -2181,8 +2220,16 @@ convert_search_mode_to_innobase( case HA_READ_AFTER_KEY: return(PAGE_CUR_G); case HA_READ_BEFORE_KEY: return(PAGE_CUR_L); case HA_READ_PREFIX: return(PAGE_CUR_GE); - case HA_READ_PREFIX_LAST: return(PAGE_CUR_LE); - /* HA_READ_PREFIX_LAST does not yet work in InnoDB! */ + case HA_READ_PREFIX_LAST: + /* ut_print_timestamp(stderr); + fprintf(stderr, + " InnoDB: Warning: Using HA_READ_PREFIX_LAST\n"); */ + return(PAGE_CUR_LE); + + /* InnoDB does not yet support ..PREFIX_LAST! + We have to add a new search flag + PAGE_CUR_LE_OR_PREFIX to InnoDB. */ + /* the above PREFIX flags mean that the last field in the key value may just be a prefix of the complete fixed length field */ @@ -2751,7 +2798,11 @@ ha_innobase::position( that len is always fixed for this table. The following assertion checks this. */ - ut_a(len == ref_length); + if (len != ref_length) { + fprintf(stderr, + "InnoDB: Error: stored ref len is %lu, but table ref len is %lu\n", + (ulint)len, (ulint)ref_length); + } } @@ -2935,16 +2986,21 @@ ha_innobase::create( trx->check_unique_secondary = FALSE; } + if (lower_case_table_names) { + srv_lower_case_table_names = TRUE; + } else { + srv_lower_case_table_names = FALSE; + } fn_format(name2, name, "", "",2); // Remove the .frm extension normalize_table_name(norm_name, name2); - /* Latch the InnoDB data dictionary exclusive so that no deadlocks + /* Latch the InnoDB data dictionary exclusively so that no deadlocks or lock waits can happen in it during a table create operation. - (Drop table etc. do this latching in row0mysql.c.) */ + Drop table etc. do this latching in row0mysql.c. */ - row_mysql_lock_data_dictionary(); + row_mysql_lock_data_dictionary(trx); /* Create the table definition in InnoDB */ @@ -2953,7 +3009,7 @@ ha_innobase::create( if (error) { innobase_commit_low(trx); - row_mysql_unlock_data_dictionary(); + row_mysql_unlock_data_dictionary(trx); trx_free_for_mysql(trx); @@ -2983,7 +3039,7 @@ ha_innobase::create( if (error) { innobase_commit_low(trx); - row_mysql_unlock_data_dictionary(); + row_mysql_unlock_data_dictionary(trx); trx_free_for_mysql(trx); @@ -2998,7 +3054,7 @@ ha_innobase::create( (uint) primary_key_no))) { innobase_commit_low(trx); - row_mysql_unlock_data_dictionary(); + row_mysql_unlock_data_dictionary(trx); trx_free_for_mysql(trx); @@ -3014,7 +3070,7 @@ ha_innobase::create( innobase_commit_low(trx); - row_mysql_unlock_data_dictionary(); + row_mysql_unlock_data_dictionary(trx); trx_free_for_mysql(trx); @@ -3023,24 +3079,27 @@ ha_innobase::create( } } - error = row_table_add_foreign_constraints(trx, - create_info->create_statement, norm_name); + if (current_thd->query != NULL) { + + error = row_table_add_foreign_constraints(trx, + current_thd->query, norm_name); - error = convert_error_code_to_mysql(error, NULL); + error = convert_error_code_to_mysql(error, NULL); - if (error) { - innobase_commit_low(trx); + if (error) { + innobase_commit_low(trx); - row_mysql_unlock_data_dictionary(); + row_mysql_unlock_data_dictionary(trx); - trx_free_for_mysql(trx); + trx_free_for_mysql(trx); - DBUG_RETURN(error); + DBUG_RETURN(error); + } } innobase_commit_low(trx); - row_mysql_unlock_data_dictionary(); + row_mysql_unlock_data_dictionary(trx); /* Flush the log to reduce probability that the .frm files and the InnoDB data dictionary get out-of-sync if the user runs @@ -3082,6 +3141,12 @@ ha_innobase::delete_table( DBUG_ENTER("ha_innobase::delete_table"); + if (lower_case_table_names) { + srv_lower_case_table_names = TRUE; + } else { + srv_lower_case_table_names = FALSE; + } + trx = trx_allocate_for_mysql(); name_len = strlen(name); @@ -3095,7 +3160,7 @@ ha_innobase::delete_table( /* Drop the table in InnoDB */ - error = row_drop_table_for_mysql(norm_name, trx, FALSE); + error = row_drop_table_for_mysql(norm_name, trx); /* Flush the log to reduce probability that the .frm files and the InnoDB data dictionary get out-of-sync if the user runs @@ -3192,6 +3257,12 @@ ha_innobase::rename_table( DBUG_ENTER("ha_innobase::rename_table"); + if (lower_case_table_names) { + srv_lower_case_table_names = TRUE; + } else { + srv_lower_case_table_names = FALSE; + } + trx = trx_allocate_for_mysql(); name_len1 = strlen(from); @@ -3318,7 +3389,7 @@ ha_innobase::estimate_number_of_rows(void) row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt; dict_index_t* index; ulonglong estimate; - ulonglong data_file_length; + ulonglong local_data_file_length; /* Warning: since it is not sure that MySQL calls external_lock before calling this function, the trx field in prebuilt can be @@ -3328,7 +3399,7 @@ ha_innobase::estimate_number_of_rows(void) index = dict_table_get_first_index_noninline(prebuilt->table); - data_file_length = ((ulonglong) index->stat_n_leaf_pages) + local_data_file_length = ((ulonglong) index->stat_n_leaf_pages) * UNIV_PAGE_SIZE; /* Calculate a minimum length for a clustered index record and from @@ -3337,7 +3408,7 @@ ha_innobase::estimate_number_of_rows(void) by a threshold factor, we must add a safety factor 2 in front of the formula below. */ - estimate = 2 * data_file_length / dict_index_calc_min_rec_len(index); + estimate = 2 * local_data_file_length / dict_index_calc_min_rec_len(index); DBUG_RETURN((ha_rows) estimate); } @@ -3374,12 +3445,21 @@ ha_innobase::info( row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt; dict_table_t* ib_table; dict_index_t* index; - ulong rec_per_key; + ha_rows rec_per_key; ulong j; ulong i; DBUG_ENTER("info"); + /* If we are forcing recovery at a high level, we will suppress + statistics calculation on tables, because that may crash the + server if an index is badly corrupted. */ + + if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) { + + return; + } + /* Warning: since it is not sure that MySQL calls external_lock before calling this function, the trx field in prebuilt can be obsolete! */ @@ -3426,7 +3506,7 @@ ha_innobase::info( rec_per_key = records; } else { - rec_per_key = (ulong)(records / + rec_per_key = (ha_rows)(records / index->stat_n_diff_key_vals[j + 1]); } @@ -3441,8 +3521,9 @@ ha_innobase::info( rec_per_key = 1; } - table->key_info[i].rec_per_key[j] - = rec_per_key; + table->key_info[i].rec_per_key[j]= + rec_per_key >= ~(ulong) 0 ? ~(ulong) 0 : + rec_per_key; } index = dict_table_get_next_index_noninline(index); @@ -3641,7 +3722,6 @@ ha_innobase::reset(void) return(0); } - /********************************************************************** When we create a temporary table inside MySQL LOCK TABLES, MySQL will not call external_lock for the temporary table when it uses it. Instead, @@ -3663,12 +3743,20 @@ ha_innobase::start_stmt( innobase_release_stat_resources(trx); trx_mark_sql_stat_end(trx); + if (trx->isolation_level <= TRX_ISO_READ_COMMITTED + && trx->read_view) { + /* At low transaction isolation levels we let + each consistent read set its own snapshot */ + + read_view_close_for_mysql(trx); + } + auto_inc_counter_for_this_stat = 0; prebuilt->sql_stat_start = TRUE; prebuilt->hint_no_need_to_fetch_extra_cols = TRUE; prebuilt->read_just_key = 0; - if (prebuilt->select_lock_type == LOCK_NONE) { + if (!prebuilt->mysql_has_locked) { /* This handle is for a temporary table created inside this same LOCK TABLES; since MySQL does NOT call external_lock in this case, we must use x-row locks inside InnoDB to be @@ -3683,6 +3771,24 @@ ha_innobase::start_stmt( } /********************************************************************** +Maps a MySQL trx isolation level code to the InnoDB isolation level code */ +inline +ulint +innobase_map_isolation_level( +/*=========================*/ + /* out: InnoDB isolation level */ + enum_tx_isolation iso) /* in: MySQL isolation level code */ +{ + switch(iso) { + case ISO_READ_COMMITTED: return(TRX_ISO_READ_COMMITTED); + case ISO_REPEATABLE_READ: return(TRX_ISO_REPEATABLE_READ); + case ISO_SERIALIZABLE: return(TRX_ISO_SERIALIZABLE); + case ISO_READ_UNCOMMITTED: return(TRX_ISO_READ_UNCOMMITTED); + default: ut_a(0); return(0); + } +} + +/********************************************************************** As MySQL will execute an external lock for every new table it uses when it starts to process an SQL statement (an exception is when MySQL calls start_stmt for the handle) we can use this function to store the pointer to @@ -3703,6 +3809,7 @@ ha_innobase::external_lock( trx_t* trx; DBUG_ENTER("ha_innobase::external_lock"); + DBUG_PRINT("enter",("lock_type: %d", lock_type)); update_thd(thd); @@ -3727,8 +3834,15 @@ ha_innobase::external_lock( thd->transaction.all.innodb_active_trans = 1; trx->n_mysql_tables_in_use++; + prebuilt->mysql_has_locked = TRUE; - if (thd->variables.tx_isolation == ISO_SERIALIZABLE + if (thd->variables.tx_isolation != ISO_REPEATABLE_READ) { + trx->isolation_level = innobase_map_isolation_level( + (enum_tx_isolation) + thd->variables.tx_isolation); + } + + if (trx->isolation_level == TRX_ISO_SERIALIZABLE && prebuilt->select_lock_type == LOCK_NONE) { /* To get serializable execution we let InnoDB @@ -3744,6 +3858,7 @@ ha_innobase::external_lock( } } else { trx->n_mysql_tables_in_use--; + prebuilt->mysql_has_locked = FALSE; auto_inc_counter_for_this_stat = 0; if (trx->n_mysql_tables_in_use == 0) { @@ -3755,6 +3870,15 @@ ha_innobase::external_lock( innobase_release_stat_resources(trx); + if (trx->isolation_level <= TRX_ISO_READ_COMMITTED + && trx->read_view) { + + /* At low transaction isolation levels we let + each consistent read set its own snapshot */ + + read_view_close_for_mysql(trx); + } + if (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) { @@ -3779,14 +3903,13 @@ innodb_show_status( char* buf; DBUG_ENTER("innodb_show_status"); - + if (innodb_skip) { - - fprintf(stderr, - "Cannot call SHOW INNODB STATUS because skip-innodb is defined\n"); - - DBUG_RETURN(-1); - } + my_message(ER_NOT_SUPPORTED_YET, + "Cannot call SHOW INNODB STATUS because skip-innodb is defined", + MYF(0)); + DBUG_RETURN(-1); + } /* We let the InnoDB Monitor to output at most 100 kB of text, add a safety margin of 10 kB for buffer overruns */ diff --git a/sql/ha_innodb.h b/sql/ha_innodb.h index 357fb31b5e3..d2639f39c5b 100644 --- a/sql/ha_innodb.h +++ b/sql/ha_innodb.h @@ -96,7 +96,7 @@ class ha_innobase: public handler ulong index_flags(uint idx) const { return (HA_READ_NEXT | HA_READ_PREV | HA_READ_ORDER | - HA_KEY_READ_ONLY | HA_NOT_READ_PREFIX_LAST); + HA_KEY_READ_ONLY); } uint max_record_length() const { return HA_MAX_REC_LENGTH; } uint max_keys() const { return MAX_KEY; } diff --git a/sql/ha_isam.cc b/sql/ha_isam.cc index 052e6a4b9ec..6fa54d18aac 100644 --- a/sql/ha_isam.cc +++ b/sql/ha_isam.cc @@ -380,7 +380,8 @@ int ha_isam::create(const char *name, register TABLE *form, } recinfo_pos->base.type= (int) FIELD_LAST; /* End of fieldinfo */ error=nisam_create(fn_format(buff,name,"","",2+4+16),form->keys,keydef, - recinfo,form->max_rows,form->min_rows,0,0,0L); + recinfo,(ulong) form->max_rows, (ulong) form->min_rows, + 0, 0, 0L); my_free((gptr) recinfo,MYF(0)); DBUG_RETURN(error); diff --git a/sql/ha_isammrg.cc b/sql/ha_isammrg.cc index b110ffba2f9..94e394e7665 100644 --- a/sql/ha_isammrg.cc +++ b/sql/ha_isammrg.cc @@ -190,13 +190,15 @@ THR_LOCK_DATA **ha_isammrg::store_lock(THD *thd, THR_LOCK_DATA **to, enum thr_lock_type lock_type) { - MRG_TABLE *table; + MRG_TABLE *open_table; - for (table=file->open_tables ; table != file->end_table ; table++) + for (open_table=file->open_tables ; + open_table != file->end_table ; + open_table++) { - *(to++)= &table->table->lock; - if (lock_type != TL_IGNORE && table->table->lock.type == TL_UNLOCK) - table->table->lock.type=lock_type; + *(to++)= &open_table->table->lock; + if (lock_type != TL_IGNORE && open_table->table->lock.type == TL_UNLOCK) + open_table->table->lock.type=lock_type; } return to; } diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc index c7f0ccf69ee..ae71e362875 100644 --- a/sql/ha_myisam.cc +++ b/sql/ha_myisam.cc @@ -576,7 +576,6 @@ int ha_myisam::repair(THD *thd, MI_CHECK ¶m, bool optimize) } if (!optimize || - //memcmp(file->state, & share->state.state, sizeof(MI_STATUS_INFO)) || ((file->state->del || share->state.split != file->state->records) && (!(param.testflag & T_QUICK) || !(share->state.changed & STATE_NOT_OPTIMIZED_KEYS)))) @@ -635,7 +634,12 @@ int ha_myisam::repair(THD *thd, MI_CHECK ¶m, bool optimize) STATE_CRASHED_ON_REPAIR); file->update|=HA_STATE_CHANGED | HA_STATE_ROW_CHANGED; } - //file->save_state=file->s->state.state; + /* + the following 'if', thought conceptually wrong, + is a useful optimization nevertheless. + */ + if (file->state != &file->s->state.state); + file->s->state.state = *file->state; if (file->s->base.auto_key) update_auto_increment_key(¶m, file, 1); if (optimize_done) @@ -914,7 +918,7 @@ void ha_myisam::info(uint flag) if (table->key_parts) memcpy((char*) table->key_info[0].rec_per_key, (char*) info.rec_per_key, - sizeof(ulong)*table->key_parts); + sizeof(table->key_info[0].rec_per_key)*table->key_parts); raid_type=info.raid_type; raid_chunks=info.raid_chunks; raid_chunksize=info.raid_chunksize; @@ -1014,7 +1018,7 @@ void ha_myisam::update_create_info(HA_CREATE_INFO *create_info) } -int ha_myisam::create(const char *name, register TABLE *table, +int ha_myisam::create(const char *name, register TABLE *table_arg, HA_CREATE_INFO *info) { int error; @@ -1026,20 +1030,20 @@ int ha_myisam::create(const char *name, register TABLE *table, MI_KEYDEF *keydef; MI_COLUMNDEF *recinfo,*recinfo_pos; HA_KEYSEG *keyseg; - uint options=table->db_options_in_use; + uint options=table_arg->db_options_in_use; DBUG_ENTER("ha_myisam::create"); type=HA_KEYTYPE_BINARY; // Keep compiler happy if (!(my_multi_malloc(MYF(MY_WME), - &recinfo,(table->fields*2+2)*sizeof(MI_COLUMNDEF), - &keydef, table->keys*sizeof(MI_KEYDEF), + &recinfo,(table_arg->fields*2+2)*sizeof(MI_COLUMNDEF), + &keydef, table_arg->keys*sizeof(MI_KEYDEF), &keyseg, - ((table->key_parts + table->keys) * sizeof(HA_KEYSEG)), + ((table_arg->key_parts + table_arg->keys) * sizeof(HA_KEYSEG)), 0))) DBUG_RETURN(1); - pos=table->key_info; - for (i=0; i < table->keys ; i++, pos++) + pos=table_arg->key_info; + for (i=0; i < table_arg->keys ; i++, pos++) { keydef[i].flag= (pos->flags & (HA_NOSAME | HA_FULLTEXT | HA_SPATIAL)); keydef[i].key_alg=pos->algorithm == HA_KEY_ALG_UNDEF ? @@ -1084,7 +1088,7 @@ int ha_myisam::create(const char *name, register TABLE *table, { keydef[i].seg[j].null_bit=field->null_bit; keydef[i].seg[j].null_pos= (uint) (field->null_ptr- - (uchar*) table->record[0]); + (uchar*) table_arg->record[0]); } else { @@ -1102,19 +1106,19 @@ int ha_myisam::create(const char *name, register TABLE *table, keydef[i].seg[j].flag|=HA_BLOB_PART; /* save number of bytes used to pack length */ keydef[i].seg[j].bit_start= (uint) (field->pack_length() - - table->blob_ptr_size); + table_arg->blob_ptr_size); } } keyseg+=pos->key_parts; } recpos=0; recinfo_pos=recinfo; - while (recpos < (uint) table->reclength) + while (recpos < (uint) table_arg->reclength) { Field **field,*found=0; - minpos=table->reclength; length=0; + minpos=table_arg->reclength; length=0; - for (field=table->field ; *field ; field++) + for (field=table_arg->field ; *field ; field++) { if ((fieldpos=(*field)->offset()) >= recpos && fieldpos <= minpos) @@ -1160,7 +1164,7 @@ int ha_myisam::create(const char *name, register TABLE *table, { recinfo_pos->null_bit=found->null_bit; recinfo_pos->null_pos= (uint) (found->null_ptr- - (uchar*) table->record[0]); + (uchar*) table_arg->record[0]); } else { @@ -1175,13 +1179,13 @@ int ha_myisam::create(const char *name, register TABLE *table, } MI_CREATE_INFO create_info; bzero((char*) &create_info,sizeof(create_info)); - create_info.max_rows=table->max_rows; - create_info.reloc_rows=table->min_rows; + create_info.max_rows=table_arg->max_rows; + create_info.reloc_rows=table_arg->min_rows; create_info.auto_increment=(info->auto_increment_value ? info->auto_increment_value -1 : (ulonglong) 0); - create_info.data_file_length= ((ulonglong) table->max_rows * - table->avg_row_length); + create_info.data_file_length= ((ulonglong) table_arg->max_rows * + table_arg->avg_row_length); create_info.raid_type=info->raid_type; create_info.raid_chunks= (info->raid_chunks ? info->raid_chunks : RAID_DEFAULT_CHUNKS); @@ -1191,7 +1195,7 @@ int ha_myisam::create(const char *name, register TABLE *table, create_info.index_file_name=info->index_file_name; error=mi_create(fn_format(buff,name,"","",2+4), - table->keys,keydef, + table_arg->keys,keydef, (uint) (recinfo_pos-recinfo), recinfo, 0, (MI_UNIQUEDEF*) 0, &create_info, diff --git a/sql/ha_myisammrg.cc b/sql/ha_myisammrg.cc index c35bf657445..07683dca73e 100644 --- a/sql/ha_myisammrg.cc +++ b/sql/ha_myisammrg.cc @@ -187,6 +187,19 @@ void ha_myisammrg::position(const byte *record) ha_store_ptr(ref, ref_length, (my_off_t) position); } +ha_rows ha_myisammrg::records_in_range(int inx, + const byte *start_key,uint start_key_len, + enum ha_rkey_function start_search_flag, + const byte *end_key,uint end_key_len, + enum ha_rkey_function end_search_flag) +{ + return (ha_rows) myrg_records_in_range(file, + inx, + start_key,start_key_len, + start_search_flag, + end_key,end_key_len, + end_search_flag); +} void ha_myisammrg::info(uint flag) { @@ -262,13 +275,15 @@ THR_LOCK_DATA **ha_myisammrg::store_lock(THD *thd, THR_LOCK_DATA **to, enum thr_lock_type lock_type) { - MYRG_TABLE *table; + MYRG_TABLE *open_table; - for (table=file->open_tables ; table != file->end_table ; table++) + for (open_table=file->open_tables ; + open_table != file->end_table ; + open_table++) { - *(to++)= &table->table->lock; - if (lock_type != TL_IGNORE && table->table->lock.type == TL_UNLOCK) - table->table->lock.type=lock_type; + *(to++)= &open_table->table->lock; + if (lock_type != TL_IGNORE && open_table->table->lock.type == TL_UNLOCK) + open_table->table->lock.type=lock_type; } return to; } @@ -279,14 +294,16 @@ void ha_myisammrg::update_create_info(HA_CREATE_INFO *create_info) DBUG_ENTER("ha_myisammrg::update_create_info"); if (!(create_info->used_fields & HA_CREATE_USED_UNION)) { - MYRG_TABLE *table; + MYRG_TABLE *open_table; THD *thd=current_thd; create_info->merge_list.next= &create_info->merge_list.first; create_info->merge_list.elements=0; - for (table=file->open_tables ; table != file->end_table ; table++) + for (open_table=file->open_tables ; + open_table != file->end_table ; + open_table++) { - char *name=table->table->filename; + char *name=open_table->table->filename; char buff[FN_REFLEN]; TABLE_LIST *ptr; if (!(ptr = (TABLE_LIST *) thd->calloc(sizeof(TABLE_LIST)))) @@ -323,7 +340,28 @@ int ha_myisammrg::create(const char *name, register TABLE *form, sizeof(char*)))) DBUG_RETURN(1); for (pos=table_names ; tables ; tables=tables->next) - *pos++= tables->real_name; + { + char *table_name; + if (create_info->options & HA_LEX_CREATE_TMP_TABLE) + { + TABLE **tbl=find_temporary_table(current_thd, + tables->db, tables->real_name); + if (!tbl) + { + table_name=sql_alloc(1+ + my_snprintf(buff,FN_REFLEN,"%s/%s/%s",mysql_real_data_home, + tables->db, tables->real_name)); + if (!table_name) + DBUG_RETURN(1); + strcpy(table_name, buff); + } + else + table_name=(*tbl)->path; + } + else + table_name=tables->real_name; + *pos++= table_name; + } *pos=0; DBUG_RETURN(myrg_create(fn_format(buff,name,"","",2+4+16), (const char **) table_names, @@ -340,13 +378,15 @@ void ha_myisammrg::append_create_info(String *packet) packet->append(get_type(&merge_insert_method,file->merge_insert_method-1)); } packet->append(" UNION=(",8); - MYRG_TABLE *table,*first; + MYRG_TABLE *open_table,*first; - for (first=table=file->open_tables ; table != file->end_table ; table++) + for (first=open_table=file->open_tables ; + open_table != file->end_table ; + open_table++) { - char *name=table->table->filename; + char *name= open_table->table->filename; fn_format(buff,name,"","",3); - if (table != first) + if (open_table != first) packet->append(','); packet->append(buff,(uint) strlen(buff)); } diff --git a/sql/ha_myisammrg.h b/sql/ha_myisammrg.h index b75d5360097..8e33b99e418 100644 --- a/sql/ha_myisammrg.h +++ b/sql/ha_myisammrg.h @@ -69,6 +69,11 @@ class ha_myisammrg: public handler int rnd_next(byte *buf); int rnd_pos(byte * buf, byte *pos); void position(const byte *record); + ha_rows ha_myisammrg::records_in_range(int inx, + const byte *start_key,uint start_key_len, + enum ha_rkey_function start_search_flag, + const byte *end_key,uint end_key_len, + enum ha_rkey_function end_search_flag); my_off_t row_position() { return myrg_position(file); } void info(uint); int extra(enum ha_extra_function operation); diff --git a/sql/handler.cc b/sql/handler.cc index f60c3449075..b2cf86a6abc 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -294,7 +294,8 @@ int ha_commit_trans(THD *thd, THD_TRANS* trans) error=1; } else - transaction_commited= 1; + if (!(thd->options & OPTION_BEGIN)) + transaction_commited= 1; trans->bdb_tid=0; } #endif diff --git a/sql/handler.h b/sql/handler.h index fbc27f4729b..6cbd83af282 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -153,7 +153,6 @@ typedef struct st_ha_create_information CHARSET_INFO *table_charset; char *comment,*password; char *data_file_name, *index_file_name; - char *create_statement; ulonglong max_rows,min_rows; ulonglong auto_increment_value; ulong table_options; @@ -230,7 +229,7 @@ public: void change_table_ptr(TABLE *table_arg) { table=table_arg; } virtual double scan_time() { return ulonglong2double(data_file_length) / IO_SIZE + 1; } - virtual double read_time(ha_rows rows) { return rows; } + virtual double read_time(ha_rows rows) { return rows2double(rows); } virtual bool fast_key_read() { return 0;} virtual key_map keys_to_use_for_scanning() { return 0; } virtual bool has_transactions(){ return 0;} diff --git a/sql/hash_filo.h b/sql/hash_filo.h index 4d746d9b9bd..f7384cc6e32 100644 --- a/sql/hash_filo.h +++ b/sql/hash_filo.h @@ -40,7 +40,7 @@ class hash_filo { const uint size, key_offset, key_length; const hash_get_key get_key; - void (*free_element)(void*); + hash_free_key free_element; bool init; hash_filo_element *first_link,*last_link; @@ -49,7 +49,7 @@ public: HASH cache; hash_filo(uint size_arg, uint key_offset_arg , uint key_length_arg, - hash_get_key get_key_arg,void (*free_element_arg)(void*)) + hash_get_key get_key_arg, hash_free_key free_element_arg) :size(size_arg), key_offset(key_offset_arg), key_length(key_length_arg), get_key(get_key_arg), free_element(free_element_arg),init(0) { diff --git a/sql/hostname.cc b/sql/hostname.cc index 3da752f3b64..609532a67d6 100644 --- a/sql/hostname.cc +++ b/sql/hostname.cc @@ -63,7 +63,7 @@ bool hostname_cache_init() if (!(hostname_cache=new hash_filo(HOST_CACHE_SIZE, offset, sizeof(struct in_addr),NULL, - (void (*)(void*)) free))) + (hash_free_key) free))) return 1; hostname_cache->clear(); return 0; diff --git a/sql/item.h b/sql/item.h index c67c16c50ad..5eeaa22a2a2 100644 --- a/sql/item.h +++ b/sql/item.h @@ -89,8 +89,8 @@ public: virtual CHARSET_INFO *charset() const { return str_value.charset(); }; virtual bool binary() const { return str_value.charset()->state & MY_CS_BINSORT ? 1 : 0 ; } virtual void set_charset(CHARSET_INFO *cs) { str_value.set_charset(cs); } - virtual bool check_loop(uint id); + virtual void top_level_item() {} }; diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 74eb5734ecf..1065c8cf023 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -27,8 +27,8 @@ /* Test functions - These returns 0LL if false and 1LL if true and null if some arg is null - 'AND' and 'OR' never return null + Most of these returns 0LL if false and 1LL if true and + NULL if some arg is NULL. */ longlong Item_func_not::val_int() @@ -362,13 +362,19 @@ void Item_func_between::fix_length_and_dec() */ if (!args[0] || !args[1] || !args[2]) return; - cmp_type=args[0]->result_type(); - if (args[0]->binary()) + cmp_type=item_cmp_type(args[0]->result_type(), + item_cmp_type(args[1]->result_type(), + args[2]->result_type())); + if (args[0]->binary() | args[1]->binary() | args[2]->binary()) string_compare=stringcmp; else string_compare=sortcmp; - // Make a special case of compare with fields to get nicer DATE comparisons + /* + Make a special case of compare with date/time and longlong fields. + They are compared as integers, so for const item this time-consuming + conversion can be done only once, not for every single comparison + */ if (args[0]->type() == FIELD_ITEM) { Field *field=((Item_field*) args[0])->field; @@ -1141,6 +1147,8 @@ Item_cond::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) #endif item= *li.ref(); // new current item } + if (abort_on_null) + item->top_level_item(); if (item->fix_fields(thd, tables, li.ref())) return 1; /* purecov: inspected */ used_tables_cache|=item->used_tables(); @@ -1230,28 +1238,41 @@ void Item_cond::print(String *str) str->append(')'); } +/* + Evalution of AND(expr, expr, expr ...) + + NOTES: + abort_if_null is set for AND expressions for which we don't care if the + result is NULL or 0. This is set for: + - WHERE clause + - HAVING clause + - IF(expression) + + RETURN VALUES + 1 If all expressions are true + 0 If all expressions are false or if we find a NULL expression and + 'abort_on_null' is set. + NULL if all expression are either 1 or NULL +*/ + longlong Item_cond_and::val_int() { List_iterator_fast<Item> li(list); Item *item; + null_value= 0; while ((item=li++)) { if (item->val_int() == 0) { - /* - TODO: In case of NULL, ANSI would require us to continue evaluation - until we get a FALSE value or run out of values; This would - require a lot of unnecessary evaluation, which we skip for now - */ - null_value=item->null_value; - return 0; + if (abort_on_null || !(null_value= item->null_value)) + return 0; // return FALSE } } - null_value=0; - return 1; + return null_value ? 0 : 1; } + longlong Item_cond_or::val_int() { List_iterator_fast<Item> li(list); @@ -1270,6 +1291,45 @@ longlong Item_cond_or::val_int() return 0; } +/* + Create an AND expression from two expressions + + SYNOPSIS + and_expressions() + a expression or NULL + b expression. + org_item Don't modify a if a == *org_item + If a == NULL, org_item is set to point at b, + to ensure that future calls will not modify b. + + NOTES + This will not modify item pointed to by org_item or b + The idea is that one can call this in a loop and create and + 'and' over all items without modifying any of the original items. + + RETURN + NULL Error + Item +*/ + +Item *and_expressions(Item *a, Item *b, Item **org_item) +{ + if (!a) + return (*org_item= b); + if (a == *org_item) + { + Item_cond *res; + if ((res= new Item_cond_and(a, b))) + res->used_tables_cache= a->used_tables() | b->used_tables(); + return res; + } + if (((Item_cond_and*) a)->add(b)) + return 0; + ((Item_cond_and*) a)->used_tables_cache|= b->used_tables(); + return a; +} + + longlong Item_func_isnull::val_int() { /* diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 489d54ae786..a9dc6c87f95 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -213,6 +213,11 @@ public: longlong val_int(); String *val_str(String *str); enum Item_result result_type () const { return cached_result_type; } + bool fix_fields(THD *thd,struct st_table_list *tlist) + { + args[0]->top_level_item(); + return Item_func::fix_fields(thd,tlist); + } void fix_length_and_dec(); const char *func_name() const { return "if"; } }; @@ -286,9 +291,9 @@ public: virtual void set(uint pos,Item *item)=0; virtual byte *get_value(Item *item)=0; void sort() - { - qsort(base,used_count,size,compare); - } + { + qsort(base,used_count,size,compare); + } int find(Item *item); }; @@ -557,10 +562,12 @@ class Item_cond :public Item_bool_func { protected: List<Item> list; + bool abort_on_null; public: - Item_cond() : Item_bool_func() { const_item_cache=0; } - Item_cond(Item *i1,Item *i2) :Item_bool_func() - { list.push_back(i1); list.push_back(i2); } + /* Item_cond() is only used to create top level items */ + Item_cond() : Item_bool_func(), abort_on_null(1) { const_item_cache=0; } + Item_cond(Item *i1,Item *i2) :Item_bool_func(), abort_on_null(0) + { list.push_back(i1); list.push_back(i2); } ~Item_cond() { list.delete_elements(); } bool add(Item *item) { return list.push_back(item); } bool fix_fields(THD *, struct st_table_list *, Item **ref); @@ -573,6 +580,7 @@ public: void split_sum_func(List<Item> &fields); friend int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds); bool check_loop(uint id); + void top_level_item() { abort_on_null=1; } }; @@ -620,6 +628,7 @@ inline Item *and_conds(Item *a,Item *b) return cond; } +Item *and_expressions(Item *a, Item *b, Item **org_item); /************************************************************** Spatial relations diff --git a/sql/item_func.cc b/sql/item_func.cc index 4c7985cd1bf..75260065be6 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -787,13 +787,14 @@ double Item_func_rand::val() } else if (!thd->rand_used) { - // no need to send a Rand log event if seed was given eg: RAND(seed), - // as it will be replicated in the query as such. - - // save the seed only the first time RAND() is used in the query + /* + No need to send a Rand log event if seed was given eg: RAND(seed), + as it will be replicated in the query as such. - // once events are forwarded rather than recreated, - // the following can be skipped if inside the slave thread + Save the seed only the first time RAND() is used in the query + Once events are forwarded rather than recreated, + the following can be skipped if inside the slave thread + */ thd->rand_used=1; thd->rand_saved_seed1=thd->rand.seed1; thd->rand_saved_seed2=thd->rand.seed2; @@ -1606,7 +1607,7 @@ void item_user_lock_release(ULL *ull) tmp.copy(command, strlen(command), tmp.charset()); tmp.append(ull->key,ull->key_length); tmp.append("\")"); - Query_log_event qev(current_thd,tmp.ptr(), tmp.length()); + Query_log_event qev(current_thd, tmp.ptr(), tmp.length(),1); qev.error_code=0; // this query is always safe to run on slave mysql_bin_log.write(&qev); } @@ -2051,13 +2052,13 @@ void Item_func_set_user_var::print(String *str) user_var_entry *Item_func_get_user_var::get_entry() { - if (!entry || ! entry->value) + if (!var_entry || ! var_entry->value) { null_value=1; return 0; } null_value=0; - return entry; + return var_entry; } @@ -2126,8 +2127,8 @@ void Item_func_get_user_var::fix_length_and_dec() maybe_null=1; decimals=NOT_FIXED_DEC; max_length=MAX_BLOB_WIDTH; - if ((entry= get_variable(&thd->user_vars, name, 0))) - const_var_flag= thd->query_id != entry->update_query_id; + if ((var_entry= get_variable(&thd->user_vars, name, 0))) + const_var_flag= thd->query_id != var_entry->update_query_id; } @@ -2317,18 +2318,18 @@ bool Item_func_match::fix_index() { List_iterator_fast<Item> li(fields); Item_field *item; - uint ft_to_key[MAX_KEY], ft_cnt[MAX_KEY], fts=0, key; + uint ft_to_key[MAX_KEY], ft_cnt[MAX_KEY], fts=0, keynr; uint max_cnt=0, mkeys=0; - if (this->key == NO_SUCH_KEY) + if (key == NO_SUCH_KEY) return 0; - for (key=0 ; key<table->keys ; key++) + for (keynr=0 ; keynr < table->keys ; keynr++) { - if ((table->key_info[key].flags & HA_FULLTEXT) && - (table->keys_in_use_for_query & (((key_map)1) << key))) + if ((table->key_info[keynr].flags & HA_FULLTEXT) && + (table->keys_in_use_for_query & (((key_map)1) << keynr))) { - ft_to_key[fts]=key; + ft_to_key[fts]=keynr; ft_cnt[fts]=0; fts++; } @@ -2339,45 +2340,45 @@ bool Item_func_match::fix_index() while ((item=(Item_field*)(li++))) { - for (key=0 ; key<fts ; key++) + for (keynr=0 ; keynr < fts ; keynr++) { - KEY *ft_key=&table->key_info[ft_to_key[key]]; + KEY *ft_key=&table->key_info[ft_to_key[keynr]]; uint key_parts=ft_key->key_parts; for (uint part=0 ; part < key_parts ; part++) { if (item->field->eq(ft_key->key_part[part].field)) - ft_cnt[key]++; + ft_cnt[keynr]++; } } } - for (key=0 ; key<fts ; key++) + for (keynr=0 ; keynr < fts ; keynr++) { - if (ft_cnt[key] > max_cnt) + if (ft_cnt[keynr] > max_cnt) { mkeys=0; - max_cnt=ft_cnt[mkeys]=ft_cnt[key]; - ft_to_key[mkeys]=ft_to_key[key]; + max_cnt=ft_cnt[mkeys]=ft_cnt[keynr]; + ft_to_key[mkeys]=ft_to_key[keynr]; continue; } - if (max_cnt && ft_cnt[key] == max_cnt) + if (max_cnt && ft_cnt[keynr] == max_cnt) { mkeys++; - ft_cnt[mkeys]=ft_cnt[key]; - ft_to_key[mkeys]=ft_to_key[key]; + ft_cnt[mkeys]=ft_cnt[keynr]; + ft_to_key[mkeys]=ft_to_key[keynr]; continue; } } - for (key=0 ; key<=mkeys ; key++) + for (keynr=0 ; keynr <= mkeys ; keynr++) { // for now, partial keys won't work. SerG if (max_cnt < fields.elements || - max_cnt < table->key_info[ft_to_key[key]].key_parts) + max_cnt < table->key_info[ft_to_key[keynr]].key_parts) continue; - this->key=ft_to_key[key]; + key=ft_to_key[keynr]; return 0; } @@ -2385,7 +2386,7 @@ bool Item_func_match::fix_index() err: if (mode == FT_BOOL) { - this->key=NO_SUCH_KEY; + key=NO_SUCH_KEY; return 0; } my_printf_error(ER_FT_MATCHING_KEY_NOT_FOUND, diff --git a/sql/item_func.h b/sql/item_func.h index 8996919e284..b659a6d69d2 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -918,7 +918,7 @@ public: class Item_func_get_user_var :public Item_func { LEX_STRING name; - user_var_entry *entry; + user_var_entry *var_entry; bool const_var_flag; public: diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index cec83428e24..7c085a1b25a 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -198,15 +198,28 @@ longlong Item_func_second::val_int() } -// Returns the week of year in the range of 0 - 53 +/* + Returns the week of year. + + The bits in week_format has the following meaning: + 0 If not set: USA format: Sunday is first day of week + If set: ISO format: Monday is first day of week + 1 If not set: Week is in range 0-53 + If set Week is in range 1-53. +*/ longlong Item_func_week::val_int() { uint year; + uint week_format; TIME ltime; if (get_arg0_date(<ime,0)) return 0; - return (longlong) calc_week(<ime, 0, args[1]->val_int() == 0, &year); + week_format= (uint) args[1]->val_int(); + return (longlong) calc_week(<ime, + (week_format & 2) != 0, + (week_format & 1) == 0, + &year); } @@ -216,7 +229,7 @@ longlong Item_func_yearweek::val_int() TIME ltime; if (get_arg0_date(<ime,0)) return 0; - week=calc_week(<ime, 1, args[1]->val_int() == 0, &year); + week=calc_week(<ime, 1, (args[1]->val_int() & 1) == 0, &year); return week+year*100; } diff --git a/sql/lex.h b/sql/lex.h index d4c64d08da4..0d0d60fe204 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -267,6 +267,7 @@ static SYMBOL symbols[] = { { "NOT", SYM(NOT),0,0}, { "NULL", SYM(NULL_SYM),0,0}, { "NUMERIC", SYM(NUMERIC_SYM),0,0}, + { "OFFSET", SYM(OFFSET_SYM),0,0}, { "ON", SYM(ON),0,0}, { "OPEN", SYM(OPEN_SYM),0,0}, { "OPTIMIZE", SYM(OPTIMIZE),0,0}, diff --git a/sql/lock.cc b/sql/lock.cc index 3b2444c8e9d..74d1109b203 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -80,7 +80,7 @@ extern HASH open_cache; static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table,uint count, bool unlock, TABLE **write_locked); -static int lock_external(TABLE **table,uint count); +static int lock_external(THD *thd, TABLE **table,uint count); static int unlock_external(THD *thd, TABLE **table,uint count); static void print_lock_error(int error); @@ -116,14 +116,14 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd,TABLE **tables,uint count) } thd->proc_info="System lock"; - if (lock_external(tables,count)) + if (lock_external(thd, tables, count)) { my_free((gptr) sql_lock,MYF(0)); sql_lock=0; thd->proc_info=0; break; } - thd->proc_info=0; + thd->proc_info="Table lock"; thd->locked=1; if (thr_multi_lock(sql_lock->locks,sql_lock->lock_count)) { @@ -142,6 +142,7 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd,TABLE **tables,uint count) thd->locked=0; break; } + thd->proc_info=0; /* some table was altered or deleted. reopen tables marked deleted */ mysql_unlock_tables(thd,sql_lock); @@ -151,6 +152,7 @@ retry: if (wait_for_tables(thd)) break; // Couldn't open tables } + thd->proc_info=0; if (thd->killed) { my_error(ER_SERVER_SHUTDOWN,MYF(0)); @@ -166,15 +168,15 @@ retry: } -static int lock_external(TABLE **tables,uint count) +static int lock_external(THD *thd, TABLE **tables, uint count) { reg1 uint i; int lock_type,error; - THD *thd=current_thd; DBUG_ENTER("lock_external"); for (i=1 ; i <= count ; i++, tables++) { + DBUG_ASSERT((*tables)->reginfo.lock_type >= TL_READ); lock_type=F_WRLCK; /* Lock exclusive */ if ((*tables)->db_stat & HA_READ_ONLY || ((*tables)->reginfo.lock_type >= TL_READ && diff --git a/sql/log.cc b/sql/log.cc index 286dba3f79b..0e1af8e5dae 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -1026,9 +1026,13 @@ bool MYSQL_LOG::write(THD *thd,enum enum_server_command command, bool MYSQL_LOG::write(Log_event* event_info) { bool error=0; + DBUG_ENTER("MYSQL_LOG::write(event)"); if (!inited) // Can't use mutex if not init - return 0; + { + DBUG_PRINT("error",("not initied")); + DBUG_RETURN(0); + } pthread_mutex_lock(&LOCK_log); /* In most cases this is only called if 'is_open()' is true */ @@ -1036,7 +1040,7 @@ bool MYSQL_LOG::write(Log_event* event_info) { bool should_rotate = 0; THD *thd=event_info->thd; - const char* db = event_info->get_db(); + const char *local_db = event_info->get_db(); #ifdef USING_TRANSACTIONS IO_CACHE *file = ((event_info->get_cache_stmt()) ? &thd->transaction.trans_log : @@ -1046,10 +1050,11 @@ bool MYSQL_LOG::write(Log_event* event_info) #endif if ((thd && !(thd->options & OPTION_BIN_LOG) && (thd->master_access & SUPER_ACL)) || - (db && !db_ok(db, binlog_do_db, binlog_ignore_db))) + (local_db && !db_ok(local_db, binlog_do_db, binlog_ignore_db))) { VOID(pthread_mutex_unlock(&LOCK_log)); - return 0; + DBUG_PRINT("error",("!db_ok")); + DBUG_RETURN(0); } error=1; @@ -1087,7 +1092,7 @@ bool MYSQL_LOG::write(Log_event* event_info) char buf[1024] = "SET CHARACTER SET "; char* p = strend(buf); p = strmov(p, thd->variables.convert_set->name); - Query_log_event e(thd, buf, (ulong)(p - buf)); + Query_log_event e(thd, buf, (ulong)(p - buf), 0); e.set_log_pos(this); if (e.write(file)) goto err; @@ -1135,7 +1140,7 @@ err: } pthread_mutex_unlock(&LOCK_log); - return error; + DBUG_RETURN(error); } @@ -1165,6 +1170,7 @@ uint MYSQL_LOG::next_file_id() bool MYSQL_LOG::write(THD *thd, IO_CACHE *cache) { VOID(pthread_mutex_lock(&LOCK_log)); + DBUG_ENTER("MYSQL_LOG::write(cache"); if (is_open()) // Should always be true { @@ -1223,7 +1229,7 @@ bool MYSQL_LOG::write(THD *thd, IO_CACHE *cache) signal_update(); } VOID(pthread_mutex_unlock(&LOCK_log)); - return 0; + DBUG_RETURN(0); err: if (!write_error) @@ -1232,7 +1238,7 @@ err: sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno); } VOID(pthread_mutex_unlock(&LOCK_log)); - return 1; + DBUG_RETURN(1); } @@ -1242,7 +1248,7 @@ err: */ bool MYSQL_LOG::write(THD *thd,const char *query, uint query_length, - time_t query_start) + time_t query_start_arg) { bool error=0; if (is_open()) @@ -1260,7 +1266,7 @@ bool MYSQL_LOG::write(THD *thd,const char *query, uint query_length, VOID(pthread_mutex_unlock(&LOCK_log)); return 0; } - if ((specialflag & SPECIAL_LONG_LOG_FORMAT) || query_start) + if ((specialflag & SPECIAL_LONG_LOG_FORMAT) || query_start_arg) { current_time=time(NULL); if (current_time != last_time) @@ -1288,13 +1294,13 @@ bool MYSQL_LOG::write(THD *thd,const char *query, uint query_length, thd->ip ? thd->ip : "") == (uint) -1) tmp_errno=errno; } - if (query_start) + if (query_start_arg) { /* For slow query log */ if (my_b_printf(&log_file, "# Query_time: %lu Lock_time: %lu Rows_sent: %lu Rows_examined: %lu\n", - (ulong) (current_time - query_start), - (ulong) (thd->time_after_lock - query_start), + (ulong) (current_time - query_start_arg), + (ulong) (thd->time_after_lock - query_start_arg), (ulong) thd->sent_row_count, (ulong) thd->examined_row_count) == (uint) -1) tmp_errno=errno; @@ -1321,11 +1327,11 @@ bool MYSQL_LOG::write(THD *thd,const char *query, uint query_length, } if (thd->query_start_used) { - if (query_start != thd->query_start()) + if (query_start_arg != thd->query_start()) { - query_start=thd->query_start(); + query_start_arg=thd->query_start(); end=strmov(end,",timestamp="); - end=int10_to_str((long) query_start,end,10); + end=int10_to_str((long) query_start_arg,end,10); } } if (end != buff) diff --git a/sql/log_event.cc b/sql/log_event.cc index c168c951c8f..3747af22922 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -235,22 +235,25 @@ const char* Log_event::get_type_str() ****************************************************************************/ #ifndef MYSQL_CLIENT -Log_event::Log_event(THD* thd_arg, uint16 flags_arg) - :exec_time(0), flags(flags_arg), cached_event_len(0), - temp_buf(0), thd(thd_arg) +Log_event::Log_event(THD* thd_arg, uint16 flags_arg, bool using_trans) + :temp_buf(0), exec_time(0), cached_event_len(0), flags(flags_arg), + thd(thd_arg) { - if (thd) - { - server_id = thd->server_id; - when = thd->start_time; - log_pos = thd->log_pos; - } - else - { - server_id = ::server_id; - when = time(NULL); - log_pos =0; - } + server_id= thd->server_id; + when= thd->start_time; + log_pos= thd->log_pos; + cache_stmt= (using_trans && + (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))); +} + + +Log_event::Log_event() + :temp_buf(0), exec_time(0), cached_event_len(0), flags(0), cache_stmt(0), + thd(0) +{ + server_id= ::server_id; + when= time(NULL); + log_pos= 0; } #endif // !MYSQL_CLIENT @@ -260,7 +263,7 @@ Log_event::Log_event(THD* thd_arg, uint16 flags_arg) ****************************************************************************/ Log_event::Log_event(const char* buf, bool old_format) - :cached_event_len(0), temp_buf(0) + :temp_buf(0), cached_event_len(0), cache_stmt(0) { when = uint4korr(buf); server_id = uint4korr(buf + SERVER_ID_OFFSET); @@ -330,11 +333,11 @@ void Log_event::init_show_field_list(List<Item>* field_list) Only called by SHOW BINLOG EVENTS ****************************************************************************/ -int Log_event::net_send(THD* thd, const char* log_name, my_off_t pos) +int Log_event::net_send(THD* thd_arg, const char* log_name, my_off_t pos) { - String* packet = &thd->packet; - const char* p = strrchr(log_name, FN_LIBCHAR); - const char* event_type; + String* packet = &thd_arg->packet; + const char *p= strrchr(log_name, FN_LIBCHAR); + const char *event_type; if (p) log_name = p + 1; @@ -346,7 +349,7 @@ int Log_event::net_send(THD* thd, const char* log_name, my_off_t pos) net_store_data(packet, server_id); net_store_data(packet, (longlong) log_pos); pack_info(packet); - return my_net_write(&thd->net, (char*) packet->ptr(), packet->length()); + return my_net_write(&thd_arg->net, (char*) packet->ptr(), packet->length()); } #endif // !MYSQL_CLIENT @@ -725,12 +728,10 @@ int Query_log_event::write_data(IO_CACHE* file) #ifndef MYSQL_CLIENT Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg, ulong query_length, bool using_trans) - :Log_event(thd_arg), data_buf(0), query(query_arg), db(thd_arg->db), - q_len((uint32) query_length), + :Log_event(thd_arg, 0, using_trans), data_buf(0), query(query_arg), + db(thd_arg->db), q_len((uint32) query_length), error_code(thd_arg->killed ? ER_SERVER_SHUTDOWN: thd_arg->net.last_errno), - thread_id(thd_arg->thread_id), - cache_stmt(using_trans && - (thd_arg->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) + thread_id(thd_arg->thread_id) { time_t end_time; time(&end_time); @@ -1155,18 +1156,18 @@ int Load_log_event::write_data_body(IO_CACHE* file) ****************************************************************************/ #ifndef MYSQL_CLIENT -Load_log_event::Load_log_event(THD* thd, sql_exchange* ex, - const char* db_arg, const char* table_name_arg, - List<Item>& fields_arg, +Load_log_event::Load_log_event(THD *thd_arg, sql_exchange *ex, + const char *db_arg, const char *table_name_arg, + List<Item> &fields_arg, enum enum_duplicates handle_dup) - :Log_event(thd),thread_id(thd->thread_id), num_fields(0),fields(0), + :Log_event(thd_arg),thread_id(thd_arg->thread_id), num_fields(0),fields(0), field_lens(0),field_block_len(0), table_name(table_name_arg ? table_name_arg : ""), db(db_arg), fname(ex->file_name) { time_t end_time; time(&end_time); - exec_time = (ulong) (end_time - thd->start_time); + exec_time = (ulong) (end_time - thd_arg->start_time); /* db can never be a zero pointer in 4.0 */ db_len = (uint32) strlen(db); table_name_len = (uint32) strlen(table_name); @@ -1236,11 +1237,11 @@ Load_log_event::Load_log_event(THD* thd, sql_exchange* ex, constructed event. ****************************************************************************/ -Load_log_event::Load_log_event(const char* buf, int event_len, - bool old_format): - Log_event(buf, old_format),num_fields(0),fields(0), - field_lens(0),field_block_len(0), - table_name(0),db(0),fname(0) +Load_log_event::Load_log_event(const char *buf, int event_len, + bool old_format) + :Log_event(buf, old_format),num_fields(0),fields(0), + field_lens(0),field_block_len(0), + table_name(0),db(0),fname(0) { if (!event_len) // derived class, will call copy_log_event() itself return; @@ -1390,14 +1391,14 @@ void Load_log_event::print(FILE* file, bool short_form, char* last_db) ****************************************************************************/ #ifndef MYSQL_CLIENT -void Load_log_event::set_fields(List<Item> &fields) +void Load_log_event::set_fields(List<Item> &field_list) { uint i; - const char* field = this->fields; - for (i = 0; i < num_fields; i++) + const char* field = fields; + for (i= 0; i < num_fields; i++) { - fields.push_back(new Item_field(db, table_name, field)); - field += field_lens[i] + 1; + field_list.push_back(new Item_field(db, table_name, field)); + field+= field_lens[i] + 1; } } #endif // !MYSQL_CLIENT @@ -1458,8 +1459,8 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli) ex.field_term->length(0); ex.skip_lines = skip_lines; - List<Item> fields; - set_fields(fields); + List<Item> field_list; + set_fields(field_list); thd->slave_proxy_id = thd->thread_id; if (net) { @@ -1470,7 +1471,7 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli) */ thd->net.pkt_nr = net->pkt_nr; } - if (mysql_load(thd, &ex, &tables, fields, handle_dup, net != 0, + if (mysql_load(thd, &ex, &tables, field_list, handle_dup, net != 0, TL_WRITE)) thd->query_error = 1; if (thd->cuted_fields) @@ -1795,14 +1796,12 @@ int Intvar_log_event::exec_event(struct st_relay_log_info* rli) #ifndef MYSQL_CLIENT void Rand_log_event::pack_info(String* packet) { - char buf1[256], buf[22]; - String tmp(buf1, sizeof(buf1), system_charset_info); - tmp.length(0); - tmp.append("randseed1="); - tmp.append(llstr(seed1, buf)); - tmp.append(",randseed2="); - tmp.append(llstr(seed2, buf)); - net_store_data(packet, tmp.ptr(), tmp.length()); + char buf1[256], *pos; + pos= strmov(buf1,"rand_seed1="); + pos= int10_to_str((long) seed1, pos, 10); + pos= strmov(pos, ",rand_seed2="); + pos= int10_to_str((long) seed2, pos, 10); + net_store_data(packet, buf1, (uint) (pos-buf1)); } #endif // !MYSQL_CLIENT @@ -1846,8 +1845,8 @@ void Rand_log_event::print(FILE* file, bool short_form, char* last_db) print_header(file); fprintf(file, "\tRand\n"); } - fprintf(file, "SET RAND SEED1=%s;\n", llstr(seed1, llbuff)); - fprintf(file, "SET RAND SEED2=%s;\n", llstr(seed2, llbuff)); + fprintf(file, "SET @@RAND_SEED1=%s, @@RAND_SEED2=%s;\n", + llstr(seed1, llbuff),llstr(seed2, llbuff)); fflush(file); } #endif // MYSQL_CLIENT @@ -1860,8 +1859,8 @@ void Rand_log_event::print(FILE* file, bool short_form, char* last_db) #ifndef MYSQL_CLIENT int Rand_log_event::exec_event(struct st_relay_log_info* rli) { - thd->rand.seed1 = seed1; - thd->rand.seed2 = seed2; + thd->rand.seed1= (ulong) seed1; + thd->rand.seed2= (ulong) seed2; rli->inc_pending(get_event_len()); return 0; } @@ -1907,8 +1906,8 @@ void Slave_log_event::pack_info(String* packet) ****************************************************************************/ #ifndef MYSQL_CLIENT Slave_log_event::Slave_log_event(THD* thd_arg, - struct st_relay_log_info* rli): - Log_event(thd_arg),mem_pool(0),master_host(0) + struct st_relay_log_info* rli) + :Log_event(thd_arg, 0, 0), mem_pool(0), master_host(0) { DBUG_ENTER("Slave_log_event"); if (!rli->inited) // QQ When can this happen ? @@ -2120,11 +2119,13 @@ int Stop_log_event::exec_event(struct st_relay_log_info* rli) ****************************************************************************/ #ifndef MYSQL_CLIENT -Create_file_log_event::Create_file_log_event(THD* thd_arg, sql_exchange* ex, - const char* db_arg, const char* table_name_arg, - List<Item>& fields_arg, enum enum_duplicates handle_dup, - char* block_arg, uint block_len_arg) - :Load_log_event(thd_arg,ex,db_arg,table_name_arg,fields_arg,handle_dup), +Create_file_log_event:: +Create_file_log_event(THD* thd_arg, sql_exchange* ex, + const char* db_arg, const char* table_name_arg, + List<Item>& fields_arg, enum enum_duplicates handle_dup, + char* block_arg, uint block_len_arg, bool using_trans) + :Load_log_event(thd_arg,ex,db_arg,table_name_arg,fields_arg,handle_dup, + using_trans), fake_base(0),block(block_arg),block_len(block_len_arg), file_id(thd_arg->file_id = mysql_bin_log.next_file_id()) { @@ -2327,9 +2328,10 @@ err: ****************************************************************************/ #ifndef MYSQL_CLIENT Append_block_log_event::Append_block_log_event(THD* thd_arg, char* block_arg, - uint block_len_arg) - :Log_event(thd_arg), block(block_arg),block_len(block_len_arg), - file_id(thd_arg->file_id) + uint block_len_arg, + bool using_trans) + :Log_event(thd_arg,0, using_trans), block(block_arg), + block_len(block_len_arg), file_id(thd_arg->file_id) { } #endif // !MYSQL_CLIENT @@ -2447,8 +2449,8 @@ err: ****************************************************************************/ #ifndef MYSQL_CLIENT -Delete_file_log_event::Delete_file_log_event(THD* thd_arg) - :Log_event(thd_arg),file_id(thd_arg->file_id) +Delete_file_log_event::Delete_file_log_event(THD *thd_arg, bool using_trans) + :Log_event(thd_arg, 0, using_trans),file_id(thd_arg->file_id) { } #endif // !MYSQL_CLIENT @@ -2545,8 +2547,8 @@ int Delete_file_log_event::exec_event(struct st_relay_log_info* rli) ****************************************************************************/ #ifndef MYSQL_CLIENT -Execute_load_log_event::Execute_load_log_event(THD* thd_arg) - :Log_event(thd_arg),file_id(thd_arg->file_id) +Execute_load_log_event::Execute_load_log_event(THD *thd_arg, bool using_trans) + :Log_event(thd_arg, 0, using_trans), file_id(thd_arg->file_id) { } #endif // !MYSQL_CLIENT @@ -2556,8 +2558,8 @@ Execute_load_log_event::Execute_load_log_event(THD* thd_arg) Execute_load_log_event ctor ****************************************************************************/ -Execute_load_log_event::Execute_load_log_event(const char* buf,int len) - :Log_event(buf, 0),file_id(0) +Execute_load_log_event::Execute_load_log_event(const char* buf, int len) + :Log_event(buf, 0), file_id(0) { if ((uint)len < EXEC_LOAD_EVENT_OVERHEAD) return; diff --git a/sql/log_event.h b/sql/log_event.h index bf04c480729..20a134ab3cc 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -247,18 +247,19 @@ struct st_relay_log_info; class Log_event { public: + my_off_t log_pos; + char *temp_buf; time_t when; ulong exec_time; uint32 server_id; - my_off_t log_pos; + uint cached_event_len; uint16 flags; - int cached_event_len; - char* temp_buf; - + bool cache_stmt; #ifndef MYSQL_CLIENT THD* thd; - Log_event(THD* thd_arg, uint16 flags_arg = 0); + Log_event(THD* thd_arg, uint16 flags_arg, bool cache_stmt); + Log_event(); // if mutex is 0, the read will proceed without mutex static Log_event* read_log_event(IO_CACHE* file, pthread_mutex_t* log_lock, @@ -301,7 +302,7 @@ public: { return 0; } virtual Log_event_type get_type_code() = 0; virtual bool is_valid() = 0; - virtual bool get_cache_stmt() { return 0; } + inline bool get_cache_stmt() { return cache_stmt; } Log_event(const char* buf, bool old_format); virtual ~Log_event() { free_temp_buf();} void register_temp_buf(char* buf) { temp_buf = buf; } @@ -350,14 +351,12 @@ public: uint16 error_code; ulong thread_id; #ifndef MYSQL_CLIENT - bool cache_stmt; Query_log_event(THD* thd_arg, const char* query_arg, ulong query_length, - bool using_trans=0); + bool using_trans); const char* get_db() { return db; } void pack_info(String* packet); int exec_event(struct st_relay_log_info* rli); - bool get_cache_stmt() { return cache_stmt; } #else void print(FILE* file, bool short_form = 0, char* last_db = 0); #endif @@ -445,14 +444,15 @@ public: const char* fname; uint32 skip_lines; sql_ex_info sql_ex; - + #ifndef MYSQL_CLIENT String field_lens_buf; String fields_buf; Load_log_event(THD* thd, sql_exchange* ex, const char* db_arg, const char* table_name_arg, - List<Item>& fields_arg, enum enum_duplicates handle_dup); + List<Item>& fields_arg, enum enum_duplicates handle_dup, + bool using_trans); void set_fields(List<Item> &fields_arg); void pack_info(String* packet); const char* get_db() { return db; } @@ -468,8 +468,10 @@ public: Load_log_event(const char* buf, int event_len, bool old_format); ~Load_log_event() {} - Log_event_type get_type_code() { return sql_ex.new_format() ? - NEW_LOAD_EVENT: LOAD_EVENT; } + Log_event_type get_type_code() + { + return sql_ex.new_format() ? NEW_LOAD_EVENT: LOAD_EVENT; + } int write_data_header(IO_CACHE* file); int write_data_body(IO_CACHE* file); bool is_valid() { return table_name != 0; } @@ -500,7 +502,7 @@ public: char server_version[ST_SERVER_VER_LEN]; #ifndef MYSQL_CLIENT - Start_log_event() :Log_event((THD*)0),binlog_version(BINLOG_VERSION) + Start_log_event() :Log_event(), binlog_version(BINLOG_VERSION) { created = (uint32) when; memcpy(server_version, ::server_version, ST_SERVER_VER_LEN); @@ -538,7 +540,7 @@ public: #ifndef MYSQL_CLIENT Intvar_log_event(THD* thd_arg,uchar type_arg, ulonglong val_arg) - :Log_event(thd_arg),val(val_arg),type(type_arg) + :Log_event(),val(val_arg),type(type_arg) {} void pack_info(String* packet); int exec_event(struct st_relay_log_info* rli); @@ -570,7 +572,7 @@ class Rand_log_event: public Log_event #ifndef MYSQL_CLIENT Rand_log_event(THD* thd_arg, ulonglong seed1_arg, ulonglong seed2_arg) - :Log_event(thd_arg),seed1(seed1_arg),seed2(seed2_arg) + :Log_event(thd_arg,0,0),seed1(seed1_arg),seed2(seed2_arg) {} void pack_info(String* packet); int exec_event(struct st_relay_log_info* rli); @@ -596,7 +598,7 @@ class Stop_log_event: public Log_event { public: #ifndef MYSQL_CLIENT - Stop_log_event() :Log_event((THD*)0) + Stop_log_event() :Log_event() {} int exec_event(struct st_relay_log_info* rli); #else @@ -628,8 +630,9 @@ public: bool alloced; #ifndef MYSQL_CLIENT Rotate_log_event(THD* thd_arg, const char* new_log_ident_arg, - uint ident_len_arg = 0,ulonglong pos_arg = 4) - : Log_event(thd_arg), new_log_ident(new_log_ident_arg), + uint ident_len_arg = 0, + ulonglong pos_arg = LOG_EVENT_OFFSET) + :Log_event(thd_arg,0,0), new_log_ident(new_log_ident_arg), pos(pos_arg),ident_len(ident_len_arg ? ident_len_arg : (uint) strlen(new_log_ident_arg)), alloced(0) {} @@ -678,7 +681,8 @@ public: const char* table_name_arg, List<Item>& fields_arg, enum enum_duplicates handle_dup, - char* block_arg, uint block_len_arg); + char* block_arg, uint block_len_arg, + bool using_trans); void pack_info(String* packet); int exec_event(struct st_relay_log_info* rli); #else @@ -728,7 +732,7 @@ public: #ifndef MYSQL_CLIENT Append_block_log_event(THD* thd, char* block_arg, - uint block_len_arg); + uint block_len_arg, bool using_trans); int exec_event(struct st_relay_log_info* rli); void pack_info(String* packet); #else @@ -754,7 +758,7 @@ public: uint file_id; #ifndef MYSQL_CLIENT - Delete_file_log_event(THD* thd); + Delete_file_log_event(THD* thd, bool using_trans); void pack_info(String* packet); int exec_event(struct st_relay_log_info* rli); #else @@ -780,7 +784,7 @@ public: uint file_id; #ifndef MYSQL_CLIENT - Execute_load_log_event(THD* thd); + Execute_load_log_event(THD* thd, bool using_trans); void pack_info(String* packet); int exec_event(struct st_relay_log_info* rli); #else diff --git a/sql/mini_client.cc b/sql/mini_client.cc index aa84a52eb0b..0f20587ec24 100644 --- a/sql/mini_client.cc +++ b/sql/mini_client.cc @@ -295,11 +295,11 @@ static int mc_sock_connect(my_socket s, const struct sockaddr *name, FD_SET(s, &sfds); tv.tv_sec = (long) to; tv.tv_usec = 0; -#ifdef HPUX +#ifdef HPUX10 res = select(s+1, NULL, (int*) &sfds, NULL, &tv); #else res = select(s+1, NULL, &sfds, NULL, &tv); -#endif +#endif /* HPUX10 */ if (res <= 0) /* Never became writable */ return(-1); diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 392333a4971..4317ea05041 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -85,6 +85,7 @@ char* query_table_status(THD *thd,const char *db,const char *table_name); */ #define MIN_FILE_LENGTH_TO_USE_ROW_CACHE (16L*1024*1024) #define MIN_ROWS_TO_USE_TABLE_CACHE 100 +#define MIN_ROWS_TO_USE_BULK_INSERT 100 /* The following is used to decide if MySQL should use table scanning @@ -326,9 +327,8 @@ void mysql_init_multi_delete(LEX *lex); void init_max_user_conn(void); void init_update_queries(void); void free_max_user_conn(void); -pthread_handler_decl(handle_one_connection,arg); -pthread_handler_decl(handle_bootstrap,arg); -sig_handler end_thread_signal(int sig); +extern "C" pthread_handler_decl(handle_one_connection,arg); +extern "C" pthread_handler_decl(handle_bootstrap,arg); void end_thread(THD *thd,bool put_in_cache); void flush_thread_cache(); void mysql_execute_command(THD *thd); @@ -441,14 +441,12 @@ int mysql_drop_index(THD *thd, TABLE_LIST *table_list, int mysql_update(THD *thd,TABLE_LIST *tables,List<Item> &fields, List<Item> &values,COND *conds, ORDER *order, ha_rows limit, - enum enum_duplicates handle_duplicates, - thr_lock_type lock_type); + enum enum_duplicates handle_duplicates); int mysql_insert(THD *thd,TABLE_LIST *table,List<Item> &fields, - List<List_item> &values, enum_duplicates flag, - thr_lock_type lock_type); + List<List_item> &values, enum_duplicates flag); void kill_delayed_threads(void); int mysql_delete(THD *thd, TABLE_LIST *table, COND *conds, ORDER *order, - ha_rows rows, thr_lock_type lock_type, ulong options); + ha_rows rows, ulong options); int mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok=0); TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type update); TABLE *open_table(THD *thd,const char *db,const char *table,const char *alias, @@ -543,6 +541,7 @@ bool add_field_to_list(char *field_name, enum enum_field_types type, char *change, TYPELIB *interval,CHARSET_INFO *cs); void store_position_for_column(const char *name); bool add_to_list(SQL_LIST &list,Item *group,bool asc=0); +void set_lock_for_tables(thr_lock_type lock_type); void add_join_on(TABLE_LIST *b,Item *expr); void add_join_natural(TABLE_LIST *a,TABLE_LIST *b); bool add_proc_to_list(Item *item); @@ -609,7 +608,7 @@ int write_record(TABLE *table,COPY_INFO *info); extern ulong volatile manager_status; extern bool volatile manager_thread_in_use, mqh_used; extern pthread_t manager_thread; -pthread_handler_decl(handle_manager, arg); +extern "C" pthread_handler_decl(handle_manager, arg); /* sql_test.cc */ #ifndef DBUG_OFF @@ -637,6 +636,8 @@ bool open_log(MYSQL_LOG *log, const char *hostname, const char *index_file_name, enum_log_type type, bool read_append = 0, bool no_auto_events = 0); +/* mysqld.cc */ +void clear_error_message(THD *thd); /* External variables @@ -762,7 +763,7 @@ bool wait_for_locked_table_names(THD *thd, TABLE_LIST *table_list); /* old unireg functions */ void unireg_init(ulong options); -void unireg_end(int signal); +void unireg_end(void); int rea_create_table(THD *thd, my_string file_name,HA_CREATE_INFO *create_info, List<create_field> &create_field, uint key_count,KEY *key_info); @@ -791,7 +792,7 @@ timestamp_type str_to_TIME(const char *str, uint length, TIME *l_time, int test_if_number(char *str,int *res,bool allow_wildcards); void change_byte(byte *,uint,char,char); -void unireg_abort(int exit_code); +extern "C" void unireg_abort(int exit_code); void init_read_record(READ_RECORD *info, THD *thd, TABLE *reg_form, SQL_SELECT *select, int use_record_cache, bool print_errors); diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 755998bb8ba..ebda24b404a 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -279,7 +279,7 @@ static char* pidfile_name_ptr= pidfile_name; static pthread_t select_thread; static my_bool opt_noacl=0, opt_bootstrap=0, opt_myisam_log=0; my_bool opt_safe_user_create = 0, opt_no_mix_types = 0; -my_bool opt_safe_show_db=0, lower_case_table_names, opt_old_rpl_compat; +my_bool lower_case_table_names, opt_old_rpl_compat; my_bool opt_show_slave_auth_info, opt_sql_bin_update = 0; my_bool opt_log_slave_updates= 0; @@ -349,7 +349,7 @@ volatile ulong cached_thread_count=0; my_string master_user = (char*) "test", master_password = 0, master_host=0, master_info_file = (char*) "master.info", relay_log_info_file = (char*) "relay-log.info", - master_ssl_key=0, master_ssl_cert=0; + master_ssl_key=0, master_ssl_cert=0, master_ssl_capath=0, master_ssl_cipher=0; my_string report_user = 0, report_password = 0, report_host=0; const char *localhost=LOCAL_HOST; @@ -458,23 +458,23 @@ pthread_cond_t eventShutdown; #endif static void start_signal_handler(void); -static void *signal_hand(void *arg); +extern "C" pthread_handler_decl(signal_hand, arg); static void set_options(void); static void get_options(int argc,char **argv); static char *get_relative_path(const char *path); static void fix_paths(void); -static pthread_handler_decl(handle_connections_sockets,arg); -static pthread_handler_decl(kill_server_thread,arg); +extern "C" pthread_handler_decl(handle_connections_sockets,arg); +extern "C" pthread_handler_decl(kill_server_thread,arg); static int bootstrap(FILE *file); static void close_server_sock(); static bool read_init_file(char *file_name); #ifdef __NT__ -static pthread_handler_decl(handle_connections_namedpipes,arg); +extern "C" pthread_handler_decl(handle_connections_namedpipes,arg); #endif #ifdef HAVE_SMEM static pthread_handler_decl(handle_connections_shared_memory,arg); #endif -extern pthread_handler_decl(handle_slave,arg); +extern "C" pthread_handler_decl(handle_slave,arg); #ifdef SET_RLIMIT_NOFILE static uint set_maximum_open_files(uint max_file_limit); #endif @@ -781,14 +781,14 @@ static void __cdecl kill_server(int sig_ptr) if (sig != MYSQL_KILL_SIGNAL && sig != 0) unireg_abort(1); /* purecov: inspected */ else - unireg_end(0); + unireg_end(); pthread_exit(0); /* purecov: deadcode */ RETURN_FROM_KILL_SERVER; } #ifdef USE_ONE_SIGNAL_HAND -static pthread_handler_decl(kill_server_thread,arg __attribute__((unused))) +extern "C" pthread_handler_decl(kill_server_thread,arg __attribute__((unused))) { SHUTDOWN_THD; my_thread_init(); // Initialize new thread @@ -803,7 +803,7 @@ static pthread_handler_decl(kill_server_thread,arg __attribute__((unused))) #define sigset signal #endif -static sig_handler print_signal_warning(int sig) +extern "C" sig_handler print_signal_warning(int sig) { if (!DBUG_IN_USE) { @@ -820,16 +820,33 @@ static sig_handler print_signal_warning(int sig) #endif } +/* + cleanup all memory and end program nicely + + SYNOPSIS + unireg_end() + + NOTES + This function never returns. -void unireg_end(int signal_number __attribute__((unused))) + If SIGNALS_DONT_BREAK_READ is defined, this function is called + by the main thread. To get MySQL to shut down nicely in this case + (Mac OS X) we have to call exit() instead if pthread_exit(). +*/ + +void unireg_end(void) { clean_up(); my_thread_end(); +#ifdef SIGNALS_DONT_BREAK_READ + exit(0); +#else pthread_exit(0); // Exit is in main thread +#endif } -void unireg_abort(int exit_code) +extern "C" void unireg_abort(int exit_code) { DBUG_ENTER("unireg_abort"); if (exit_code) @@ -875,6 +892,9 @@ void clean_up(bool print_message) bitmap_free(&temp_pool); free_max_user_conn(); end_slave_list(); +#ifdef USE_REGEX + regex_end(); +#endif #if !defined(__WIN__) && !defined(EMBEDDED_LIBRARY) if (!opt_bootstrap) @@ -1176,7 +1196,7 @@ void close_connection(NET *net,uint errcode,bool lock) /* Called when a thread is aborted */ /* ARGSUSED */ -sig_handler end_thread_signal(int sig __attribute__((unused))) +extern "C" sig_handler end_thread_signal(int sig __attribute__((unused))) { THD *thd=current_thd; DBUG_ENTER("end_thread_signal"); @@ -1267,7 +1287,7 @@ void flush_thread_cache() */ #ifdef THREAD_SPECIFIC_SIGPIPE -static sig_handler abort_thread(int sig __attribute__((unused))) +extern "C" sig_handler abort_thread(int sig __attribute__((unused))) { THD *thd=current_thd; DBUG_ENTER("abort_thread"); @@ -1341,7 +1361,7 @@ static void start_signal_handler(void) #define UNSAFE_DEFAULT_LINUX_THREADS 200 #endif -static sig_handler handle_segfault(int sig) +extern "C" sig_handler handle_segfault(int sig) { THD *thd=current_thd; /* @@ -1418,7 +1438,11 @@ information that should help you find out what is causing the crash.\n"); #endif /* HAVE_STACKTRACE */ if (test_flags & TEST_CORE_ON_SIGNAL) + { + fprintf(stderr, "Writing a core file\n"); + fflush(stderr); write_core(sig); + } exit(1); } @@ -1526,7 +1550,7 @@ static void start_signal_handler(void) /* This threads handles all signals and alarms */ /* ARGSUSED */ -static void *signal_hand(void *arg __attribute__((unused))) +extern "C" void *signal_hand(void *arg __attribute__((unused))) { sigset_t set; int sig; @@ -1654,8 +1678,8 @@ static void *signal_hand(void *arg __attribute__((unused))) /* ARGSUSED */ -static int my_message_sql(uint error, const char *str, - myf MyFlags __attribute__((unused))) +extern "C" int my_message_sql(uint error, const char *str, + myf MyFlags __attribute__((unused))) { THD *thd; DBUG_ENTER("my_message_sql"); @@ -1675,6 +1699,17 @@ static int my_message_sql(uint error, const char *str, DBUG_RETURN(0); } + +/* + Forget last error message (if we got one) +*/ + +void clear_error_message(THD *thd) +{ + thd->net.last_error[0]= 0; +} + + #ifdef __WIN__ struct utsname @@ -1690,7 +1725,7 @@ int uname(struct utsname *a) #ifdef __WIN__ -pthread_handler_decl(handle_shutdown,arg) +extern "C" pthread_handler_decl(handle_shutdown,arg) { MSG msg; SHUTDOWN_THD; @@ -1718,7 +1753,7 @@ int __stdcall handle_kill(ulong ctrl_type) #endif #ifdef OS2 -pthread_handler_decl(handle_shutdown,arg) +extern "C" pthread_handler_decl(handle_shutdown,arg) { SHUTDOWN_THD; my_thread_init(); @@ -1902,8 +1937,6 @@ int main(int argc, char **argv) if (!ssl_acceptor_fd) opt_use_ssl = 0; } - if (des_key_file) - load_des_key_file(des_key_file); #endif /* HAVE_OPENSSL */ #ifdef HAVE_LIBWRAP @@ -1976,6 +2009,10 @@ int main(int argc, char **argv) reset_floating_point_exceptions(); init_thr_lock(); init_slave_list(); +#ifdef HAVE_OPENSSL + if (des_key_file) + load_des_key_file(des_key_file); +#endif /* HAVE_OPENSSL */ /* Setup log files */ if (opt_log) @@ -2002,6 +2039,8 @@ int main(int argc, char **argv) if (ha_init()) { sql_print_error("Can't init databases"); + if (unix_sock != INVALID_SOCKET) + unlink(mysql_unix_port); exit(1); } ha_key_cache(); @@ -2037,10 +2076,12 @@ int main(int argc, char **argv) pthread_key_create(&THR_MALLOC,NULL)) { sql_print_error("Can't create thread-keys"); + if (unix_sock != INVALID_SOCKET) + unlink(mysql_unix_port); exit(1); } start_signal_handler(); // Creates pidfile - if (acl_init(opt_noacl)) + if (acl_init((THD*) 0, opt_noacl)) { abort_loop=1; select_thread_in_use=0; @@ -2049,10 +2090,12 @@ int main(int argc, char **argv) if (!opt_bootstrap) (void) my_delete(pidfile_name,MYF(MY_WME)); // Not needed anymore #endif + if (unix_sock != INVALID_SOCKET) + unlink(mysql_unix_port); exit(1); } if (!opt_noacl) - (void) grant_init(); + (void) grant_init((THD*) 0); init_max_user_conn(); init_update_queries(); @@ -2521,7 +2564,7 @@ inline void kill_broken_server() /* Handle new connections and spawn new process to handle them */ -pthread_handler_decl(handle_connections_sockets,arg __attribute__((unused))) +extern "C" pthread_handler_decl(handle_connections_sockets,arg __attribute__((unused))) { my_socket sock,new_sock; uint error_count=0; @@ -2557,7 +2600,7 @@ pthread_handler_decl(handle_connections_sockets,arg __attribute__((unused))) while (!abort_loop) { readFDs=clientFDs; -#ifdef HPUX +#ifdef HPUX10 if (select(max_used_connection,(int*) &readFDs,0,0,0) < 0) continue; #else @@ -2571,7 +2614,7 @@ pthread_handler_decl(handle_connections_sockets,arg __attribute__((unused))) MAYBE_BROKEN_SYSCALL continue; } -#endif /* HPUX */ +#endif /* HPUX10 */ if (abort_loop) { MAYBE_BROKEN_SYSCALL; @@ -2728,7 +2771,7 @@ pthread_handler_decl(handle_connections_sockets,arg __attribute__((unused))) #ifdef __NT__ -pthread_handler_decl(handle_connections_namedpipes,arg) +extern "C" pthread_handler_decl(handle_connections_namedpipes,arg) { HANDLE hConnectedPipe; BOOL fConnected; @@ -3053,8 +3096,9 @@ enum options { OPT_MASTER_PASSWORD, OPT_MASTER_PORT, OPT_MASTER_INFO_FILE, OPT_MASTER_CONNECT_RETRY, OPT_MASTER_RETRY_COUNT, - OPT_MASTER_SSL, OPT_MASTER_SSL_KEY, - OPT_MASTER_SSL_CERT, + OPT_MASTER_SSL, OPT_MASTER_SSL_KEY, + OPT_MASTER_SSL_CERT, OPT_MASTER_SSL_CAPATH, + OPT_MASTER_SSL_CIPHER, OPT_SQL_BIN_UPDATE_SAME, OPT_REPLICATE_DO_DB, OPT_REPLICATE_IGNORE_DB, OPT_LOG_SLAVE_UPDATES, OPT_BINLOG_DO_DB, OPT_BINLOG_IGNORE_DB, @@ -3371,6 +3415,14 @@ struct my_option my_long_options[] = "Master SSL certificate file name. Only applies if you have enabled master-ssl.", (gptr*) &master_ssl_cert, (gptr*) &master_ssl_cert, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, + {"master-ssl-capath", OPT_MASTER_SSL_CAPATH, + "Master SSL CA path. Only applies if you have enabled master-ssl.", + (gptr*) &master_ssl_capath, (gptr*) &master_ssl_capath, 0, GET_STR, OPT_ARG, + 0, 0, 0, 0, 0, 0}, + {"master-ssl-cipher", OPT_MASTER_SSL_CIPHER, + "Master SSL cipher. Only applies if you have enabled master-ssl.", + (gptr*) &master_ssl_cipher, (gptr*) &master_ssl_capath, 0, GET_STR, OPT_ARG, + 0, 0, 0, 0, 0, 0}, {"myisam-recover", OPT_MYISAM_RECOVER, "Syntax: myisam-recover[=option[,option...]], where option can be DEFAULT, BACKUP or FORCE.", (gptr*) &myisam_recover_options_str, (gptr*) &myisam_recover_options_str, 0, @@ -3460,7 +3512,7 @@ struct my_option my_long_options[] = (gptr*) &report_port, (gptr*) &report_port, 0, GET_UINT, REQUIRED_ARG, MYSQL_PORT, 0, 0, 0, 0, 0}, {"rpl-recovery-rank", OPT_RPL_RECOVERY_RANK, "Undocumented", - (gptr*) &rpl_recovery_rank, (gptr*) &rpl_recovery_rank, 0, GET_UINT, + (gptr*) &rpl_recovery_rank, (gptr*) &rpl_recovery_rank, 0, GET_ULONG, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"relay-log", OPT_RELAY_LOG, "Undocumented", (gptr*) &opt_relay_logname, (gptr*) &opt_relay_logname, 0, @@ -3473,8 +3525,7 @@ struct my_option my_long_options[] = #ifndef TO_BE_DELETED {"safe-show-database", OPT_SAFE_SHOW_DB, "Deprecated option; One should use GRANT SHOW DATABASES instead...", - (gptr*) &opt_safe_show_db, (gptr*) &opt_safe_show_db, 0, GET_BOOL, NO_ARG, - 0, 0, 0, 0, 0, 0}, + 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif {"safe-user-create", OPT_SAFE_USER_CREATE, "Don't allow new user creation by the user who has no write privileges to the mysql.user table", @@ -4029,6 +4080,7 @@ struct show_var_st status_vars[]= { {"Qcache_queries_in_cache", (char*) &query_cache.queries_in_cache, SHOW_LONG_CONST}, {"Qcache_inserts", (char*) &query_cache.inserts, SHOW_LONG}, {"Qcache_hits", (char*) &query_cache.hits, SHOW_LONG}, + {"Qcache_lowmem_prunes", (char*) &query_cache.lowmem_prunes, SHOW_LONG}, {"Qcache_not_cached", (char*) &query_cache.refused, SHOW_LONG}, {"Qcache_free_memory", (char*) &query_cache.free_memory, SHOW_LONG_CONST}, @@ -4149,7 +4201,7 @@ static void set_options(void) /* Set default values for some variables */ global_system_variables.table_type=DB_TYPE_MYISAM; - global_system_variables.tx_isolation=ISO_READ_COMMITTED; + global_system_variables.tx_isolation=ISO_REPEATABLE_READ; global_system_variables.select_limit= (ulonglong) HA_POS_ERROR; max_system_variables.select_limit= (ulong) HA_POS_ERROR; global_system_variables.max_join_size= (ulonglong) HA_POS_ERROR; @@ -4176,7 +4228,7 @@ static void set_options(void) } -static my_bool +extern "C" my_bool get_one_option(int optid, const struct my_option *opt __attribute__((unused)), char *argument) { @@ -4621,7 +4673,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), } global_system_variables.tx_isolation= ((opt_sql_mode & MODE_SERIALIZABLE) ? ISO_SERIALIZABLE : - ISO_READ_COMMITTED); + ISO_REPEATABLE_READ); break; } case OPT_MASTER_PASSWORD: @@ -4719,9 +4771,17 @@ fn_format_relative_to_data_home(my_string to, const char *name, static void fix_paths(void) { - char buff[FN_REFLEN]; - (void) fn_format(mysql_home,mysql_home,"","",16); // Remove symlinks + char buff[FN_REFLEN],*pos; convert_dirname(mysql_home,mysql_home,NullS); + /* Resolve symlinks to allow 'mysql_home' to be a relative symlink */ + my_realpath(mysql_home,mysql_home,MYF(0)); + /* Ensure that mysql_home ends in FN_LIBCHAR */ + pos=strend(mysql_home); + if (pos[-1] != FN_LIBCHAR) + { + pos[0]= FN_LIBCHAR; + pos[1]= 0; + } convert_dirname(mysql_real_data_home,mysql_real_data_home,NullS); convert_dirname(language,language,NullS); (void) my_load_path(mysql_home,mysql_home,""); // Resolve current dir diff --git a/sql/nt_servc.cc b/sql/nt_servc.cc index 2d0eae125d6..b917c91ce15 100644 --- a/sql/nt_servc.cc +++ b/sql/nt_servc.cc @@ -568,31 +568,3 @@ BOOL NTService::is_super_user() FreeSid(psidAdministrators); return ret_value; } -/* ------------------------------------------------------------------------ - -------------------------------------------------------------------------- */ -BOOL NTService::IsService(LPCSTR ServiceName) -{ - BOOL ret_value=FALSE; - SC_HANDLE service, scm; - - if (scm = OpenSCManager(0, 0,SC_MANAGER_ENUMERATE_SERVICE)) - { - if ((service = OpenService(scm,ServiceName, SERVICE_ALL_ACCESS ))) - { - ret_value=TRUE; - CloseServiceHandle(service); - } - CloseServiceHandle(scm); - } - return ret_value; -} -/* ------------------------------------------------------------------------ - -------------------------------------------------------------------------- */ -BOOL NTService::got_service_option(char **argv, char *service_option) -{ - char *option; - for (option= argv[1]; *option; option++) - if (!strcmp(option, service_option)) - return TRUE; - return FALSE; -} diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 13c2f6333b1..b6f81ab07eb 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -2463,9 +2463,9 @@ int QUICK_SELECT::get_next() if (range->flag & NO_MIN_RANGE) // Read first record { - int error; - if ((error=file->index_first(record))) - DBUG_RETURN(error); // Empty table + int local_error; + if ((local_error=file->index_first(record))) + DBUG_RETURN(local_error); // Empty table if (cmp_next(range) == 0) DBUG_RETURN(0); range=0; // No matching records; go to next range @@ -2499,13 +2499,13 @@ int QUICK_SELECT::get_next() /* compare if found key is over max-value */ /* Returns 0 if key <= range->max_key */ -int QUICK_SELECT::cmp_next(QUICK_RANGE *range) +int QUICK_SELECT::cmp_next(QUICK_RANGE *range_arg) { - if (range->flag & NO_MAX_RANGE) - return (0); /* key can't be to large */ + if (range_arg->flag & NO_MAX_RANGE) + return 0; /* key can't be to large */ KEY_PART *key_part=key_parts; - for (char *key=range->max_key, *end=key+range->max_length; + for (char *key=range_arg->max_key, *end=key+range_arg->max_length; key < end; key+= key_part++->part_length) { @@ -2526,7 +2526,7 @@ int QUICK_SELECT::cmp_next(QUICK_RANGE *range) if (cmp > 0) return 1; } - return (range->flag & NEAR_MAX) ? 1 : 0; // Exact match + return (range_arg->flag & NEAR_MAX) ? 1 : 0; // Exact match } @@ -2610,9 +2610,9 @@ int QUICK_SELECT_DESC::get_next() if (range->flag & NO_MAX_RANGE) // Read last record { - int error; - if ((error=file->index_last(record))) - DBUG_RETURN(error); // Empty table + int local_error; + if ((local_error=file->index_last(record))) + DBUG_RETURN(local_error); // Empty table if (cmp_prev(range) == 0) DBUG_RETURN(0); range=0; // No matching records; go to next range @@ -2666,16 +2666,18 @@ int QUICK_SELECT_DESC::get_next() } } + /* - * Returns 0 if found key is inside range (found key >= range->min_key). - */ -int QUICK_SELECT_DESC::cmp_prev(QUICK_RANGE *range) + Returns 0 if found key is inside range (found key >= range->min_key). +*/ + +int QUICK_SELECT_DESC::cmp_prev(QUICK_RANGE *range_arg) { - if (range->flag & NO_MIN_RANGE) - return (0); /* key can't be to small */ + if (range_arg->flag & NO_MIN_RANGE) + return 0; /* key can't be to small */ KEY_PART *key_part = key_parts; - for (char *key = range->min_key, *end = key + range->min_length; + for (char *key = range_arg->min_key, *end = key + range_arg->min_length; key < end; key += key_part++->part_length) { @@ -2699,42 +2701,45 @@ int QUICK_SELECT_DESC::cmp_prev(QUICK_RANGE *range) if (cmp < 0) return 1; } - return (range->flag & NEAR_MIN) ? 1 : 0; // Exact match + return (range_arg->flag & NEAR_MIN) ? 1 : 0; // Exact match } + /* * True if this range will require using HA_READ_AFTER_KEY See comment in get_next() about this */ -bool QUICK_SELECT_DESC::range_reads_after_key(QUICK_RANGE *range) +bool QUICK_SELECT_DESC::range_reads_after_key(QUICK_RANGE *range_arg) { - return ((range->flag & (NO_MAX_RANGE | NEAR_MAX)) || - !(range->flag & EQ_RANGE) || - head->key_info[index].key_length != range->max_length) ? 1 : 0; + return ((range_arg->flag & (NO_MAX_RANGE | NEAR_MAX)) || + !(range_arg->flag & EQ_RANGE) || + head->key_info[index].key_length != range_arg->max_length) ? 1 : 0; } + /* True if we are reading over a key that may have a NULL value */ -bool QUICK_SELECT_DESC::test_if_null_range(QUICK_RANGE *range, +bool QUICK_SELECT_DESC::test_if_null_range(QUICK_RANGE *range_arg, uint used_key_parts) { uint offset,end; KEY_PART *key_part = key_parts, *key_part_end= key_part+used_key_parts; - for (offset= 0, end = min(range->min_length, range->max_length) ; + for (offset= 0, end = min(range_arg->min_length, range_arg->max_length) ; offset < end && key_part != key_part_end ; offset += key_part++->part_length) { uint null_length=test(key_part->null_bit); - if (!memcmp((char*) range->min_key+offset, (char*) range->max_key+offset, + if (!memcmp((char*) range_arg->min_key+offset, + (char*) range_arg->max_key+offset, key_part->part_length + null_length)) { offset+=null_length; continue; } - if (null_length && range->min_key[offset]) + if (null_length && range_arg->min_key[offset]) return 1; // min_key is null and max_key isn't // Range doesn't cover NULL. This is ok if there is no more null parts break; @@ -2747,7 +2752,7 @@ bool QUICK_SELECT_DESC::test_if_null_range(QUICK_RANGE *range, */ if (key_part != key_part_end && key_part->null_bit) { - if (offset >= range->min_length || range->min_key[offset]) + if (offset >= range_arg->min_length || range_arg->min_key[offset]) return 1; // Could be null key_part++; } diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc index 38365dbb546..1477d46e756 100644 --- a/sql/opt_sum.cc +++ b/sql/opt_sum.cc @@ -37,6 +37,19 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds) bool recalc_const_item=0; table_map removed_tables=0; Item *item; + COND *org_conds= conds; + + /* Add all ON conditions to WHERE condition */ + for (TABLE_LIST *tl=tables; tl ; tl= tl->next) + { + if (tl->on_expr) + conds= and_expressions(conds, tl->on_expr, &org_conds); + } + + /* + Iterate through item is select part and replace COUNT(), MIN() and MAX() + with constants (if possible) + */ while ((item= it++)) { diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc index 4295a16c547..785a253b1ac 100644 --- a/sql/repl_failsafe.cc +++ b/sql/repl_failsafe.cc @@ -188,14 +188,15 @@ err2: return 1; } -static uint32* slave_list_key(SLAVE_INFO* si, uint* len, - my_bool not_used __attribute__((unused))) +extern "C" uint32 +*slave_list_key(SLAVE_INFO* si, uint* len, + my_bool not_used __attribute__((unused))) { *len = 4; return &si->server_id; } -static void slave_info_free(void *s) +extern "C" void slave_info_free(void *s) { my_free((gptr) s, MYF(MY_WME)); } @@ -203,7 +204,7 @@ static void slave_info_free(void *s) void init_slave_list() { hash_init(&slave_list, system_charset_info, SLAVE_LIST_CHUNK, 0, 0, - (hash_get_key) slave_list_key, slave_info_free, 0); + (hash_get_key) slave_list_key, (hash_free_key) slave_info_free, 0); pthread_mutex_init(&LOCK_slave_list, MY_MUTEX_INIT_FAST); } diff --git a/sql/set_var.cc b/sql/set_var.cc index 141320cc3f6..599c4af06cc 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -202,8 +202,6 @@ sys_var_thd_enum sys_query_cache_type("query_cache_type", &SV::query_cache_type, &query_cache_type_typelib); #endif /* HAVE_QUERY_CACHE */ -sys_var_bool_ptr sys_safe_show_db("safe_show_database", - &opt_safe_show_db); sys_var_long_ptr sys_server_id("server_id",&server_id); sys_var_bool_ptr sys_slave_compressed_protocol("slave_compressed_protocol", &opt_slave_compressed_protocol); @@ -299,6 +297,8 @@ static sys_var_readonly sys_warning_count("warning_count", /* alias for last_insert_id() to be compatible with Sybase */ static sys_var_slave_skip_counter sys_slave_skip_counter("sql_slave_skip_counter"); +static sys_var_rand_seed1 sys_rand_seed1("rand_seed1"); +static sys_var_rand_seed2 sys_rand_seed2("rand_seed2"); /* @@ -370,10 +370,11 @@ sys_var *sys_variables[]= &sys_query_cache_type, #endif /* HAVE_QUERY_CACHE */ &sys_quote_show_create, + &sys_rand_seed1, + &sys_rand_seed2, &sys_read_buff_size, &sys_read_rnd_buff_size, &sys_rpl_recovery_rank, - &sys_safe_show_db, &sys_safe_updates, &sys_select_limit, &sys_server_id, @@ -448,7 +449,7 @@ struct show_var_st init_vars[]= { {"innodb_file_io_threads", (char*) &innobase_file_io_threads, SHOW_LONG }, {"innodb_force_recovery", (char*) &innobase_force_recovery, SHOW_LONG }, {"innodb_thread_concurrency", (char*) &innobase_thread_concurrency, SHOW_LONG }, - {"innodb_flush_log_at_trx_commit", (char*) &innobase_flush_log_at_trx_commit, SHOW_LONG}, + {"innodb_flush_log_at_trx_commit", (char*) &innobase_flush_log_at_trx_commit, SHOW_INT}, {"innodb_fast_shutdown", (char*) &innobase_fast_shutdown, SHOW_MY_BOOL}, {"innodb_flush_method", (char*) &innobase_unix_file_flush_method, SHOW_CHAR_PTR}, {"innodb_lock_wait_timeout", (char*) &innobase_lock_wait_timeout, SHOW_LONG }, @@ -519,7 +520,6 @@ struct show_var_st init_vars[]= { {sys_query_cache_size.name, (char*) &sys_query_cache_size, SHOW_SYS}, {sys_query_cache_type.name, (char*) &sys_query_cache_type, SHOW_SYS}, #endif /* HAVE_QUERY_CACHE */ - {sys_safe_show_db.name, (char*) &sys_safe_show_db, SHOW_SYS}, #ifdef HAVE_SMEM {"shared_memory", (char*) &opt_enable_shared_memory, SHOW_MY_BOOL}, {"shared_memory_base_name", (char*) &shared_memory_base_name, SHOW_CHAR_PTR}, @@ -530,7 +530,9 @@ struct show_var_st init_vars[]= { {"skip_networking", (char*) &opt_disable_networking, SHOW_BOOL}, {"skip_show_database", (char*) &opt_skip_show_db, SHOW_BOOL}, {sys_slow_launch_time.name, (char*) &sys_slow_launch_time, SHOW_SYS}, +#ifdef HAVE_SYS_UN_H {"socket", (char*) &mysql_unix_port, SHOW_CHAR_PTR}, +#endif {sys_sort_buffer.name, (char*) &sys_sort_buffer, SHOW_SYS}, {"sql_mode", (char*) &opt_sql_mode, SHOW_LONG}, {"table_cache", (char*) &table_cache_size, SHOW_LONG}, @@ -1073,6 +1075,19 @@ bool sys_var_slave_skip_counter::update(THD *thd, set_var *var) } +bool sys_var_rand_seed1::update(THD *thd, set_var *var) +{ + thd->rand.seed1= (ulong) var->value->val_int(); + return 0; +} + +bool sys_var_rand_seed2::update(THD *thd, set_var *var) +{ + thd->rand.seed2= (ulong) var->value->val_int(); + return 0; +} + + /* Functions to update thd->options bits */ diff --git a/sql/set_var.h b/sql/set_var.h index 62fa977eb06..de1e27e0da8 100644 --- a/sql/set_var.h +++ b/sql/set_var.h @@ -337,6 +337,23 @@ public: }; +class sys_var_rand_seed1 :public sys_var +{ +public: + sys_var_rand_seed1(const char *name_arg) :sys_var(name_arg) {} + bool update(THD *thd, set_var *var); + bool check_type(enum_var_type type) { return type == OPT_GLOBAL; } +}; + +class sys_var_rand_seed2 :public sys_var +{ +public: + sys_var_rand_seed2(const char *name_arg) :sys_var(name_arg) {} + bool update(THD *thd, set_var *var); + bool check_type(enum_var_type type) { return type == OPT_GLOBAL; } +}; + + class sys_var_thd_conv_charset :public sys_var_thd { public: diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt index 0eef4ae9cad..1b1f90abfb3 100644 --- a/sql/share/czech/errmsg.txt +++ b/sql/share/czech/errmsg.txt @@ -188,7 +188,7 @@ "Update tabulky bez WHERE s kl-Bíèem není v módu bezpeèných update dovoleno", "Kl-Bíè '%-.64s' v tabulce '%-.64s' neexistuje", "Nemohu otev-Bøít tabulku", -"Handler tabulky nepodporuje check/repair", +"Handler tabulky nepodporuje %s", "Proveden-Bí tohoto pøíkazu není v transakci dovoleno", "Chyba %d p-Bøi COMMIT", "Chyba %d p-Bøi ROLLBACK", diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt index c2e0ddb064f..65eb190b48b 100644 --- a/sql/share/danish/errmsg.txt +++ b/sql/share/danish/errmsg.txt @@ -182,7 +182,7 @@ "Du bruger sikker opdaterings modus ('safe update mode') og du forsøgte at opdatere en tabel uden en WHERE klausul, der gør brug af et KEY felt", "Nøglen '%-.64s' eksisterer ikke i tabellen '%-.64s'", "Kan ikke åbne tabellen", -"Denne tabeltype understøtter ikke CHECK/REPAIR", +"Denne tabeltype understøtter ikke %s", "Du må ikke bruge denne kommando i en transaktion", "Modtog fejl %d mens kommandoen COMMIT blev udført", "Modtog fejl %d mens kommandoen ROLLBACK blev udført", diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt index 7a3f7b787b2..965221dd83f 100644 --- a/sql/share/dutch/errmsg.txt +++ b/sql/share/dutch/errmsg.txt @@ -190,7 +190,7 @@ "U gebruikt 'safe update mode' en u probeerde een tabel te updaten zonder een WHERE met een KEY kolom", "Zoeksleutel '%-.64s' bestaat niet in tabel '%-.64s'", "Kan tabel niet openen", -"De 'handler' voor de tabel ondersteund geen check/repair", +"De 'handler' voor de tabel ondersteund geen %s", "Het is u niet toegestaan dit commando uit te voeren binnen een transactie", "Kreeg fout %d tijdens COMMIT", "Kreeg fout %d tijdens ROLLBACK", diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt index e746b461a6d..7472fe14365 100644 --- a/sql/share/english/errmsg.txt +++ b/sql/share/english/errmsg.txt @@ -179,7 +179,7 @@ "You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column", "Key '%-.64s' doesn't exist in table '%-.64s'", "Can't open table", -"The handler for the table doesn't support check/repair", +"The handler for the table doesn't support %s", "You are not allowed to execute this command in a transaction", "Got error %d during COMMIT", "Got error %d during ROLLBACK", diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt index ee20b9890c4..3f2745a8809 100644 --- a/sql/share/estonian/errmsg.txt +++ b/sql/share/estonian/errmsg.txt @@ -184,7 +184,7 @@ "Katse muuta tabelit turvalises rezhiimis ilma WHERE klauslita", "Võti '%-.64s' ei eksisteeri tabelis '%-.64s'", "Ei suuda avada tabelit", -"Antud tabelitüüp ei toeta CHECK/REPAIR käske", +"Antud tabelitüüp ei toeta %s käske", "Seda käsku ei saa kasutada transaktsiooni sees", "Viga %d käsu COMMIT täitmisel", "Viga %d käsu ROLLBACK täitmisel", diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt index 89b82b3851b..f1df0c0c2f2 100644 --- a/sql/share/french/errmsg.txt +++ b/sql/share/french/errmsg.txt @@ -179,7 +179,7 @@ "Vous êtes en mode 'safe update' et vous essayez de faire un UPDATE sans clause WHERE utilisant un index", "L'index '%-.64s' n'existe pas sur la table '%-.64s'", "Impossible d'ouvrir la table", -"Ce type de table ne supporte pas les check/repair", +"Ce type de table ne supporte pas les %s", "Vous n'êtes pas autorisé à exécute cette commande dans une transaction", "Erreur %d lors du COMMIT", "Erreur %d lors du ROLLBACK", diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt index 3b354ee3298..bd51de5a257 100644 --- a/sql/share/german/errmsg.txt +++ b/sql/share/german/errmsg.txt @@ -182,7 +182,7 @@ "Unter Verwendung des Sicheren Updatemodes wurde versucht eine Tabelle zu updaten ohne eine KEY-Spalte in der WHERE-Klausel", "Schlüssel '%-.64s' existiert nicht in der Tabelle '%-.64s'", "Kann Tabelle nicht öffnen", -"Der Tabellen-Handler für diese Tabelle unterstützt kein check/repair", +"Der Tabellen-Handler für diese Tabelle unterstützt kein %s", "Keine Berechtigung dieses Kommando in einer Transaktion auszuführen", "Fehler %d wärend COMMIT", "Fehler %d wärend ROLLBACK", diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt index 38ce4217888..915b4e9f64b 100644 --- a/sql/share/greek/errmsg.txt +++ b/sql/share/greek/errmsg.txt @@ -179,7 +179,7 @@ "You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column", "Key '%-.64s' doesn't exist in table '%-.64s'", "Can't open table", -"The handler for the table doesn't support check/repair", +"The handler for the table doesn't support %s", "You are not allowed to execute this command in a transaction", "Got error %d during COMMIT", "Got error %d during ROLLBACK", diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt index f2fd63765d9..aa8567dac87 100644 --- a/sql/share/hungarian/errmsg.txt +++ b/sql/share/hungarian/errmsg.txt @@ -181,7 +181,7 @@ "On a biztonsagos update modot hasznalja, es WHERE that uses a KEY column", "A '%-.64s' kulcs nem letezik a '%-.64s' tablaban", "Nem tudom megnyitni a tablat", -"A tabla kezeloje (handler) nem tamogatja az ellenorzest/helyreallitast", +"A tabla kezeloje (handler) nem tamogatja az %s", "Az On szamara nem engedelyezett a parancs vegrehajtasa a tranzakcioban", "%d hiba a COMMIT vegrehajtasa soran", "%d hiba a ROLLBACK vegrehajtasa soran", diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt index 2b24a123e25..20430757590 100644 --- a/sql/share/italian/errmsg.txt +++ b/sql/share/italian/errmsg.txt @@ -179,7 +179,7 @@ "In modalita` 'safe update' si e` cercato di aggiornare una tabella senza clausola WHERE su una chiave", "La chiave '%-.64s' non esiste nella tabella '%-.64s'", "Impossibile aprire la tabella", -"Il gestore per la tabella non supporta il controllo/riparazione", +"Il gestore per la tabella non supporta il %s", "Non puoi eseguire questo comando in una transazione", "Rilevato l'errore %d durante il COMMIT", "Rilevato l'errore %d durante il ROLLBACK", diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt index 7b428cae703..2f3c61c1fe1 100644 --- a/sql/share/japanese/errmsg.txt +++ b/sql/share/japanese/errmsg.txt @@ -181,7 +181,7 @@ "You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column", "Key '%-.64s' doesn't exist in table '%-.64s'", "Can't open table", -"The handler for the table doesn't support check/repair", +"The handler for the table doesn't support %s", "You are not allowed to execute this command in a transaction", "Got error %d during COMMIT", "Got error %d during ROLLBACK", diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt index 8fbc33bf690..277e53895c3 100644 --- a/sql/share/korean/errmsg.txt +++ b/sql/share/korean/errmsg.txt @@ -179,7 +179,7 @@ "You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column", "Key '%-.64s' doesn't exist in table '%-.64s'", "Can't open table", -"The handler for the table doesn't support check/repair", +"The handler for the table doesn't support %s", "You are not allowed to execute this command in a transaction", "Got error %d during COMMIT", "Got error %d during ROLLBACK", diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt index 1c3cf11e10c..4c3a12d6557 100644 --- a/sql/share/norwegian-ny/errmsg.txt +++ b/sql/share/norwegian-ny/errmsg.txt @@ -181,7 +181,7 @@ "You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column", "Key '%-.64s' doesn't exist in table '%-.64s'", "Can't open table", -"The handler for the table doesn't support check/repair", +"The handler for the table doesn't support %s", "You are not allowed to execute this command in a transaction", "Got error %d during COMMIT", "Got error %d during ROLLBACK", diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt index 1db0068685c..46bf84c409e 100644 --- a/sql/share/norwegian/errmsg.txt +++ b/sql/share/norwegian/errmsg.txt @@ -181,7 +181,7 @@ "You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column", "Key '%-.64s' doesn't exist in table '%-.64s'", "Can't open table", -"The handler for the table doesn't support check/repair", +"The handler for the table doesn't support %s", "You are not allowed to execute this command in a transaction", "Got error %d during COMMIT", "Got error %d during ROLLBACK", diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt index bda25b01065..e4d9832725d 100644 --- a/sql/share/polish/errmsg.txt +++ b/sql/share/polish/errmsg.txt @@ -183,7 +183,7 @@ "You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column", "Key '%-.64s' doesn't exist in table '%-.64s'", "Can't open table", -"The handler for the table doesn't support check/repair", +"The handler for the table doesn't support %s", "You are not allowed to execute this command in a transaction", "Got error %d during COMMIT", "Got error %d during ROLLBACK", diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt index 947f935fd33..1c5adc96560 100644 --- a/sql/share/portuguese/errmsg.txt +++ b/sql/share/portuguese/errmsg.txt @@ -179,7 +179,7 @@ "Você está usando modo de atualização seguro e tentou atualizar uma tabela sem uma cláusula WHERE que use uma coluna chave", "Chave '%-.64s' não existe na tabela '%-.64s'", "Não pode abrir a tabela", -"O manipulador de tabela não suporta checagem/reparação (check/repair)", +"O manipulador de tabela não suporta %s", "Não lhe é permitido executar este comando em uma transação", "Obteve erro %d durante COMMIT", "Obteve erro %d durante ROLLBACK", diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt index 71baf4ca098..313af2e5f14 100644 --- a/sql/share/romanian/errmsg.txt +++ b/sql/share/romanian/errmsg.txt @@ -183,7 +183,7 @@ "You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column", "Key '%-.64s' doesn't exist in table '%-.64s'", "Can't open table", -"The handler for the table doesn't support check/repair", +"The handler for the table doesn't support %s", "You are not allowed to execute this command in a transaction", "Got error %d during COMMIT", "Got error %d during ROLLBACK", diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt index 03ea8b74ce5..3b636aacae7 100644 --- a/sql/share/russian/errmsg.txt +++ b/sql/share/russian/errmsg.txt @@ -182,7 +182,7 @@ "MySQL ÒÁÂÏÔÁÅÔ × ÒÅÖÉÍÅ ÚÁÝÉÔÙ ÏÔ ÄÕÒÁËÏ× (safe_mode) - ÎÅ ÍÏÇÕ UPDATE ÂÅÚ WHERE Ó ËÁËÉÍ-ÎÅÂÕÄØ KEY", "éÎÄÅËÓ '%-.64s' ÎÅ ÎÁÊÄÅÎ × ÔÁÂÌÉÃÅ '%-.64s'", "îÅ ÍÏÇÕ ÏÔËÒÙÔØ ÔÁÂÌÉÃÕ", -"äÁÎÎÙÊ ÔÉÐ ÔÁÂÌÉà ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔ check/repair", +"äÁÎÎÙÊ ÔÉÐ ÔÁÂÌÉà ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔ ËÏÍÁÎÄÕ %s", "üÔÁ ËÏÍÁÎÄÁ ×ÎÕÔÒÉ ÔÒÁÎÚÁËÃÉÉ ÚÁÐÒÅÝÅÎÁ", "ïÛÉÂËÁ %d ×Ï ×ÒÅÍÑ COMMIT", "ïÛÉÂËÁ %d ×Ï ×ÒÅÍÑ ROLLBACK", diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt index 36f5e421561..9f610a84bd9 100644 --- a/sql/share/slovak/errmsg.txt +++ b/sql/share/slovak/errmsg.txt @@ -187,7 +187,7 @@ "You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column", "Key '%-.64s' doesn't exist in table '%-.64s'", "Can't open table", -"The handler for the table doesn't support check/repair", +"The handler for the table doesn't support %s", "You are not allowed to execute this command in a transaction", "Got error %d during COMMIT", "Got error %d during ROLLBACK", diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt index 5a087d6fa17..ab4e3e93a25 100644 --- a/sql/share/spanish/errmsg.txt +++ b/sql/share/spanish/errmsg.txt @@ -180,7 +180,7 @@ "Tu estás usando modo de actualización segura y tentado actualizar una tabla sin un WHERE que usa una KEY columna", "Clave '%-.64s' no existe en la tabla '%-.64s'", "No puedo abrir tabla", -"El manipulador de la tabla no permite soporte para check/repair", +"El manipulador de la tabla no permite soporte para %s", "No tienes el permiso para ejecutar este comando en una transición", "Obtenido error %d durante COMMIT", "Obtenido error %d durante ROLLBACK", diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt index 42f2e72ec45..3d91522bf0f 100644 --- a/sql/share/swedish/errmsg.txt +++ b/sql/share/swedish/errmsg.txt @@ -179,7 +179,7 @@ "Du använder 'säker uppdaterings mod' och försökte uppdatera en table utan en WHERE sats som använder sig av en nyckel", "Nyckel '%-.64s' finns inte in tabell '%-.64s'", "Kan inte öppna tabellen", -"Tabellhanteraren för denna tabell kan inte göra check/repair", +"Tabellhanteraren för denna tabell kan inte göra %s", "Du får inte utföra detta kommando i en transaktion", "Fick fel %d vid COMMIT", "Fick fel %d vid ROLLBACK", diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt index f41041de2bb..d16a8e678d1 100644 --- a/sql/share/ukrainian/errmsg.txt +++ b/sql/share/ukrainian/errmsg.txt @@ -184,7 +184,7 @@ "÷É Õ ÒÅÖÉͦ ÂÅÚÐÅÞÎÏÇÏ ÏÎÏ×ÌÅÎÎÑ ÔÁ ÎÁÍÁÇÁ¤ÔÅÓØ ÏÎÏ×ÉÔÉ ÔÁÂÌÉÃÀ ÂÅÚ ÏÐÅÒÁÔÏÒÁ WHERE, ÝÏ ×ÉËÏÒÉÓÔÏ×Õ¤ KEY ÓÔÏ×ÂÅÃØ", "ëÌÀÞ '%-.64s' ÎÅ ¦ÓÎÕ¤ × ÔÁÂÌÉæ '%-.64s'", "îÅ ÍÏÖÕ ×¦ÄËÒÉÔÉ ÔÁÂÌÉÃÀ", -"÷ËÁÚ¦×ÎÉË ÔÁÂÌÉæ ΊЦÄÔÒÉÍÕÅ ÐÅÒÅצÒËÕ/צÄÎÏ×ÌÅÎÎÑ", +"÷ËÁÚ¦×ÎÉË ÔÁÂÌÉæ ΊЦÄÔÒÉÍÕÅ %s", "÷ÁÍ ÎÅ ÄÏÚ×ÏÌÅÎÏ ×ÉËÏÎÕ×ÁÔÉ ÃÀ ËÏÍÁÎÄÕ × ÔÒÁÎÚÁËæ§", "ïÔÒÉÍÁÎÏ ÐÏÍÉÌËÕ %d Ð¦Ä ÞÁÓ COMMIT", "ïÔÒÉÍÁÎÏ ÐÏÍÉÌËÕ %d Ð¦Ä ÞÁÓ ROLLBACK", diff --git a/sql/slave.cc b/sql/slave.cc index a9c1b15a982..f8acc592afa 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -608,7 +608,7 @@ void init_table_rule_hash(HASH* h, bool* h_inited) { hash_init(h, system_charset_info,TABLE_RULE_HASH_SIZE,0,0, (hash_get_key) get_table_key, - (void (*)(void*)) free_table_ent, 0); + (hash_free_key) free_table_ent, 0); *h_inited = 1; } @@ -1637,7 +1637,7 @@ bool flush_master_info(MASTER_INFO* mi) DBUG_PRINT("enter",("master_pos: %ld", (long) mi->master_log_pos)); my_b_seek(file, 0L); - my_b_printf(file, "%s\n%s\n%s\n%s\n%s\n%d\n%d\n%d\n", + my_b_printf(file, "%s\n%s\n%s\n%s\n%s\n%d\n%d\n", mi->master_log_name, llstr(mi->master_log_pos, lbuf), mi->host, mi->user, mi->password, mi->port, mi->connect_retry @@ -1945,7 +1945,7 @@ int check_expected_error(THD* thd, RELAY_LOG_INFO* rli, int expected_error) "Slave: query '%s' partially completed on the master \ and was aborted. There is a chance that your master is inconsistent at this \ point. If you are sure that your master is ok, run this query manually on the\ - slave and then restart the slave with SET SQL_SLAVE_SKIP_COUNTER=1;\ + slave and then restart the slave with SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1;\ SLAVE START;", thd->query); rli->last_slave_errno = expected_error; sql_print_error("%s",rli->last_slave_error); @@ -2025,11 +2025,10 @@ This may also be a network problem, or just a bug in the master or slave code.\ } /***************************************************************************** - Slave I/O Thread entry point - *****************************************************************************/ -pthread_handler_decl(handle_slave_io,arg) + +extern "C" pthread_handler_decl(handle_slave_io,arg) { THD *thd; // needs to be first for thread_stack MYSQL *mysql; @@ -2298,11 +2297,10 @@ err: } /***************************************************************************** - Slave SQL Thread entry point - *****************************************************************************/ -pthread_handler_decl(handle_slave_sql,arg) + +extern "C" pthread_handler_decl(handle_slave_sql,arg) { THD *thd; /* needs to be first for thread_stack */ char llbuff[22],llbuff1[22]; @@ -2478,7 +2476,7 @@ static int process_io_create_file(MASTER_INFO* mi, Create_file_log_event* cev) in the loop */ { - Append_block_log_event aev(thd,0,0); + Append_block_log_event aev(thd,0,0,0); for (;;) { @@ -2491,7 +2489,7 @@ static int process_io_create_file(MASTER_INFO* mi, Create_file_log_event* cev) if (unlikely(!num_bytes)) /* eof */ { net_write_command(net, 0, "", 0, "", 0);/* 3.23 master wants it */ - Execute_load_log_event xev(thd); + Execute_load_log_event xev(thd,0); xev.log_pos = mi->master_log_pos; if (unlikely(mi->rli.relay_log.append(&xev))) { diff --git a/sql/slave.h b/sql/slave.h index 74c89f9d755..2c750e415bc 100644 --- a/sql/slave.h +++ b/sql/slave.h @@ -436,8 +436,8 @@ int init_relay_log_pos(RELAY_LOG_INFO* rli,const char* log,ulonglong pos, int purge_relay_logs(RELAY_LOG_INFO* rli, THD *thd, bool just_reset, const char** errmsg); -pthread_handler_decl(handle_slave_io,arg); -pthread_handler_decl(handle_slave_sql,arg); +extern "C" pthread_handler_decl(handle_slave_io,arg); +extern "C" pthread_handler_decl(handle_slave_sql,arg); extern bool volatile abort_loop; extern MASTER_INFO main_mi, *active_mi; /* active_mi for multi-master */ extern volatile int active_mi_in_use; diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 5f8cf42c2bf..8ccd7dbde68 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -119,6 +119,7 @@ static bool compare_hostname(const acl_host_and_ip *host, const char *hostname, SYNOPSIS acl_init() + thd Thread handler dont_read_acl_tables Set to 1 if run with --skip-grant RETURN VALUES @@ -127,9 +128,9 @@ static bool compare_hostname(const acl_host_and_ip *host, const char *hostname, */ -my_bool acl_init(bool dont_read_acl_tables) +my_bool acl_init(THD *org_thd, bool dont_read_acl_tables) { - THD *thd, *org_thd; + THD *thd; TABLE_LIST tables[3]; TABLE *table; READ_RECORD read_record_info; @@ -140,14 +141,13 @@ my_bool acl_init(bool dont_read_acl_tables) if (!acl_cache) acl_cache=new hash_filo(ACL_CACHE_SIZE,0,0, (hash_get_key) acl_entry_get_key, - (void (*)(void*)) free); + (hash_free_key) free); if (dont_read_acl_tables) DBUG_RETURN(0); /* purecov: tested */ /* To be able to run this from boot, we allocate a temporary THD */ - org_thd=current_thd; // Save for restore if (!(thd=new THD)) DBUG_RETURN(1); /* purecov: inspected */ thd->store_globals(); @@ -339,6 +339,11 @@ end: delete thd; if (org_thd) org_thd->store_globals(); /* purecov: inspected */ + else + { + /* Remember that we don't have a THD */ + my_pthread_setspecific_ptr(THR_THD, 0); + } DBUG_RETURN(return_val); } @@ -385,7 +390,7 @@ void acl_reload(THD *thd) delete_dynamic(&acl_wild_hosts); hash_free(&acl_check_hosts); - if (acl_init(0)) + if (acl_init(thd, 0)) { // Error. Revert to old list acl_free(); /* purecov: inspected */ acl_hosts=old_acl_hosts; @@ -1089,7 +1094,7 @@ bool change_password(THD *thd, const char *host, const char *user, acl_user->host.hostname ? acl_user->host.hostname : "", new_password)); mysql_update_log.write(thd, buff, query_length); - Query_log_event qinfo(thd, buff, query_length); + Query_log_event qinfo(thd, buff, query_length, 0); mysql_bin_log.write(&qinfo); DBUG_RETURN(0); } @@ -1352,8 +1357,13 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo, strlen(thd->lex.x509_subject), system_charset_info); break; case SSL_TYPE_NOT_SPECIFIED: - case SSL_TYPE_NONE: // Impossible - break; // Nothing to do + break; + case SSL_TYPE_NONE: + table->field[24]->store("",0); + table->field[25]->store("",0); + table->field[26]->store("",0); + table->field[27]->store("",0); + break; } USER_RESOURCES mqh = thd->lex.mqh; @@ -2275,9 +2285,9 @@ void grant_free(void) /* Init grant array if possible */ -my_bool grant_init(void) +my_bool grant_init(THD *org_thd) { - THD *thd, *org_thd; + THD *thd; TABLE_LIST tables[2]; MYSQL_LOCK *lock; my_bool return_val= 1; @@ -2294,7 +2304,6 @@ my_bool grant_init(void) if (!initialized) DBUG_RETURN(0); /* purecov: tested */ - org_thd=current_thd; if (!(thd=new THD)) DBUG_RETURN(1); /* purecov: deadcode */ thd->store_globals(); @@ -2352,13 +2361,18 @@ end: delete thd; if (org_thd) org_thd->store_globals(); + else + { + /* Remember that we don't have a THD */ + my_pthread_setspecific_ptr(THR_THD, 0); + } DBUG_RETURN(return_val); } /* Reload grant array if possible */ -void grant_reload(void) +void grant_reload(THD *thd) { HASH old_hash_tables;bool old_grant_option; MEM_ROOT old_mem; @@ -2372,7 +2386,7 @@ void grant_reload(void) old_grant_option = grant_option; old_mem = memex; - if (grant_init()) + if (grant_init(thd)) { // Error. Revert to old hash grant_free(); /* purecov: deadcode */ hash_tables=old_hash_tables; /* purecov: deadcode */ diff --git a/sql/sql_acl.h b/sql/sql_acl.h index 326a55ddd0c..6925b6b406c 100644 --- a/sql/sql_acl.h +++ b/sql/sql_acl.h @@ -81,7 +81,7 @@ /* prototypes */ -my_bool acl_init(bool dont_read_acl_tables); +my_bool acl_init(THD *thd, bool dont_read_acl_tables); void acl_reload(THD *thd); void acl_free(bool end=0); ulong acl_get(const char *host, const char *ip, const char *bin_ip, @@ -98,9 +98,9 @@ int mysql_grant(THD *thd, const char *db, List <LEX_USER> &user_list, int mysql_table_grant(THD *thd, TABLE_LIST *table, List <LEX_USER> &user_list, List <LEX_COLUMN> &column_list, ulong rights, bool revoke); -my_bool grant_init(void); +my_bool grant_init(THD *thd); void grant_free(void); -void grant_reload(void); +void grant_reload(THD *thd); bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables, uint show_command=0, bool dont_print_error=0); bool check_grant_column (THD *thd,TABLE *table, const char *name, uint length, diff --git a/sql/sql_analyse.cc b/sql/sql_analyse.cc index 5c735ab35d5..f98eb0e0b26 100644 --- a/sql/sql_analyse.cc +++ b/sql/sql_analyse.cc @@ -677,7 +677,7 @@ bool analyse::end_of_records() case FIELD_TYPE_DECIMAL: ans.append("DECIMAL", 7); // if item is FIELD_ITEM, it _must_be_ Field_num in this case - if (((Field_num*) (*f)->item)->zerofill) + if (((Field_num*) ((Item_field*) (*f)->item)->field)->zerofill) ans.append(" ZEROFILL"); break; default: diff --git a/sql/sql_base.cc b/sql/sql_base.cc index fd6c2c48020..59310fb00de 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -39,8 +39,8 @@ static key_map get_key_map_from_key_list(TABLE *table, List<String> *index_list); -static byte *cache_key(const byte *record,uint *length, - my_bool not_used __attribute__((unused))) +extern "C" byte *table_cache_key(const byte *record,uint *length, + my_bool not_used __attribute__((unused))) { TABLE *entry=(TABLE*) record; *length=entry->key_length; @@ -50,8 +50,8 @@ static byte *cache_key(const byte *record,uint *length, void table_cache_init(void) { VOID(hash_init(&open_cache,system_charset_info, - table_cache_size+16,0,0,cache_key, - (void (*)(void*)) free_cache_entry,0)); + table_cache_size+16,0,0,table_cache_key, + (hash_free_key) free_cache_entry,0)); mysql_rm_tmp_tables(); } @@ -536,14 +536,14 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh, if (!found) if_wait_for_refresh=0; // Nothing to wait for } + if (!tables) + kill_delayed_threads(); if (if_wait_for_refresh) { /* If there is any table that has a lower refresh_version, wait until this is closed (or this thread is killed) before returning */ - if (!tables) - kill_delayed_threads(); thd->mysys_var->current_mutex= &LOCK_open; thd->mysys_var->current_cond= &COND_refresh; thd->proc_info="Flushing tables"; @@ -699,26 +699,20 @@ void close_temporary_tables(THD *thd) { TABLE *table,*next; char *query, *end; - const uint init_query_buf_size = 11; // "drop table " uint query_buf_size; bool found_user_tables = 0; + if (!thd->temporary_tables) + return; + LINT_INIT(end); - query_buf_size = init_query_buf_size; + query_buf_size= 50; // Enough for DROP ... TABLE for (table=thd->temporary_tables ; table ; table=table->next) - { query_buf_size += table->key_length; - } - - if (query_buf_size == init_query_buf_size) - return; // no tables to close if ((query = alloc_root(&thd->mem_root, query_buf_size))) - { - memcpy(query, "drop table ", init_query_buf_size); - end = query + init_query_buf_size; - } + end=strmov(query, "DROP /*!40005 TEMPORARY */ TABLE "); for (table=thd->temporary_tables ; table ; table=next) { @@ -727,12 +721,14 @@ void close_temporary_tables(THD *thd) // skip temporary tables not created directly by the user if (table->real_name[0] != '#') { - end = strxmov(end,table->table_cache_key,".", - table->real_name,",", NullS); - // here we assume table_cache_key always starts - // with \0 terminated db name + /* + Here we assume table_cache_key always starts + with \0 terminated db name + */ found_user_tables = 1; } + end = strxmov(end,table->table_cache_key,".", + table->real_name,",", NullS); } next=table->next; close_temporary(table); @@ -740,7 +736,7 @@ void close_temporary_tables(THD *thd) if (query && found_user_tables && mysql_bin_log.is_open()) { /* The -1 is to remove last ',' */ - Query_log_event qinfo(thd, query, (ulong)(end-query)-1); + Query_log_event qinfo(thd, query, (ulong)(end-query)-1, 0); qinfo.error_code=0; mysql_bin_log.write(&qinfo); } @@ -1435,7 +1431,7 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db, int error; DBUG_ENTER("open_unireg_entry"); - (void) sprintf(path,"%s/%s/%s",mysql_data_home,db,name); + strxmov(path, mysql_data_home, "/", db, "/", name, NullS); if (openfrm(path,alias, (uint) (HA_OPEN_KEYFILE | HA_OPEN_RNDFILE | HA_GET_INDEX | HA_TRY_READ_ONLY), @@ -1564,6 +1560,61 @@ int open_tables(THD *thd,TABLE_LIST *start) } +/* + Check that lock is ok for tables; Call start stmt if ok + + SYNOPSIS + check_lock_and_start_stmt() + thd Thread handle + table_list Table to check + lock_type Lock used for table + + RETURN VALUES + 0 ok + 1 error +*/ + +static bool check_lock_and_start_stmt(THD *thd, TABLE *table, + thr_lock_type lock_type) +{ + int error; + DBUG_ENTER("check_lock_and_start_stmt"); + + if ((int) lock_type >= (int) TL_WRITE_ALLOW_READ && + (int) table->reginfo.lock_type < (int) TL_WRITE_ALLOW_READ) + { + my_printf_error(ER_TABLE_NOT_LOCKED_FOR_WRITE, + ER(ER_TABLE_NOT_LOCKED_FOR_WRITE), + MYF(0),table->table_name); + DBUG_RETURN(1); + } + if ((error=table->file->start_stmt(thd))) + { + table->file->print_error(error,MYF(0)); + DBUG_RETURN(1); + } + DBUG_RETURN(0); +} + + +/* + Open and lock one table + + SYNOPSIS + open_ltable() + thd Thread handler + table_list Table to open is first table in this list + lock_type Lock to use for open + + RETURN VALUES + table Opened table + 0 Error + + If ok, the following are also set: + table_list->lock_type lock_type + table_list->table table +*/ + TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type) { TABLE *table; @@ -1576,8 +1627,6 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type) &refresh)) && refresh) ; if (table) { - int error; - #if defined( __WIN__) || defined(OS2) /* Win32 can't drop a file that is open */ if (lock_type == TL_WRITE_ALLOW_READ) @@ -1585,39 +1634,29 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type) lock_type= TL_WRITE; } #endif /* __WIN__ || OS2 */ - - table_list->table=table; + table_list->lock_type= lock_type; + table_list->table= table; table->grant= table_list->grant; if (thd->locked_tables) { - thd->proc_info=0; - if ((int) lock_type >= (int) TL_WRITE_ALLOW_READ && - (int) table->reginfo.lock_type < (int) TL_WRITE_ALLOW_READ) - { - my_printf_error(ER_TABLE_NOT_LOCKED_FOR_WRITE, - ER(ER_TABLE_NOT_LOCKED_FOR_WRITE), - MYF(0),table_list->alias); - table=0; - } - else if ((error=table->file->start_stmt(thd))) - { - table->file->print_error(error,MYF(0)); - table=0; - } - thd->proc_info=0; - DBUG_RETURN(table); + if (check_lock_and_start_stmt(thd, table, lock_type)) + table= 0; + } + else + { + if ((table->reginfo.lock_type= lock_type) != TL_UNLOCK) + if (!(thd->lock=mysql_lock_tables(thd,&table_list->table,1))) + table= 0; } - if ((table->reginfo.lock_type=lock_type) != TL_UNLOCK) - if (!(thd->lock=mysql_lock_tables(thd,&table_list->table,1))) - DBUG_RETURN(0); } thd->proc_info=0; DBUG_RETURN(table); } + /* -** Open all tables in list and locks them for read. -** The lock will automaticly be freed by the close_thread_tables + Open all tables in list and locks them for read. + The lock will automaticly be freed by close_thread_tables() */ int open_and_lock_tables(THD *thd,TABLE_LIST *tables) @@ -1627,10 +1666,27 @@ int open_and_lock_tables(THD *thd,TABLE_LIST *tables) return 0; } + +/* + Lock all tables in list + + SYNOPSIS + lock_tables() + thd Thread handler + tables Tables to lock + + RETURN VALUES + 0 ok + -1 Error +*/ + int lock_tables(THD *thd,TABLE_LIST *tables) { TABLE_LIST *table; - if (tables && !thd->locked_tables) + if (!tables) + return 0; + + if (!thd->locked_tables) { uint count=0; for (table = tables ; table ; table=table->next) @@ -1647,10 +1703,9 @@ int lock_tables(THD *thd,TABLE_LIST *tables) { for (table = tables ; table ; table=table->next) { - int error; - if ((error=table->table->file->start_stmt(thd))) + if (check_lock_and_start_stmt(thd, table->table, table->lock_type)) { - table->table->file->print_error(error,MYF(0)); + ha_rollback_stmt(thd); return -1; } } @@ -1658,10 +1713,11 @@ int lock_tables(THD *thd,TABLE_LIST *tables) return 0; } + /* -** Open a single table without table caching and don't set it in open_list -** Used by alter_table to open a temporary table and when creating -** a temporary table with CREATE TEMPORARY ... + Open a single table without table caching and don't set it in open_list + Used by alter_table to open a temporary table and when creating + a temporary table with CREATE TEMPORARY ... */ TABLE *open_temporary_table(THD *thd, const char *path, const char *db, @@ -1670,11 +1726,13 @@ TABLE *open_temporary_table(THD *thd, const char *path, const char *db, TABLE *tmp_table; DBUG_ENTER("open_temporary_table"); - // the extra size in my_malloc() is for table_cache_key - // 4 bytes for master thread id if we are in the slave - // 1 byte to terminate db - // 1 byte to terminate table_name - // total of 6 extra bytes in my_malloc in addition to table/db stuff + /* + The extra size in my_malloc() is for table_cache_key + 4 bytes for master thread id if we are in the slave + 1 byte to terminate db + 1 byte to terminate table_name + total of 6 extra bytes in my_malloc in addition to table/db stuff + */ if (!(tmp_table=(TABLE*) my_malloc(sizeof(*tmp_table)+(uint) strlen(db)+ (uint) strlen(table_name)+6, MYF(MY_WME)))) @@ -2071,6 +2129,7 @@ bool setup_tables(TABLE_LIST *tables) DBUG_RETURN(1); table->keys_in_use_for_query &= ~map; } + table->used_keys &= table->keys_in_use_for_query; if (table_list->shared) { /* Clear query_id that may have been set by previous select */ @@ -2202,6 +2261,7 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds) Item_cond_and *cond_and=new Item_cond_and(); if (!cond_and) // If not out of memory DBUG_RETURN(1); + cond_and->top_level_item(); uint i,j; for (i=0 ; i < t1->fields ; i++) diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index 2f236da2aa3..ef584f4364e 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -473,33 +473,6 @@ byte *query_cache_table_get_key(const byte *record, uint *length, Query_cache_query methods *****************************************************************************/ -void Query_cache_query::init_n_lock() -{ - DBUG_ENTER("Query_cache_query::init_n_lock"); - res=0; wri = 0; len = 0; - my_rwlock_init(&lock, NULL); - lock_writing(); - DBUG_PRINT("qcache", ("inited & locked query for block 0x%lx", - ((byte*) this)-ALIGN_SIZE(sizeof(Query_cache_block)))); - DBUG_VOID_RETURN; -} - - -void Query_cache_query::unlock_n_destroy() -{ - DBUG_ENTER("Query_cache_query::unlock_n_destroy"); - DBUG_PRINT("qcache", ("destroyed & unlocked query for block 0x%lx", - ((byte*)this)-ALIGN_SIZE(sizeof(Query_cache_block)))); - /* - The following call is not needed on system where one can destroy an - active semaphore - */ - this->unlock_writing(); - rwlock_destroy(&lock); - DBUG_VOID_RETURN; -} - - /* Following methods work for block read/write locking only in this particular case and in interaction with structure_guard_mutex. @@ -551,6 +524,34 @@ inline void Query_cache_query::unlock_reading() RW_UNLOCK(&lock); } + +void Query_cache_query::init_n_lock() +{ + DBUG_ENTER("Query_cache_query::init_n_lock"); + res=0; wri = 0; len = 0; + my_rwlock_init(&lock, NULL); + lock_writing(); + DBUG_PRINT("qcache", ("inited & locked query for block 0x%lx", + ((byte*) this)-ALIGN_SIZE(sizeof(Query_cache_block)))); + DBUG_VOID_RETURN; +} + + +void Query_cache_query::unlock_n_destroy() +{ + DBUG_ENTER("Query_cache_query::unlock_n_destroy"); + DBUG_PRINT("qcache", ("destroyed & unlocked query for block 0x%lx", + ((byte*)this)-ALIGN_SIZE(sizeof(Query_cache_block)))); + /* + The following call is not needed on system where one can destroy an + active semaphore + */ + this->unlock_writing(); + rwlock_destroy(&lock); + DBUG_VOID_RETURN; +} + + extern "C" { byte *query_cache_query_get_key(const byte *record, uint *length, @@ -714,19 +715,19 @@ void query_cache_invalidate_by_MyISAM_filename(const char *filename) Query_cache methods *****************************************************************************/ -Query_cache::Query_cache(ulong query_cache_limit, - ulong min_allocation_unit, - ulong min_result_data_size, - uint def_query_hash_size , - uint def_table_hash_size) +Query_cache::Query_cache(ulong query_cache_limit_arg, + ulong min_allocation_unit_arg, + ulong min_result_data_size_arg, + uint def_query_hash_size_arg, + uint def_table_hash_size_arg) :query_cache_size(0), - query_cache_limit(query_cache_limit), + query_cache_limit(query_cache_limit_arg), queries_in_cache(0), hits(0), inserts(0), refused(0), - total_blocks(0), - min_allocation_unit(ALIGN_SIZE(min_allocation_unit)), - min_result_data_size(ALIGN_SIZE(min_result_data_size)), - def_query_hash_size(ALIGN_SIZE(def_query_hash_size)), - def_table_hash_size(ALIGN_SIZE(def_table_hash_size)), + total_blocks(0), lowmem_prunes(0), + min_allocation_unit(ALIGN_SIZE(min_allocation_unit_arg)), + min_result_data_size(ALIGN_SIZE(min_result_data_size_arg)), + def_query_hash_size(ALIGN_SIZE(def_query_hash_size_arg)), + def_table_hash_size(ALIGN_SIZE(def_table_hash_size_arg)), initialized(0) { ulong min_needed= (ALIGN_SIZE(sizeof(Query_cache_block)) + @@ -751,13 +752,13 @@ ulong Query_cache::resize(ulong query_cache_size_arg) void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used) { - TABLE_COUNTER_TYPE tables; + TABLE_COUNTER_TYPE local_tables; ulong tot_length; DBUG_ENTER("Query_cache::store_query"); if (query_cache_size == 0) DBUG_VOID_RETURN; - if ((tables = is_cacheable(thd, thd->query_length, + if ((local_tables = is_cacheable(thd, thd->query_length, thd->query, &thd->lex, tables_used))) { NET *net = &thd->net; @@ -803,7 +804,7 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used) Query_cache_block *query_block; query_block= write_block_data(tot_length, (gptr) thd->query, ALIGN_SIZE(sizeof(Query_cache_query)), - Query_cache_block::QUERY, tables, 1); + Query_cache_block::QUERY, local_tables, 1); if (query_block != 0) { DBUG_PRINT("qcache", ("query block 0x%lx allocated, %lu", @@ -820,7 +821,7 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used) STRUCT_UNLOCK(&structure_guard_mutex); goto end; } - if (!register_all_tables(query_block, tables_used, tables)) + if (!register_all_tables(query_block, tables_used, local_tables)) { refused++; DBUG_PRINT("warning", ("tables list including failed")); @@ -1527,6 +1528,7 @@ my_bool Query_cache::free_old_query() if (query_block != 0) { free_query(query_block); + lowmem_prunes++; DBUG_RETURN(0); } } @@ -1796,7 +1798,7 @@ inline ulong Query_cache::get_min_append_result_data_size() my_bool Query_cache::allocate_data_chain(Query_cache_block **result_block, ulong data_len, Query_cache_block *query_block, - my_bool first_block) + my_bool first_block_arg) { ulong all_headers_len = (ALIGN_SIZE(sizeof(Query_cache_block)) + ALIGN_SIZE(sizeof(Query_cache_result))); @@ -1806,7 +1808,7 @@ my_bool Query_cache::allocate_data_chain(Query_cache_block **result_block, DBUG_PRINT("qcache", ("data_len %lu, all_headers_len %lu", data_len, all_headers_len)); - ulong min_size = (first_block ? + ulong min_size = (first_block_arg ? get_min_first_result_data_size(): get_min_append_result_data_size()); *result_block = allocate_block(max(min_size, align_len), @@ -1833,7 +1835,7 @@ my_bool Query_cache::allocate_data_chain(Query_cache_block **result_block, Query_cache_block *next_block; if ((success = allocate_data_chain(&next_block, len - new_block->length, - query_block, first_block))) + query_block, first_block_arg))) double_linked_list_join(new_block, next_block); } if (success) @@ -1902,14 +1904,23 @@ void Query_cache::invalidate_table(Query_cache_block *table_block) } } +/* + Store all used tables + + SYNOPSIS + register_all_tables() + block Store tables in this block + tables_used List if used tables + tables_arg Not used ? +*/ my_bool Query_cache::register_all_tables(Query_cache_block *block, TABLE_LIST *tables_used, - TABLE_COUNTER_TYPE tables) + TABLE_COUNTER_TYPE tables_arg) { TABLE_COUNTER_TYPE n; DBUG_PRINT("qcache", ("register tables block 0x%lx, n %d, header %x", - (ulong) block, (int) tables, + (ulong) block, (int) tables_arg, (int) ALIGN_SIZE(sizeof(Query_cache_block)))); Query_cache_block_table *block_table = block->table(0); @@ -2201,28 +2212,28 @@ void Query_cache::split_block(Query_cache_block *block, ulong len) Query_cache_block * -Query_cache::join_free_blocks(Query_cache_block *first_block, +Query_cache::join_free_blocks(Query_cache_block *first_block_arg, Query_cache_block *block_in_list) { Query_cache_block *second_block; DBUG_ENTER("Query_cache::join_free_blocks"); DBUG_PRINT("qcache", ("join first 0x%lx, pnext 0x%lx, in list 0x%lx", - (ulong) first_block, (ulong) first_block->pnext, + (ulong) first_block_arg, (ulong) first_block_arg->pnext, (ulong) block_in_list)); exclude_from_free_memory_list(block_in_list); - second_block = first_block->pnext; + second_block = first_block_arg->pnext; // May be was not free block second_block->used=0; second_block->destroy(); total_blocks--; - first_block->length += second_block->length; - first_block->pnext = second_block->pnext; - second_block->pnext->pprev = first_block; + first_block_arg->length += second_block->length; + first_block_arg->pnext = second_block->pnext; + second_block->pnext->pprev = first_block_arg; - DBUG_RETURN(first_block); + DBUG_RETURN(first_block_arg); } @@ -2439,7 +2450,7 @@ TABLE_COUNTER_TYPE Query_cache::is_cacheable(THD *thd, uint32 query_len, char *query, LEX *lex, TABLE_LIST *tables_used) { - TABLE_COUNTER_TYPE tables = 0; + TABLE_COUNTER_TYPE table_count = 0; DBUG_ENTER("Query_cache::is_cacheable"); if (lex->sql_command == SQLCOM_SELECT && @@ -2456,7 +2467,7 @@ TABLE_COUNTER_TYPE Query_cache::is_cacheable(THD *thd, uint32 query_len, for (; tables_used; tables_used= tables_used->next) { - tables++; + table_count++; DBUG_PRINT("qcache", ("table %s, db %s, type %u", tables_used->real_name, tables_used->db, tables_used->table->db_type)); @@ -2480,7 +2491,7 @@ TABLE_COUNTER_TYPE Query_cache::is_cacheable(THD *thd, uint32 query_len, { ha_myisammrg *handler = (ha_myisammrg *)tables_used->table->file; MYRG_INFO *file = handler->myrg_info(); - tables+= (file->end_table - file->open_tables); + table_count+= (file->end_table - file->open_tables); } } @@ -2490,8 +2501,8 @@ TABLE_COUNTER_TYPE Query_cache::is_cacheable(THD *thd, uint32 query_len, DBUG_PRINT("qcache", ("not in autocommin mode")); DBUG_RETURN(0); } - DBUG_PRINT("qcache", ("select is using %d tables", tables)); - DBUG_RETURN(tables); + DBUG_PRINT("qcache", ("select is using %d tables", table_count)); + DBUG_RETURN(table_count); } DBUG_PRINT("qcache", diff --git a/sql/sql_cache.h b/sql/sql_cache.h index f19e6630da5..b15df28f54b 100644 --- a/sql/sql_cache.h +++ b/sql/sql_cache.h @@ -178,7 +178,7 @@ extern "C" my_bool not_used); } void query_cache_insert(NET *thd, const char *packet, ulong length); -void query_cache_invalidate_by_MyISAM_filename(const char* filename); +extern "C" void query_cache_invalidate_by_MyISAM_filename(const char* filename); struct Query_cache_memory_bin @@ -219,7 +219,7 @@ public: ulong query_cache_size, query_cache_limit; /* statistics */ ulong free_memory, queries_in_cache, hits, inserts, refused, - free_memory_blocks, total_blocks; + free_memory_blocks, total_blocks, lowmem_prunes; protected: /* diff --git a/sql/sql_class.cc b/sql/sql_class.cc index b7cca50ffb5..e3ee0fb9f72 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -59,14 +59,14 @@ template class List_iterator<Alter_column>; ** User variables ****************************************************************************/ -static byte* get_var_key(user_var_entry *entry, uint *length, - my_bool not_used __attribute__((unused))) +extern "C" byte *get_var_key(user_var_entry *entry, uint *length, + my_bool not_used __attribute__((unused))) { *length=(uint) entry->name.length; return (byte*) entry->name.str; } -static void free_var(user_var_entry *entry) +extern "C" void free_user_var(user_var_entry *entry) { char *pos= (char*) entry+ALIGN_SIZE(sizeof(*entry)); if (entry->value && entry->value != pos) @@ -88,9 +88,6 @@ THD::THD():user_time(0), fatal_error(0), host_or_ip="unknown ip"; locked=killed=count_cuted_fields=some_tables_deleted=no_errors=password= query_start_used=safe_to_cache_query=prepare_command=0; - pthread_mutex_lock(&LOCK_global_system_variables); - variables= global_system_variables; - pthread_mutex_unlock(&LOCK_global_system_variables); db_length=query_length=col_access=0; query_error=0; next_insert_id=last_insert_id=0; @@ -133,19 +130,12 @@ THD::THD():user_time(0), fatal_error(0), server_id = ::server_id; slave_net = 0; log_pos = 0; - server_status= SERVER_STATUS_AUTOCOMMIT; - update_lock_default= (variables.low_priority_updates ? - TL_WRITE_LOW_PRIORITY : - TL_WRITE); - options= thd_startup_options; - sql_mode=(uint) opt_sql_mode; - open_options=ha_open_options; - session_tx_isolation= (enum_tx_isolation) variables.tx_isolation; command=COM_CONNECT; set_query_id=1; db_access=NO_ACCESS; version=refresh_version; // For boot + init(); /* Initialize sub structures */ bzero((char*) &mem_root,sizeof(mem_root)); bzero((char*) &transaction.mem_root,sizeof(transaction.mem_root)); @@ -157,7 +147,7 @@ THD::THD():user_time(0), fatal_error(0), user_connect=(USER_CONN *)0; hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0, (hash_get_key) get_var_key, - (void (*)(void*)) free_var,0); + (hash_free_key) free_user_var,0); /* Prepared statements */ last_prepared_stmt= 0; @@ -190,6 +180,48 @@ THD::THD():user_time(0), fatal_error(0), } } + +/* + Init common variables that has to be reset on start and on change_user +*/ + +void THD::init(void) +{ + server_status= SERVER_STATUS_AUTOCOMMIT; + update_lock_default= (variables.low_priority_updates ? + TL_WRITE_LOW_PRIORITY : + TL_WRITE); + options= thd_startup_options; + sql_mode=(uint) opt_sql_mode; + open_options=ha_open_options; + pthread_mutex_lock(&LOCK_global_system_variables); + variables= global_system_variables; + pthread_mutex_unlock(&LOCK_global_system_variables); + session_tx_isolation= (enum_tx_isolation) variables.tx_isolation; +} + +/* + Do what's needed when one invokes change user + + SYNOPSIS + change_user() + + IMPLEMENTATION + Reset all resources that are connection specific +*/ + + +void THD::change_user(void) +{ + cleanup(); + cleanup_done=0; + init(); + hash_init(&user_vars, USER_VARS_HASH_SIZE, 0, 0, + (hash_get_key) get_var_key, + (hash_free_key) free_user_var,0); +} + + /* Do operations that may take a long time */ void THD::cleanup(void) @@ -207,17 +239,21 @@ void THD::cleanup(void) close_thread_tables(this); } close_temporary_tables(this); -#ifdef USING_TRANSACTIONS - if (opt_using_transactions) + hash_free(&user_vars); + if (global_read_lock) + unlock_global_read_lock(this); + if (ull) { - close_cached_file(&transaction.trans_log); - ha_close_connection(this); + pthread_mutex_lock(&LOCK_user_locks); + item_user_lock_release(ull); + pthread_mutex_unlock(&LOCK_user_locks); + ull= 0; } -#endif cleanup_done=1; DBUG_VOID_RETURN; } + THD::~THD() { THD_CHECK_SENTRY(this); @@ -234,15 +270,13 @@ THD::~THD() } if (!cleanup_done) cleanup(); - if (global_read_lock) - unlock_global_read_lock(this); - if (ull) +#ifdef USING_TRANSACTIONS + if (opt_using_transactions) { - pthread_mutex_lock(&LOCK_user_locks); - item_user_lock_release(ull); - pthread_mutex_unlock(&LOCK_user_locks); + close_cached_file(&transaction.trans_log); + ha_close_connection(this); } - hash_free(&user_vars); +#endif DBUG_PRINT("info", ("freeing host")); if (host != localhost) // If not pointer to constant @@ -338,20 +372,21 @@ void THD::add_changed_table(TABLE *table) DBUG_VOID_RETURN; } + void THD::add_changed_table(const char *key, long key_length) { DBUG_ENTER("THD::add_changed_table(key)"); - CHANGED_TABLE_LIST** prev = &transaction.changed_tables; - CHANGED_TABLE_LIST* curr = transaction.changed_tables; + CHANGED_TABLE_LIST **prev_changed = &transaction.changed_tables; + CHANGED_TABLE_LIST *curr = transaction.changed_tables; - for (; curr; prev = &(curr->next), curr = curr->next) + for (; curr; prev_changed = &(curr->next), curr = curr->next) { int cmp = (long)curr->key_length - (long)key_length; if (cmp < 0) { - list_include(prev, curr, changed_table_dup(key, key_length)); + list_include(prev_changed, curr, changed_table_dup(key, key_length)); DBUG_PRINT("info", - ("key_length %u %u", key_length, (*prev)->key_length)); + ("key_length %u %u", key_length, (*prev_changed)->key_length)); DBUG_VOID_RETURN; } else if (cmp == 0) @@ -359,10 +394,10 @@ void THD::add_changed_table(const char *key, long key_length) cmp = memcmp(curr->key, key, curr->key_length); if (cmp < 0) { - list_include(prev, curr, changed_table_dup(key, key_length)); + list_include(prev_changed, curr, changed_table_dup(key, key_length)); DBUG_PRINT("info", ("key_length %u %u", key_length, - (*prev)->key_length)); + (*prev_changed)->key_length)); DBUG_VOID_RETURN; } else if (cmp == 0) @@ -372,9 +407,9 @@ void THD::add_changed_table(const char *key, long key_length) } } } - *prev = changed_table_dup(key, key_length); + *prev_changed = changed_table_dup(key, key_length); DBUG_PRINT("info", ("key_length %u %u", key_length, - (*prev)->key_length)); + (*prev_changed)->key_length)); DBUG_VOID_RETURN; } diff --git a/sql/sql_class.h b/sql/sql_class.h index 9a7ee4556e8..acdf2471ba8 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -488,6 +488,7 @@ public: uint total_warn_count, old_total_warn_count; ulong query_id, warn_id, version, options, thread_id, col_access; ulong current_stmt_id; + ulong rand_saved_seed1, rand_saved_seed2; long dbug_thread_id; pthread_t real_id; uint current_tablenr,tmp_table,cond_count; @@ -504,7 +505,6 @@ public: bool set_query_id,locked,count_cuted_fields,some_tables_deleted; bool no_errors, allow_sum_func, password, fatal_error; bool query_start_used,last_insert_id_used,insert_id_used,rand_used; - ulonglong rand_saved_seed1, rand_saved_seed2; bool system_thread,in_lock_tables,global_read_lock; bool query_error, bootstrap, cleanup_done; bool safe_to_cache_query; @@ -534,6 +534,8 @@ public: THD(); ~THD(); + void init(void); + void change_user(void); void cleanup(void); bool store_globals(); #ifdef SIGNAL_WITH_VIO_CLOSE @@ -932,11 +934,9 @@ public: ha_rows deleted; uint num_of_tables; int error; - thr_lock_type lock_option; - bool do_delete, not_trans_safe; + bool do_delete, transactional_tables, log_delayed, normal_tables; public: - multi_delete(THD *thd, TABLE_LIST *dt, thr_lock_type lock_option_arg, - uint num_of_tables); + multi_delete(THD *thd, TABLE_LIST *dt, uint num_of_tables); ~multi_delete(); int prepare(List<Item> &list, SELECT_LEX_UNIT *u); bool send_fields(List<Item> &list, @@ -956,7 +956,6 @@ public: ha_rows updated, found; List<Item> fields; List <Item> **fields_by_tables; - thr_lock_type lock_option; enum enum_duplicates dupl; uint num_of_tables, num_fields, num_updated, *save_time_stamps, *field_sequence; int error; @@ -964,7 +963,7 @@ public: public: multi_update(THD *thd_arg, TABLE_LIST *ut, List<Item> &fs, enum enum_duplicates handle_duplicates, - thr_lock_type lock_option_arg, uint num); + uint num); ~multi_update(); int prepare(List<Item> &list, SELECT_LEX_UNIT *u); bool send_fields(List<Item> &list, diff --git a/sql/sql_db.cc b/sql/sql_db.cc index b80e25c9f40..cefad6a0805 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -220,7 +220,7 @@ int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info, if (!thd->query) // Only in replication { query= path; - query_length= (uint) (strxmov(path,"create database ", db, NullS) - + query_length= (uint) (strxmov(path,"create database `", db, "`", NullS) - path); } else @@ -231,7 +231,7 @@ int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info, mysql_update_log.write(thd, query, query_length); if (mysql_bin_log.is_open()) { - Query_log_event qinfo(thd, query, query_length); + Query_log_event qinfo(thd, query, query_length, 0); mysql_bin_log.write(&qinfo); } send_ok(thd, result); @@ -346,22 +346,25 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) query_cache_invalidate1(db); if (!silent) { + const char *query; + ulong query_length; if (!thd->query) { - thd->query = path; - thd->query_length = (uint) (strxmov(path,"drop database ", db, NullS)- - path); + /* The client used the old obsolete mysql_drop_db() call */ + query= path; + query_length = (uint) (strxmov(path,"drop database `", db, "`", + NullS)- path); } - mysql_update_log.write(thd, thd->query, thd->query_length); - if (mysql_bin_log.is_open()) + else { - Query_log_event qinfo(thd, thd->query, thd->query_length); - mysql_bin_log.write(&qinfo); + query=thd->query; + query_length=thd->query_length; } - if (thd->query == path) + mysql_update_log.write(thd, query, query_length); + if (mysql_bin_log.is_open()) { - thd->query = 0; // just in case - thd->query_length = 0; + Query_log_event qinfo(thd, query, query_length, 0); + mysql_bin_log.write(&qinfo); } send_ok(thd,(ulong) deleted); } diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 811cc7c5f5e..cc60ebfb58d 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -28,20 +28,18 @@ #include "sql_select.h" int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order, - ha_rows limit, thr_lock_type lock_type, ulong options) + ha_rows limit, ulong options) { int error; TABLE *table; SQL_SELECT *select=0; READ_RECORD info; bool using_limit=limit != HA_POS_ERROR; - bool using_transactions, safe_update, const_cond; + bool using_transactions, log_delayed, safe_update, const_cond; ha_rows deleted; DBUG_ENTER("mysql_delete"); - if (!table_list->db) - table_list->db=thd->db; - if (!(table = open_ltable(thd,table_list, lock_type))) + if (!(table = open_ltable(thd, table_list, table_list->lock_type))) DBUG_RETURN(-1); table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK); thd->proc_info="init"; @@ -162,23 +160,34 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order, (void) table->file->extra(HA_EXTRA_NORMAL); cleanup: - using_transactions=table->file->has_transactions(); - if (deleted && (error <= 0 || !using_transactions)) + transactional_table= table->file->has_transactions(); + log_delayed= (transactional_table || table->tmp_table); + if (deleted && (error <= 0 || !transactional_table)) { mysql_update_log.write(thd,thd->query, thd->query_length); if (mysql_bin_log.is_open()) { Query_log_event qinfo(thd, thd->query, thd->query_length, - using_transactions); - if (mysql_bin_log.write(&qinfo) && using_transactions) + log_delayed); + if (mysql_bin_log.write(&qinfo) && transactional_table) error=1; } - if (!using_transactions) + if (!log_delayed) thd->options|=OPTION_STATUS_NO_TRANS_UPDATE; } - if (using_transactions && ha_autocommit_or_rollback(thd,error >= 0)) - error=1; - if (deleted) + if (transactional_table) + { + if (ha_autocommit_or_rollback(thd,error >= 0)) + error=1; + } + /* + Only invalidate the query cache if something changed or if we + didn't commit the transacion (query cache is automaticly + invalidated on commit) + */ + if (deleted && + (!transactional_table || + thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) { query_cache_invalidate3(thd, table_list, 1); } @@ -205,19 +214,17 @@ cleanup: #define MEM_STRIP_BUF_SIZE current_thd->variables.sortbuff_size -int refposcmp2(void* arg, const void *a,const void *b) +extern "C" int refposcmp2(void* arg, const void *a,const void *b) { return memcmp(a,b, *(int*) arg); } multi_delete::multi_delete(THD *thd_arg, TABLE_LIST *dt, - thr_lock_type lock_option_arg, uint num_of_tables_arg) : delete_tables (dt), thd(thd_arg), deleted(0), - num_of_tables(num_of_tables_arg), error(0), lock_option(lock_option_arg), - do_delete(false) + num_of_tables(num_of_tables_arg), error(0), + do_delete(0), transactional_tables(0), log_delayed(0), normal_tables(0) { - not_trans_safe=false; tempfiles = (Unique **) sql_calloc(sizeof(Unique *) * (num_of_tables-1)); } @@ -268,8 +275,12 @@ multi_delete::initialize_tables(JOIN *join) /* Don't use KEYREAD optimization on this table */ tbl->no_keyread=1; walk=walk->next; - if (!not_trans_safe && !tbl->file->has_transactions()) - not_trans_safe=true; + if (tbl->file->has_transactions()) + log_delayed= transactional_tables= 1; + else if (tbl->tmp_table != NO_TMP_TABLE) + log_delayed= 1; + else + normal_tables= 1; } } walk= delete_tables; @@ -375,7 +386,7 @@ void multi_delete::send_error(uint errcode,const char *err) In all other cases do attempt deletes ... */ if ((table_being_deleted->table->file->has_transactions() && - table_being_deleted == delete_tables) || !not_trans_safe) + table_being_deleted == delete_tables) || !normal_tables) ha_rollback_stmt(thd); else if (do_delete) { @@ -394,7 +405,7 @@ void multi_delete::send_error(uint errcode,const char *err) int multi_delete::do_deletes(bool from_send_error) { - int error = 0, counter = 0; + int local_error= 0, counter= 0; if (from_send_error) { @@ -415,27 +426,26 @@ int multi_delete::do_deletes(bool from_send_error) TABLE *table = table_being_deleted->table; if (tempfiles[counter]->get(table)) { - error=1; + local_error=1; break; } READ_RECORD info; init_read_record(&info,thd,table,NULL,0,0); - while (!(error=info.read_record(&info)) && - (!thd->killed || from_send_error || not_trans_safe)) + while (!(local_error=info.read_record(&info)) && !thd->killed) { - if ((error=table->file->delete_row(table->record[0]))) + if ((local_error=table->file->delete_row(table->record[0]))) { - table->file->print_error(error,MYF(0)); + table->file->print_error(local_error,MYF(0)); break; } deleted++; } end_read_record(&info); - if (error == -1) // End of file - error = 0; + if (local_error == -1) // End of file + local_error = 0; } - return error; + return local_error; } @@ -451,15 +461,11 @@ bool multi_delete::send_eof() thd->proc_info="deleting from reference tables"; /* Does deletes for the last n - 1 tables, returns 0 if ok */ - int error = do_deletes(0); // returns 0 if success + int local_error= do_deletes(0); // returns 0 if success /* reset used flags */ thd->proc_info="end"; - if (error) - { - ::send_error(thd); - return 1; - } + /* Write the SQL statement to the binlog if we deleted @@ -467,24 +473,25 @@ bool multi_delete::send_eof() was a non-transaction-safe table involved, since modifications in it cannot be rolled back. */ - if (deleted || not_trans_safe) + if (deleted) { mysql_update_log.write(thd,thd->query,thd->query_length); if (mysql_bin_log.is_open()) { - Query_log_event qinfo(thd, thd->query, thd->query_length); - if (mysql_bin_log.write(&qinfo) && - !not_trans_safe) - error=1; // Log write failed: roll back the SQL statement + Query_log_event qinfo(thd, thd->query, thd->query_length, + log_delayed); + if (mysql_bin_log.write(&qinfo) && !normal_tables) + local_error=1; // Log write failed: roll back the SQL statement } /* Commit or rollback the current SQL statement */ - VOID(ha_autocommit_or_rollback(thd,error > 0)); - } - if (deleted) - { + VOID(ha_autocommit_or_rollback(thd,local_error > 0)); + query_cache_invalidate3(thd, delete_tables, 1); } - ::send_ok(thd,deleted); + if (local_error) + ::send_error(thd); + else + ::send_ok(thd, deleted); return 0; } @@ -557,8 +564,9 @@ int mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok) if (!ha_supports_generate(table_type)) { /* Probably InnoDB table */ - DBUG_RETURN(mysql_delete(thd,table_list, (COND*) 0, (ORDER*) 0, - HA_POS_ERROR, TL_WRITE, 0)); + table_list->lock_type= TL_WRITE; + DBUG_RETURN(mysql_delete(thd, table_list, (COND*) 0, (ORDER*) 0, + HA_POS_ERROR, 0)); } if (lock_and_wait_for_table_name(thd, table_list)) DBUG_RETURN(-1); @@ -570,6 +578,7 @@ int mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok) *fn_ext(path)=0; // Remove the .frm extension error= ha_create_table(path,&create_info,1) ? -1 : 0; query_cache_invalidate3(thd, table_list, 0); + end: if (!dont_send_ok) { @@ -578,7 +587,8 @@ end: mysql_update_log.write(thd,thd->query,thd->query_length); if (mysql_bin_log.is_open()) { - Query_log_event qinfo(thd, thd->query, thd->query_length); + Query_log_event qinfo(thd, thd->query, thd->query_length, + thd->tmp_table); mysql_bin_log.write(&qinfo); } send_ok(thd); // This should return record count diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 0a1b4435fff..6cb146afb33 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -25,7 +25,7 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list); static int write_delayed(THD *thd,TABLE *table, enum_duplicates dup, char *query, uint query_length, bool log_on); static void end_delayed_insert(THD *thd); -static pthread_handler_decl(handle_delayed_insert,arg); +extern "C" pthread_handler_decl(handle_delayed_insert,arg); static void unlink_blobs(register TABLE *table); /* Define to force use of my_malloc() if the allocated memory block is big */ @@ -98,13 +98,12 @@ check_insert_fields(THD *thd,TABLE *table,List<Item> &fields, int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields, - List<List_item> &values_list,enum_duplicates duplic, - thr_lock_type lock_type) + List<List_item> &values_list,enum_duplicates duplic) { int error; bool log_on= ((thd->options & OPTION_UPDATE_LOG) || !(thd->master_access & SUPER_ACL)); - bool using_transactions, bulk_insert=0; + bool transactional_table, log_delayed, bulk_insert=0; uint value_count; uint save_time_stamp; ulong counter = 1; @@ -114,6 +113,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields, List_iterator_fast<List_item> its(values_list); List_item *values; char *query=thd->query; + thr_lock_type lock_type = table_list->lock_type; DBUG_ENTER("mysql_insert"); /* @@ -194,14 +194,19 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields, thd->proc_info="update"; if (duplic == DUP_IGNORE || duplic == DUP_REPLACE) table->file->extra(HA_EXTRA_IGNORE_DUP_KEY); - if ((bulk_insert= (values_list.elements > 1 && + if ((bulk_insert= (values_list.elements >= MIN_ROWS_TO_USE_BULK_INSERT && lock_type != TL_WRITE_DELAYED && !(specialflag & SPECIAL_SAFE_MODE)))) { table->file->extra_opt(HA_EXTRA_WRITE_CACHE, - thd->variables.read_buff_size); - table->file->extra_opt(HA_EXTRA_BULK_INSERT_BEGIN, - thd->variables.bulk_insert_buff_size); + min(thd->variables.read_buff_size, + table->avg_row_length*values_list.elements)); + if (thd->variables.bulk_insert_buff_size) + table->file->extra_opt(HA_EXTRA_BULK_INSERT_BEGIN, + min(thd->variables.bulk_insert_buff_size, + (table->total_key_length + + table->keys * TREE_ELEMENT_EXTRA_SIZE)* + values_list.elements)); table->bulk_insert= 1; } @@ -266,10 +271,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields, info.copied=values_list.elements; end_delayed_insert(thd); } - if (info.copied || info.deleted) - { - query_cache_invalidate3(thd, table_list, 1); - } + query_cache_invalidate3(thd, table_list, 1); } else { @@ -297,23 +299,33 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields, thd->insert_id(id); // For update log else if (table->next_number_field) id=table->next_number_field->val_int(); // Return auto_increment value - using_transactions=table->file->has_transactions(); - if ((info.copied || info.deleted) && (error <= 0 || !using_transactions)) + + transactional_table= table->file->has_transactions(); + log_delayed= (transactional_table || table->tmp_table); + if ((info.copied || info.deleted) && (error <= 0 || !transactional_table)) { mysql_update_log.write(thd, thd->query, thd->query_length); if (mysql_bin_log.is_open()) { Query_log_event qinfo(thd, thd->query, thd->query_length, - using_transactions); - if (mysql_bin_log.write(&qinfo) && using_transactions) + log_delayed); + if (mysql_bin_log.write(&qinfo) && transactional_table) error=1; } - if (!using_transactions) + if (!log_delayed) thd->options|=OPTION_STATUS_NO_TRANS_UPDATE; } - if (using_transactions) + if (transactional_table) error=ha_autocommit_or_rollback(thd,error); - if (info.copied || info.deleted) + + /* + Only invalidate the query cache if something changed or if we + didn't commit the transacion (query cache is automaticly + invalidated on commit) + */ + if ((info.copied || info.deleted) && + (!transactional_table || + thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) { query_cache_invalidate3(thd, table_list, 1); } @@ -913,7 +925,7 @@ void kill_delayed_threads(void) * Create a new delayed insert thread */ -static pthread_handler_decl(handle_delayed_insert,arg) +extern "C" pthread_handler_decl(handle_delayed_insert,arg) { delayed_insert *di=(delayed_insert*) arg; THD *thd= &di->thd; @@ -1197,7 +1209,7 @@ bool delayed_insert::handle_inserts(void) mysql_update_log.write(&thd,row->query, row->query_length); if (using_bin_log) { - Query_log_event qinfo(&thd, row->query, row->query_length); + Query_log_event qinfo(&thd, row->query, row->query_length,0); mysql_bin_log.write(&qinfo); } } diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 6bafef8a469..9f8e3200246 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -436,9 +436,9 @@ typedef struct st_lex uint grant, grant_tot_col, which_columns; uint fk_delete_opt, fk_update_opt, fk_match_option; uint param_count; - bool drop_primary, drop_if_exists, local_file, olap; + bool drop_primary, drop_if_exists, drop_temporary, local_file; bool in_comment, ignore_space, verbose, simple_alter; - bool derived_tables, describe; + bool derived_tables, describe, olap; uint slave_thd_opt; CHARSET_INFO *charset; char *help_arg; diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 52d1f3adf48..00450a3b86c 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -90,7 +90,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, bool is_fifo=0; LOAD_FILE_INFO lf_info; char * db = table_list->db ? table_list->db : thd->db; - bool using_transactions; + bool transactional_table, log_delayed; DBUG_ENTER("mysql_load"); #ifdef EMBEDDED_LIBRARY @@ -105,6 +105,9 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, } if (!(table = open_ltable(thd,table_list,lock_type))) DBUG_RETURN(-1); + transactional_table= table->file->has_transactions(); + log_delayed= (transactional_table || table->tmp_table); + if (!fields.elements) { Field **field; @@ -224,6 +227,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, lf_info.handle_dup = handle_duplicates; lf_info.wrote_create_file = 0; lf_info.last_pos_in_file = HA_POS_ERROR; + lf_info.log_delayed= log_delayed; read_info.set_io_cache_arg((void*) &lf_info); } restore_record(table,2); @@ -275,16 +279,16 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, free_blobs(table); /* if pack_blob was used */ table->copy_blobs=0; thd->count_cuted_fields=0; /* Don`t calc cuted fields */ - using_transactions = table->file->has_transactions(); + if (error) { - if (using_transactions) + if (transactional_table) ha_autocommit_or_rollback(thd,error); if (!opt_old_rpl_compat && mysql_bin_log.is_open()) { if (lf_info.wrote_create_file) { - Delete_file_log_event d(thd); + Delete_file_log_event d(thd, log_delayed); mysql_bin_log.write(&d); } } @@ -297,27 +301,30 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, if (!thd->slave_thread) mysql_update_log.write(thd,thd->query,thd->query_length); - if (!using_transactions) + if (!log_delayed) thd->options|=OPTION_STATUS_NO_TRANS_UPDATE; if (mysql_bin_log.is_open()) { - if (opt_old_rpl_compat && !read_file_from_client) + if (opt_old_rpl_compat) { - Load_log_event qinfo(thd, ex, db, table->table_name, fields, - handle_duplicates); - mysql_bin_log.write(&qinfo); + if (!read_file_from_client) + { + Load_log_event qinfo(thd, ex, db, table->table_name, fields, + handle_duplicates, log_delayed); + mysql_bin_log.write(&qinfo); + } } - if (!opt_old_rpl_compat) + else { read_info.end_io_cache(); // make sure last block gets logged if (lf_info.wrote_create_file) { - Execute_load_log_event e(thd); + Execute_load_log_event e(thd, log_delayed); mysql_bin_log.write(&e); } } } - if (using_transactions) + if (transactional_table) error=ha_autocommit_or_rollback(thd,error); DBUG_RETURN(error); } diff --git a/sql/sql_manager.cc b/sql/sql_manager.cc index 13cac83fc3f..0af6a80d4c2 100644 --- a/sql/sql_manager.cc +++ b/sql/sql_manager.cc @@ -32,7 +32,7 @@ pthread_t manager_thread; pthread_mutex_t LOCK_manager; pthread_cond_t COND_manager; -pthread_handler_decl(handle_manager,arg __attribute__((unused))) +extern "C" pthread_handler_decl(handle_manager,arg __attribute__((unused))) { int error = 0; ulong status; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index aebccf7a39e..4816a0539f3 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -98,7 +98,17 @@ static void init_signals(void) } #endif -inline bool end_active_trans(THD *thd) +static void unlock_locked_tables(THD *thd) +{ + if (thd->locked_tables) + { + thd->lock=thd->locked_tables; + thd->locked_tables=0; // Will be automaticly closed + close_thread_tables(thd); // Free tables + } +} + +static bool end_active_trans(THD *thd) { int error=0; if (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN | @@ -257,14 +267,14 @@ static bool check_user(THD *thd,enum_server_command command, const char *user, started with corresponding variable that is greater then 0. */ -static byte* get_key_conn(user_conn *buff, uint *length, - my_bool not_used __attribute__((unused))) +extern "C" byte *get_key_conn(user_conn *buff, uint *length, + my_bool not_used __attribute__((unused))) { *length=buff->len; return (byte*) buff->user; } -static void free_user(struct user_conn *uc) +extern "C" void free_user(struct user_conn *uc) { my_free((char*) uc,MYF(0)); } @@ -273,7 +283,7 @@ void init_max_user_conn(void) { (void) hash_init(&hash_user_connections,system_charset_info,max_connections, 0,0, - (hash_get_key) get_key_conn, (void (*)(void*)) free_user, + (hash_get_key) get_key_conn, (hash_free_key) free_user, 0); } @@ -552,7 +562,13 @@ check_connections(THD *thd) { /* Do the SSL layering. */ DBUG_PRINT("info", ("IO layer change in progress...")); - sslaccept(ssl_acceptor_fd, net->vio, thd->variables.net_wait_timeout); + if (sslaccept(ssl_acceptor_fd, net->vio, thd->variables.net_wait_timeout)) + { + DBUG_PRINT("error", ("Failed to read user information (pkt_len= %lu)", + pkt_len)); + inc_host_errors(&thd->remote.sin_addr); + return(ER_HANDSHAKE_ERROR); + } DBUG_PRINT("info", ("Reading user information over SSL layer")); if ((pkt_len=my_net_read(net)) == packet_error || pkt_len < NORMAL_HANDSHAKE_SIZE) @@ -690,7 +706,7 @@ pthread_handler_decl(handle_one_connection,arg) (net->last_errno ? ER(net->last_errno) : ER(ER_UNKNOWN_ERROR))); send_error(thd,net->last_errno,NullS); - thread_safe_increment(aborted_threads,&LOCK_status); + statistic_increment(aborted_threads,&LOCK_status); } end_thread: @@ -711,7 +727,7 @@ end_thread: Used when creating the initial grant tables */ -pthread_handler_decl(handle_bootstrap,arg) +extern "C" pthread_handler_decl(handle_bootstrap,arg) { THD *thd=(THD*) arg; FILE *file=bootstrap_file; @@ -903,7 +919,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, thd->lex.select_lex.options=0; // We store status here switch (command) { case COM_INIT_DB: - thread_safe_increment(com_stat[SQLCOM_CHANGE_DB],&LOCK_status); + statistic_increment(com_stat[SQLCOM_CHANGE_DB],&LOCK_status); if (!mysql_change_db(thd,packet)) mysql_log.write(thd,command,"%s",thd->db); break; @@ -915,7 +931,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, } case COM_TABLE_DUMP: { - thread_safe_increment(com_other, &LOCK_status); + statistic_increment(com_other, &LOCK_status); slow_command = TRUE; uint db_len = *(uchar*)packet; uint tbl_len = *(uchar*)(packet + db_len + 1); @@ -932,7 +948,10 @@ bool dispatch_command(enum enum_server_command command, THD *thd, } case COM_CHANGE_USER: { - thread_safe_increment(com_other,&LOCK_status); + thd->change_user(); + clear_error_message(thd); // If errors from rollback + + statistic_increment(com_other,&LOCK_status); char *user= (char*) packet; char *passwd= strend(user)+1; char *db= strend(passwd)+1; @@ -1005,7 +1024,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, { char *fields; TABLE_LIST table_list; - thread_safe_increment(com_stat[SQLCOM_SHOW_FIELDS],&LOCK_status); + statistic_increment(com_stat[SQLCOM_SHOW_FIELDS],&LOCK_status); bzero((char*) &table_list,sizeof(table_list)); if (!(table_list.db=thd->db)) { @@ -1040,7 +1059,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, case COM_CREATE_DB: // QQ: To be removed { - thread_safe_increment(com_stat[SQLCOM_CREATE_DB],&LOCK_status); + statistic_increment(com_stat[SQLCOM_CREATE_DB],&LOCK_status); char *db=thd->strdup(packet); // null test to handle EOM if (!db || !strip_sp(db) || check_db_name(db)) @@ -1058,7 +1077,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, } case COM_DROP_DB: // QQ: To be removed { - thread_safe_increment(com_stat[SQLCOM_DROP_DB],&LOCK_status); + statistic_increment(com_stat[SQLCOM_DROP_DB],&LOCK_status); char *db=thd->strdup(packet); // null test to handle EOM if (!db || !strip_sp(db) || check_db_name(db)) @@ -1079,7 +1098,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, } case COM_BINLOG_DUMP: { - thread_safe_increment(com_other,&LOCK_status); + statistic_increment(com_other,&LOCK_status); slow_command = TRUE; if (check_global_access(thd, REPL_SLAVE_ACL)) break; @@ -1103,7 +1122,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, } case COM_REFRESH: { - thread_safe_increment(com_stat[SQLCOM_FLUSH],&LOCK_status); + statistic_increment(com_stat[SQLCOM_FLUSH],&LOCK_status); ulong options= (ulong) (uchar) packet[0]; if (check_global_access(thd,RELOAD_ACL)) break; @@ -1115,7 +1134,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, break; } case COM_SHUTDOWN: - thread_safe_increment(com_other,&LOCK_status); + statistic_increment(com_other,&LOCK_status); if (check_global_access(thd,SHUTDOWN_ACL)) break; /* purecov: inspected */ DBUG_PRINT("quit",("Got shutdown command")); @@ -1138,7 +1157,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, case COM_STATISTICS: { mysql_log.write(thd,command,NullS); - thread_safe_increment(com_stat[SQLCOM_SHOW_STATUS],&LOCK_status); + statistic_increment(com_stat[SQLCOM_SHOW_STATUS],&LOCK_status); char buff[200]; ulong uptime = (ulong) (thd->start_time - start_time); sprintf((char*) buff, @@ -1157,11 +1176,11 @@ bool dispatch_command(enum enum_server_command command, THD *thd, break; } case COM_PING: - thread_safe_increment(com_other,&LOCK_status); + statistic_increment(com_other,&LOCK_status); send_ok(thd); // Tell client we are alive break; case COM_PROCESS_INFO: - thread_safe_increment(com_stat[SQLCOM_SHOW_PROCESSLIST],&LOCK_status); + statistic_increment(com_stat[SQLCOM_SHOW_PROCESSLIST],&LOCK_status); if (!thd->priv_user[0] && check_global_access(thd,PROCESS_ACL)) break; mysql_log.write(thd,command,NullS); @@ -1170,13 +1189,13 @@ bool dispatch_command(enum enum_server_command command, THD *thd, break; case COM_PROCESS_KILL: { - thread_safe_increment(com_stat[SQLCOM_KILL],&LOCK_status); + statistic_increment(com_stat[SQLCOM_KILL],&LOCK_status); ulong id=(ulong) uint4korr(packet); kill_one_thread(thd,id); break; } case COM_DEBUG: - thread_safe_increment(com_other,&LOCK_status); + statistic_increment(com_other,&LOCK_status); if (check_global_access(thd, SUPER_ACL)) break; /* purecov: inspected */ mysql_print_status(thd); @@ -1355,7 +1374,7 @@ mysql_execute_command(THD *thd) !tables_ok(thd,tables))) DBUG_VOID_RETURN; - thread_safe_increment(com_stat[lex->sql_command],&LOCK_status); + statistic_increment(com_stat[lex->sql_command],&LOCK_status); switch (lex->sql_command) { case SQLCOM_SELECT: { @@ -1413,6 +1432,8 @@ mysql_execute_command(THD *thd) Normal select: Change lock if we are using SELECT HIGH PRIORITY, FOR UPDATE or IN SHARE MODE + + TODO: Delete the following loop when locks is set by sql_yacc */ TABLE_LIST *table; for (table = tables ; table ; table=table->next) @@ -1642,6 +1663,7 @@ mysql_execute_command(THD *thd) TABLE_LIST *table; if (check_table_access(thd, SELECT_ACL, tables->next)) goto error; // Error message is given + /* TODO: Delete the following loop when locks is set by sql_yacc */ for (table = tables->next ; table ; table=table->next) table->lock_type= lex->lock_option; } @@ -1711,7 +1733,7 @@ mysql_execute_command(THD *thd) #else { ulong priv=0; - if (lex->name && strlen(lex->name) > NAME_LEN) + if (lex->name && (!lex->name[0] || strlen(lex->name) > NAME_LEN)) { net_printf(thd,ER_WRONG_TABLE_NAME,lex->name); res=0; @@ -1885,18 +1907,13 @@ mysql_execute_command(THD *thd) } if (select_lex->table_list.elements == 1) { - res = mysql_update(thd,tables, - select_lex->item_list, - lex->value_list, - select_lex->where, - (ORDER *) select_lex->order_list.first, - select_lex->select_limit, - lex->duplicates, - lex->lock_option); - -#ifdef DELETE_ITEMS - delete select_lex->where; -#endif + res= mysql_update(thd,tables, + select_lex->item_list, + lex->value_list, + select_lex->where, + (ORDER *) select_lex->order_list.first, + select_lex->select_limit, + lex->duplicates); } else { @@ -1906,11 +1923,8 @@ mysql_execute_command(THD *thd) const char *msg=0; lex->sql_command=SQLCOM_MULTI_UPDATE; - for (auxi=(TABLE_LIST*) tables, table_count=0 ; auxi ; auxi=auxi->next) - { + for (auxi= (TABLE_LIST*) tables, table_count=0 ; auxi ; auxi=auxi->next) table_count++; - auxi->lock_type=TL_WRITE; - } if (select_lex->order_list.elements) msg="ORDER BY"; @@ -1932,8 +1946,7 @@ mysql_execute_command(THD *thd) !setup_fields(thd,tables,lex->value_list,0,0,0) && !thd->fatal_error && (result=new multi_update(thd,tables,select_lex->item_list, - lex->duplicates, lex->lock_option, - table_count))) + lex->duplicates, table_count))) { List <Item> total_list; List_iterator <Item> field_list(select_lex->item_list); @@ -1964,8 +1977,7 @@ mysql_execute_command(THD *thd) if (grant_option && check_grant(thd,INSERT_ACL,tables)) goto error; res = mysql_insert(thd,tables,lex->field_list,lex->many_values, - lex->duplicates, - lex->lock_option); + lex->duplicates); break; case SQLCOM_REPLACE: if (check_access(thd,INSERT_ACL | DELETE_ACL, @@ -1976,8 +1988,7 @@ mysql_execute_command(THD *thd) goto error; res = mysql_insert(thd,tables,lex->field_list,lex->many_values, - DUP_REPLACE, - lex->lock_option); + DUP_REPLACE); break; case SQLCOM_REPLACE_SELECT: case SQLCOM_INSERT_SELECT: @@ -2012,8 +2023,8 @@ mysql_execute_command(THD *thd) net_printf(thd,ER_INSERT_TABLE_USED,tables->real_name); DBUG_VOID_RETURN; } - tables->lock_type=TL_WRITE; // update first table { + /* TODO: Delete the following loop when locks is set by sql_yacc */ TABLE_LIST *table; for (table = tables->next ; table ; table=table->next) table->lock_type= lex->lock_option; @@ -2056,8 +2067,7 @@ mysql_execute_command(THD *thd) tables->grant.want_privilege=(SELECT_ACL & ~tables->grant.privilege); res = mysql_delete(thd,tables, select_lex->where, (ORDER*) select_lex->order_list.first, - select_lex->select_limit, lex->lock_option, - select_lex->options); + select_lex->select_limit, select_lex->options); break; } case SQLCOM_DELETE_MULTI: @@ -2093,7 +2103,7 @@ mysql_execute_command(THD *thd) net_printf(thd,ER_NONUNIQ_TABLE,auxi->real_name); goto error; } - auxi->lock_type=walk->lock_type=TL_WRITE; + walk->lock_type= auxi->lock_type; auxi->table_list= walk; // Remember corresponding table } if (add_item_to_list(new Item_null())) @@ -2108,7 +2118,6 @@ mysql_execute_command(THD *thd) for (auxi=(TABLE_LIST*) aux_tables ; auxi ; auxi=auxi->next) auxi->table= auxi->table_list->table; if (!thd->fatal_error && (result= new multi_delete(thd,aux_tables, - lex->lock_option, table_count))) { res= mysql_select(thd,tables,select_lex->item_list, @@ -2314,11 +2323,7 @@ mysql_execute_command(THD *thd) send_ok(thd); break; case SQLCOM_UNLOCK_TABLES: - if (thd->locked_tables) - { - thd->lock=thd->locked_tables; - thd->locked_tables=0; // Will be automaticly closed - } + unlock_locked_tables(thd); if (thd->options & OPTION_TABLE_LOCK) { end_active_trans(thd); @@ -2329,12 +2334,7 @@ mysql_execute_command(THD *thd) send_ok(thd); break; case SQLCOM_LOCK_TABLES: - if (thd->locked_tables) - { - thd->lock=thd->locked_tables; - thd->locked_tables=0; // Will be automaticly closed - close_thread_tables(thd); - } + unlock_locked_tables(thd); if (check_db_used(thd,tables) || end_active_trans(thd)) goto error; if (check_table_access(thd, LOCK_TABLES_ACL | SELECT_ACL, tables)) @@ -2484,7 +2484,7 @@ mysql_execute_command(THD *thd) mysql_update_log.write(thd, thd->query, thd->query_length); if (mysql_bin_log.is_open()) { - Query_log_event qinfo(thd, thd->query, thd->query_length); + Query_log_event qinfo(thd, thd->query, thd->query_length, 0); mysql_bin_log.write(&qinfo); } } @@ -2504,7 +2504,7 @@ mysql_execute_command(THD *thd) mysql_update_log.write(thd, thd->query, thd->query_length); if (mysql_bin_log.is_open()) { - Query_log_event qinfo(thd, thd->query, thd->query_length); + Query_log_event qinfo(thd, thd->query, thd->query_length, 0); mysql_bin_log.write(&qinfo); } if (mqh_used && lex->sql_command == SQLCOM_GRANT) @@ -2874,7 +2874,7 @@ mysql_init_query(THD *thd) thd->total_warn_count=0; // Warnings for this query thd->last_insert_id_used= thd->query_start_used= thd->insert_id_used=0; thd->sent_row_count= thd->examined_row_count= 0; - thd->fatal_error= thd->rand_used=0; + thd->fatal_error= thd->rand_used= 0; thd->safe_to_cache_query= 1; thd->possible_loops= 0; DBUG_VOID_RETURN; @@ -3476,14 +3476,50 @@ TABLE_LIST *st_select_lex::add_table_to_list(Table_ident *table, } +/* + Set lock for all tables in current select level + + SYNOPSIS: + set_lock_for_tables() + lock_type Lock to set for tables + + NOTE: + If lock is a write lock, then tables->updating is set 1 + This is to get tables_ok to know that the table is updated by the + query +*/ + +void set_lock_for_tables(thr_lock_type lock_type) +{ + THD *thd=current_thd; + bool for_update= lock_type >= TL_READ_NO_INSERT; + DBUG_ENTER("set_lock_for_tables"); + DBUG_PRINT("enter", ("lock_type: %d for_update: %d", lock_type, + for_update)); + + for (TABLE_LIST *tables= (TABLE_LIST*) thd->lex.select->table_list.first ; + tables ; + tables=tables->next) + { + tables->lock_type= lock_type; + tables->updating= for_update; + } + DBUG_VOID_RETURN; +} + + void add_join_on(TABLE_LIST *b,Item *expr) { - if (!b->on_expr) - b->on_expr=expr; - else + if (expr) { - // This only happens if you have both a right and left join - b->on_expr=new Item_cond_and(b->on_expr,expr); + if (!b->on_expr) + b->on_expr=expr; + else + { + // This only happens if you have both a right and left join + b->on_expr=new Item_cond_and(b->on_expr,expr); + } + b->on_expr->top_level_item(); } } @@ -3511,7 +3547,7 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables) if (options & REFRESH_GRANT) { acl_reload(thd); - grant_reload(); + grant_reload(thd); if (mqh_used) reset_mqh(thd,(LEX_USER *) NULL,true); } diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc index a9ab1776e19..5b0ec2ec843 100644 --- a/sql/sql_rename.cc +++ b/sql/sql_rename.cc @@ -94,7 +94,7 @@ end: mysql_update_log.write(thd,thd->query,thd->query_length); if (mysql_bin_log.is_open()) { - Query_log_event qinfo(thd, thd->query, thd->query_length); + Query_log_event qinfo(thd, thd->query, thd->query_length, 0); mysql_bin_log.write(&qinfo); } send_ok(thd); diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 93545d10268..23951cec29f 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -941,7 +941,7 @@ int show_binlog_events(THD* thd) if (mysql_bin_log.is_open()) { LEX_MASTER_INFO *lex_mi = &thd->lex.mi; - uint event_count, limit_start, limit_end; + ha_rows event_count, limit_start, limit_end; my_off_t pos = lex_mi->pos; char search_file_name[FN_REFLEN], *name; const char *log_file_name = lex_mi->log_file_name; @@ -1133,7 +1133,8 @@ int log_loaded_block(IO_CACHE* file) lf_info->last_pos_in_file = file->pos_in_file; if (lf_info->wrote_create_file) { - Append_block_log_event a(lf_info->thd, buffer, block_len); + Append_block_log_event a(lf_info->thd, buffer, block_len, + lf_info->log_delayed); mysql_bin_log.write(&a); } else @@ -1141,7 +1142,7 @@ int log_loaded_block(IO_CACHE* file) Create_file_log_event c(lf_info->thd,lf_info->ex,lf_info->db, lf_info->table_name, *lf_info->fields, lf_info->handle_dup, buffer, - block_len); + block_len, lf_info->log_delayed); mysql_bin_log.write(&c); lf_info->wrote_create_file = 1; DBUG_SYNC_POINT("debug_lock.created_file_event",10); diff --git a/sql/sql_repl.h b/sql/sql_repl.h index 197fd03ec7c..15435382b08 100644 --- a/sql/sql_repl.h +++ b/sql/sql_repl.h @@ -43,13 +43,13 @@ int check_binlog_magic(IO_CACHE* log, const char** errmsg); typedef struct st_load_file_info { THD* thd; + my_off_t last_pos_in_file; sql_exchange* ex; List <Item> *fields; enum enum_duplicates handle_dup; char* db; char* table_name; - bool wrote_create_file; - my_off_t last_pos_in_file; + bool wrote_create_file, log_delayed; } LOAD_FILE_INFO; int log_loaded_block(IO_CACHE* file); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 05551980309..20b000392df 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -367,6 +367,7 @@ JOIN::optimize() { conds->fix_fields(thd, tables_list, &conds); conds->change_ref_to_fields(thd, tables_list); + conds->top_level_item(); having= 0; } } @@ -960,6 +961,7 @@ JOIN::exec() sort_table_cond))) DBUG_VOID_RETURN; table->select_cond=table->select->cond; + table->select_cond->top_level_item(); DBUG_EXECUTE("where",print_where(table->select->cond, "select and having");); having_list= make_cond_for_table(having_list, ~ (table_map) 0, @@ -1432,7 +1434,7 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds, select->quick=0; if (records != HA_POS_ERROR) { - s->found_records=records; + s->records=s->found_records=records; s->read_time= (ha_rows) (s->quick ? s->quick->read_time : 0.0); } } @@ -1965,7 +1967,7 @@ static void find_best(JOIN *join,table_map rest_tables,uint idx,double record_count, double read_time) { - ulong rec; + ha_rows rec; double tmp; THD *thd= join->thd; @@ -2158,7 +2160,7 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count, records This gives the formula: records= (x * (b-a) + a*c-b)/(c-1) - + b = records matched by whole key a = records matched by first key part (10% of all records?) c = number of key parts in key @@ -2227,7 +2229,7 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count, { // Check full join if (s->on_expr) { - tmp=s->found_records; // Can't use read cache + tmp=rows2double(s->found_records); // Can't use read cache } else { @@ -2246,11 +2248,11 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count, will ensure that this will be used */ best=tmp; - records=s->found_records; + records= rows2double(s->found_records); best_key=0; } } - join->positions[idx].records_read=(double) records; + join->positions[idx].records_read= records; join->positions[idx].key=best_key; join->positions[idx].table= s; if (!best_key && idx == join->const_tables && @@ -2587,7 +2589,7 @@ bool store_val_in_field(Field *field,Item *item) { THD *thd=current_thd; - ulong cuted_fields=thd->cuted_fields; + ha_rows cuted_fields=thd->cuted_fields; thd->count_cuted_fields=1; (void) item->save_in_field(field); thd->count_cuted_fields=0; @@ -2675,7 +2677,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) use_quick_range=1; tab->use_quick=1; tab->ref.key_parts=0; // Don't use ref key. - join->best_positions[i].records_read=tab->quick->records; + join->best_positions[i].records_read= rows2double(tab->quick->records); } COND *tmp=make_cond_for_table(cond,used_tables,current_map); @@ -3948,7 +3950,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, *blob_field= 0; // End marker /* If result table is small; use a heap */ - if (blob_count || using_unique_constraint || group_null_items || + if (blob_count || using_unique_constraint || (select_options & (OPTION_BIG_TABLES | SELECT_SMALL_RESULT)) == OPTION_BIG_TABLES) { @@ -5547,6 +5549,8 @@ end_write_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), } else { + if (end_of_records) + DBUG_RETURN(0); join->first_record=1; VOID(test_if_group_changed(join->group_fields)); } @@ -5616,6 +5620,7 @@ make_cond_for_table(COND *cond,table_map tables,table_map used_table) { if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC) { + /* Create new top level AND item */ Item_cond_and *new_cond=new Item_cond_and; if (!new_cond) return (COND*) 0; // OOM /* purecov: inspected */ @@ -5653,6 +5658,7 @@ make_cond_for_table(COND *cond,table_map tables,table_map used_table) new_cond->argument_list()->push_back(fix); } new_cond->used_tables_cache=((Item_cond_or*) cond)->used_tables_cache; + new_cond->top_level_item(); return new_cond; } } @@ -6004,6 +6010,7 @@ static bool fix_having(JOIN *join, Item **having) sort_table_cond))) return 1; table->select_cond=table->select->cond; + table->select_cond->top_level_item(); DBUG_EXECUTE("where",print_where(table->select_cond, "select and having");); *having=make_cond_for_table(*having,~ (table_map) 0,~used_tables); @@ -7432,56 +7439,32 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, { if (tab->use_quick == 2) { - sprintf(buff_ptr,"range checked for each record (index map: %u)", + sprintf(buff_ptr,"; Range checked for each record (index map: %u)", tab->keys); buff_ptr=strend(buff_ptr); } else - buff_ptr=strmov(buff_ptr,"where used"); + buff_ptr=strmov(buff_ptr,"; Using where"); } if (key_read) - { - if (buff != buff_ptr) - { - buff_ptr[0]=';' ; buff_ptr[1]=' '; buff_ptr+=2; - } - buff_ptr=strmov(buff_ptr,"Using index"); - } + buff_ptr= strmov(buff_ptr,"; Using index"); if (table->reginfo.not_exists_optimize) - { - if (buff != buff_ptr) - { - buff_ptr[0]=';' ; buff_ptr[1]=' '; buff_ptr+=2; - } - buff_ptr=strmov(buff_ptr,"Not exists"); - } + buff_ptr= strmov(buff_ptr,"; Not exists"); if (need_tmp_table) { need_tmp_table=0; - if (buff != buff_ptr) - { - buff_ptr[0]=';' ; buff_ptr[1]=' '; buff_ptr+=2; - } - buff_ptr=strmov(buff_ptr,"Using temporary"); + buff_ptr= strmov(buff_ptr,"; Using temporary"); } if (need_order) { need_order=0; - if (buff != buff_ptr) - { - buff_ptr[0]=';' ; buff_ptr[1]=' '; buff_ptr+=2; - } - buff_ptr=strmov(buff_ptr,"Using filesort"); + buff_ptr= strmov(buff_ptr,"; Using filesort"); } if (distinct & test_all_bits(used_tables,thd->used_tables)) - { - if (buff != buff_ptr) - { - buff_ptr[0]=';' ; buff_ptr[1]=' '; buff_ptr+=2; - } - buff_ptr=strmov(buff_ptr,"Distinct"); - } - item_list.push_back(new Item_string(buff,(uint) (buff_ptr - buff), + buff_ptr= strmov(buff_ptr,"; Distinct"); + if (buff_ptr == buff) + buff_ptr+= 2; // Skip inital "; " + item_list.push_back(new Item_string(buff+2,(uint) (buff_ptr - buff)-2, default_charset_info)); // For next iteration used_tables|=table->map; diff --git a/sql/sql_show.cc b/sql/sql_show.cc index c039f84dc77..ebf5b210d6c 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -889,7 +889,7 @@ mysqld_show_keys(THD *thd, TABLE_LIST *table_list) field_list.push_back(new Item_empty_string("Column_name",NAME_LEN)); field_list.push_back(item=new Item_empty_string("Collation",1)); item->maybe_null=1; - field_list.push_back(item=new Item_int("Cardinality",0,11)); + field_list.push_back(item=new Item_int("Cardinality",0,21)); item->maybe_null=1; field_list.push_back(item=new Item_int("Sub_part",0,3)); item->maybe_null=1; @@ -930,8 +930,8 @@ mysqld_show_keys(THD *thd, TABLE_LIST *table_list) KEY *key=table->key_info+i; if (key->rec_per_key[j]) { - ulong records=(table->file->records / key->rec_per_key[j]); - end=int10_to_str((long) records, buff, 10); + ha_rows records=(table->file->records / key->rec_per_key[j]); + end=longlong10_to_str((longlong) records, buff, 10); net_store_data(packet,convert,buff,(uint) (end-buff)); } else diff --git a/sql/sql_table.cc b/sql/sql_table.cc index abb4cf8d3f9..00077bda39f 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -110,6 +110,17 @@ int mysql_rm_table_part2_with_lock(THD *thd, return error; } +/* + TODO: + When logging to the binary log, we should log + tmp_tables and transactional tables as separate statements if we + are in a transaction; This is needed to get these tables into the + cached binary log that is only written on COMMIT. + + The current code only writes DROP statements that only uses temporary + tables to the cache binary log. This should be ok on most cases, but + not all. +*/ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, bool dont_log_query) @@ -119,7 +130,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, String wrong_tables; db_type table_type; int error; - bool some_tables_deleted=0; + bool some_tables_deleted=0, tmp_table_deleted=0; DBUG_ENTER("mysql_rm_table_part2"); for (table=tables ; table ; table=table->next) @@ -127,7 +138,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, char *db=table->db ? table->db : thd->db; if (!close_temporary_table(thd, db, table->real_name)) { - some_tables_deleted=1; // Log query + tmp_table_deleted=1; continue; // removed temporary table } @@ -143,8 +154,8 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, DBUG_RETURN(-1); /* remove form file and isam files */ - (void) sprintf(path,"%s/%s/%s%s",mysql_data_home,db,table->real_name, - reg_ext); + strxmov(path, mysql_data_home, "/", db, "/", table->real_name, reg_ext, + NullS); (void) unpack_filename(path,path); error=0; @@ -177,7 +188,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, wrong_tables.append(String(table->real_name,default_charset_info)); } } - if (some_tables_deleted) + if (some_tables_deleted || tmp_table_deleted) { query_cache_invalidate3(thd, tables, 0); if (!dont_log_query) @@ -185,7 +196,8 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, mysql_update_log.write(thd, thd->query,thd->query_length); if (mysql_bin_log.is_open()) { - Query_log_event qinfo(thd, thd->query, thd->query_length); + Query_log_event qinfo(thd, thd->query, thd->query_length, + tmp_table_deleted && !some_tables_deleted); mysql_bin_log.write(&qinfo); } } @@ -271,7 +283,8 @@ static int sort_keys(KEY *a, KEY *b) create_info Create information (like MAX_ROWS) fields List of fields to create keys List of keys to create - tmp_table Set to 1 if this is a temporary table + tmp_table Set to 1 if this is an internal temporary table + (From ALTER TABLE) no_log Don't log the query to binary log. DESCRIPTION @@ -784,7 +797,6 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, thd->proc_info="creating table"; - create_info->create_statement = thd->query; create_info->table_options=db_options; if (rea_create_table(thd, path, create_info, fields, key_count, key_info_buffer)) @@ -792,16 +804,6 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, /* my_error(ER_CANT_CREATE_TABLE,MYF(0),table_name,my_errno); */ goto end; } - if (!tmp_table && !no_log) - { - // Must be written before unlock - mysql_update_log.write(thd,thd->query, thd->query_length); - if (mysql_bin_log.is_open()) - { - Query_log_event qinfo(thd, thd->query, thd->query_length); - mysql_bin_log.write(&qinfo); - } - } if (create_info->options & HA_LEX_CREATE_TMP_TABLE) { /* Open table and put in temporary table list */ @@ -811,6 +813,18 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, goto end; } } + if (!tmp_table && !no_log) + { + // Must be written before unlock + mysql_update_log.write(thd,thd->query, thd->query_length); + if (mysql_bin_log.is_open()) + { + Query_log_event qinfo(thd, thd->query, thd->query_length, + test(create_info->options & + HA_LEX_CREATE_TMP_TABLE)); + mysql_bin_log.write(&qinfo); + } + } error=0; end: VOID(pthread_mutex_unlock(&LOCK_open)); @@ -1255,8 +1269,13 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables, switch (result_code) { case HA_ADMIN_NOT_IMPLEMENTED: - net_store_data(packet, "error"); - net_store_data(packet, ER(ER_CHECK_NOT_IMPLEMENTED)); + { + char buf[ERRMSGSIZE+20]; + my_snprintf(buf, ERRMSGSIZE, + ER(ER_CHECK_NOT_IMPLEMENTED), operator_name); + net_store_data(packet, "error"); + net_store_data(packet, buf); + } break; case HA_ADMIN_OK: @@ -1511,7 +1530,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, mysql_update_log.write(thd, thd->query, thd->query_length); if (mysql_bin_log.is_open()) { - Query_log_event qinfo(thd, thd->query, thd->query_length); + Query_log_event qinfo(thd, thd->query, thd->query_length, 0); mysql_bin_log.write(&qinfo); } send_ok(thd); @@ -1887,7 +1906,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, mysql_update_log.write(thd, thd->query,thd->query_length); if (mysql_bin_log.is_open()) { - Query_log_event qinfo(thd, thd->query, thd->query_length); + Query_log_event qinfo(thd, thd->query, thd->query_length, 0); mysql_bin_log.write(&qinfo); } goto end_temporary; @@ -2016,7 +2035,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, mysql_update_log.write(thd, thd->query,thd->query_length); if (mysql_bin_log.is_open()) { - Query_log_event qinfo(thd, thd->query, thd->query_length); + Query_log_event qinfo(thd, thd->query, thd->query_length, 0); mysql_bin_log.write(&qinfo); } VOID(pthread_cond_broadcast(&COND_refresh)); diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc index f45eca0b65f..35e33caf572 100644 --- a/sql/sql_udf.cc +++ b/sql/sql_udf.cc @@ -98,8 +98,8 @@ static void init_syms(udf_func *tmp) } } -static byte* get_hash_key(const byte *buff,uint *length, - my_bool not_used __attribute__((unused))) +extern "C" byte* get_hash_key(const byte *buff,uint *length, + my_bool not_used __attribute__((unused))) { udf_func *udf=(udf_func*) buff; *length=(uint) udf->name_length; diff --git a/sql/sql_update.cc b/sql/sql_update.cc index be69935a49c..73343ab1a50 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -50,11 +50,10 @@ int mysql_update(THD *thd, COND *conds, ORDER *order, ha_rows limit, - enum enum_duplicates handle_duplicates, - thr_lock_type lock_type) + enum enum_duplicates handle_duplicates) { - bool using_limit=limit != HA_POS_ERROR; - bool used_key_is_modified, using_transactions; + bool using_limit=limit != HA_POS_ERROR, safe_update= thd->options & OPTION_SAFE_UPDATES; + bool used_key_is_modified, transactional_table, log_delayed; int error=0; uint save_time_stamp, used_index, want_privilege; ulong query_id=thd->query_id, timestamp_query_id; @@ -66,7 +65,7 @@ int mysql_update(THD *thd, LINT_INIT(used_index); LINT_INIT(timestamp_query_id); - if (!(table = open_ltable(thd,table_list,lock_type))) + if (!(table = open_ltable(thd,table_list,table_list->lock_type))) DBUG_RETURN(-1); /* purecov: inspected */ save_time_stamp=table->time_stamp; table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK); @@ -117,9 +116,7 @@ int mysql_update(THD *thd, table->used_keys=0; select=make_select(table,0,0,conds,&error); if (error || - (select && select->check_quick(test(thd->options & OPTION_SAFE_UPDATES), - limit)) || - !limit) + (select && select->check_quick(safe_update, limit)) || !limit) { delete select; table->time_stamp=save_time_stamp; // Restore timestamp pointer @@ -134,7 +131,7 @@ int mysql_update(THD *thd, if (!table->quick_keys) { thd->lex.select_lex.options|=QUERY_NO_INDEX_USED; - if ((thd->options & OPTION_SAFE_UPDATES) && limit == HA_POS_ERROR) + if (safe_update && !using_limit) { delete select; table->time_stamp=save_time_stamp; @@ -301,23 +298,34 @@ int mysql_update(THD *thd, thd->proc_info="end"; VOID(table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY)); table->time_stamp=save_time_stamp; // Restore auto timestamp pointer - using_transactions=table->file->has_transactions(); - if (updated && (error <= 0 || !using_transactions)) + transactional_table= table->file->has_transactions(); + log_delayed= (transactional_table || table->tmp_table); + if (updated && (error <= 0 || !transactional_table)) { mysql_update_log.write(thd,thd->query,thd->query_length); if (mysql_bin_log.is_open()) { Query_log_event qinfo(thd, thd->query, thd->query_length, - using_transactions); - if (mysql_bin_log.write(&qinfo) && using_transactions) - error=1; + log_delayed); + if (mysql_bin_log.write(&qinfo) && transactional_table) + error=1; // Rollback update } - if (!using_transactions) + if (!log_delayed) thd->options|=OPTION_STATUS_NO_TRANS_UPDATE; } - if (using_transactions && ha_autocommit_or_rollback(thd, error >= 0)) - error=1; - if (updated) + if (transactional_table) + { + if (ha_autocommit_or_rollback(thd, error >= 0)) + error=1; + } + /* + Only invalidate the query cache if something changed or if we + didn't commit the transacion (query cache is automaticly + invalidated on commit) + */ + if (updated && + (!transactional_table || + thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) { query_cache_invalidate3(thd, table_list, 1); } @@ -349,10 +357,12 @@ int mysql_update(THD *thd, Update multiple tables from join ***************************************************************************/ -multi_update::multi_update(THD *thd_arg, TABLE_LIST *ut, List<Item> &fs, - enum enum_duplicates handle_duplicates, thr_lock_type lock_option_arg, uint num) - : update_tables (ut), thd(thd_arg), updated(0), found(0), fields(fs), lock_option(lock_option_arg), - dupl(handle_duplicates), num_of_tables(num), num_fields(0), num_updated(0) , error(0), do_update(false) +multi_update::multi_update(THD *thd_arg, TABLE_LIST *ut, List<Item> &fs, + enum enum_duplicates handle_duplicates, + uint num) + : update_tables (ut), thd(thd_arg), updated(0), found(0), fields(fs), + dupl(handle_duplicates), num_of_tables(num), num_fields(0), num_updated(0), + error(0), do_update(false) { save_time_stamps = (uint *) sql_calloc (sizeof(uint) * num_of_tables); tmp_tables = (TABLE **)NULL; @@ -695,7 +705,7 @@ void multi_update::send_error(uint errcode,const char *err) int multi_update::do_updates (bool from_send_error) { - int error = 0, counter = 0; + int local_error= 0, counter= 0; if (from_send_error) { @@ -720,7 +730,7 @@ int multi_update::do_updates (bool from_send_error) TABLE *tmp_table=tmp_tables[counter]; if (tmp_table->file->extra(HA_EXTRA_NO_CACHE)) { - error=1; + local_error=1; break; } List<Item> list; @@ -736,35 +746,36 @@ int multi_update::do_updates (bool from_send_error) tmp_table->used_keys&=field->part_of_key; } tmp_table->used_fields=tmp_table->fields; - error=0; list.pop(); // we get position some other way ... - error = tmp_table->file->rnd_init(1); - if (error) - return error; - while (!(error=tmp_table->file->rnd_next(tmp_table->record[0])) && + local_error=0; + list.pop(); // we get position some other way ... + local_error = tmp_table->file->rnd_init(1); + if (local_error) + return local_error; + while (!(local_error=tmp_table->file->rnd_next(tmp_table->record[0])) && (!thd->killed || from_send_error || not_trans_safe)) { found++; - error= table->file->rnd_pos(table->record[0], - (byte*) (*(tmp_table->field))->ptr); - if (error) - return error; + local_error= table->file->rnd_pos(table->record[0], + (byte*) (*(tmp_table->field))->ptr); + if (local_error) + return local_error; table->status|= STATUS_UPDATED; store_record(table,1); - error= fill_record(*fields_by_tables[counter + 1],list) || - /* compare_record(table, query_id) || */ - table->file->update_row(table->record[1],table->record[0]); - if (error) + local_error= (fill_record(*fields_by_tables[counter + 1],list) || + /* compare_record(table, query_id) || */ + table->file->update_row(table->record[1],table->record[0])); + if (local_error) { - table->file->print_error(error,MYF(0)); + table->file->print_error(local_error,MYF(0)); break; } else updated++; } - if (error == HA_ERR_END_OF_FILE) - error = 0; + if (local_error == HA_ERR_END_OF_FILE) + local_error = 0; } - return error; + return local_error; } @@ -775,18 +786,18 @@ bool multi_update::send_eof() thd->proc_info="updating the reference tables"; /* Does updates for the last n - 1 tables, returns 0 if ok */ - int error = (num_updated) ? do_updates(false) : 0; /* do_updates returns 0 if success */ + int local_error = (num_updated) ? do_updates(false) : 0; /* reset used flags */ #ifndef NOT_USED update_tables->table->no_keyread=0; #endif - if (error == -1) - error = 0; - thd->proc_info="end"; - //TODO error should be sent at the query processing end - if (error) - send_error(error,"An error occured in multi-table update"); + if (local_error == -1) + local_error= 0; + thd->proc_info= "end"; + // TODO: Error should be sent at the query processing end + if (local_error) + send_error(local_error, "An error occured in multi-table update"); /* Write the SQL statement to the binlog if we updated @@ -798,7 +809,7 @@ bool multi_update::send_eof() if (updated || not_trans_safe) { mysql_update_log.write(thd,thd->query,thd->query_length); - Query_log_event qinfo(thd, thd->query, thd->query_length); + Query_log_event qinfo(thd, thd->query, thd->query_length, 0); /* mysql_bin_log is not open if binlogging or replication @@ -807,14 +818,14 @@ bool multi_update::send_eof() if (mysql_bin_log.is_open() && mysql_bin_log.write(&qinfo) && !not_trans_safe) - error=1; /* Log write failed: roll back the SQL statement */ + local_error=1; /* Log write failed: roll back the SQL statement */ /* Commit or rollback the current SQL statement */ - VOID(ha_autocommit_or_rollback(thd,error > 0)); + VOID(ha_autocommit_or_rollback(thd, local_error > 0)); } else - error=0; // this can happen only if it is end of file error - if (!error) // if the above log write did not fail ... + local_error= 0; // this can happen only if it is end of file error + if (!local_error) // if the above log write did not fail ... { char buff[80]; sprintf(buff,ER(ER_UPDATE_INFO), (long) found, (long) updated, diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 04aeddfc384..a994a2539f7 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -69,6 +69,7 @@ inline Item *or_or_concat(Item* A, Item* B) enum Item_cast cast_type; enum Item_udftype udf_type; CHARSET_INFO *charset; + thr_lock_type lock_type; interval_type interval; } @@ -177,7 +178,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token CHARSET %token CHECKSUM_SYM %token CHECK_SYM -%token CIPHER %token COMMITTED_SYM %token COLLATE_SYM %token COLUMNS @@ -234,7 +234,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token IN_SYM %token ISOLATION %token ISAM_SYM -%token ISSUER %token JOIN_SYM %token KEYS %token KEY_SYM @@ -254,7 +253,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token MASTER_USER_SYM %token MASTER_LOG_FILE_SYM %token MASTER_LOG_POS_SYM -%token MASTER_LOG_SEQ_SYM %token MASTER_PASSWORD_SYM %token MASTER_PORT_SYM %token MASTER_CONNECT_RETRY_SYM @@ -275,10 +273,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token NEW_SYM %token NCHAR_SYM %token NOT -%token NO_FOREIGN_KEY_CHECKS %token NO_SYM %token NULL_SYM %token NUM +%token OFFSET_SYM %token ON %token OPEN_SYM %token OPTION @@ -305,7 +303,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token REAL_NUM %token REFERENCES %token REGEXP -%token RELAXED_UNIQUE_CHECKS %token RELOAD %token RENAME %token REPEATABLE_SYM @@ -557,7 +554,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); type int_type real_type order_dir opt_field_spec lock_option udf_type if_exists opt_local opt_table_options table_options table_option opt_if_not_exists opt_var_type opt_var_ident_type - delete_option opt_with_if_not_exists + delete_option opt_temporary %type <ulong_num> ULONG_NUM raid_types merge_insert_types @@ -565,6 +562,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %type <ulonglong_number> ulonglong_num +%type <lock_type> + replace_lock_option opt_low_priority insert_lock_option load_data_lock + %type <item> literal text_literal insert_ident order_ident simple_ident select_item2 expr opt_expr opt_else sum_expr in_sum_expr @@ -636,17 +636,18 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); field_opt_list opt_binary table_lock_list table_lock varchar ref_list opt_on_delete opt_on_delete_list opt_on_delete_item use opt_delete_options opt_delete_option - opt_outer table_list table_name opt_option opt_place opt_low_priority + opt_outer table_list table_name opt_option opt_place opt_attribute opt_attribute_list attribute column_list column_list_id opt_column_list grant_privileges opt_table user_list grant_option grant_privilege grant_privilege_list - flush_options flush_option insert_lock_option replace_lock_option + flush_options flush_option equal optional_braces opt_key_definition key_usage_list2 opt_mi_check_type opt_to mi_check_types normal_join table_to_table_list table_to_table opt_table_list opt_as handler_rkey_function handler_read_or_scan - single_multi table_wild_list table_wild_one opt_wild union union_list - precision union_option opt_on_delete_item subselect_start opt_and + single_multi table_wild_list table_wild_one opt_wild + union opt_union union_list union_option + precision opt_on_delete_item subselect_start opt_and subselect_end select_var_list select_var_list_init help opt_len END_OF_INPUT @@ -730,7 +731,7 @@ change: { LEX *lex = Lex; lex->sql_command = SQLCOM_CHANGE_MASTER; - memset(&lex->mi, 0, sizeof(lex->mi)); + bzero((char*) &lex->mi, sizeof(lex->mi)); } master_defs; master_defs: @@ -887,10 +888,6 @@ opt_if_not_exists: /* empty */ { $$= 0; } | IF NOT EXISTS { $$=HA_LEX_CREATE_IF_NOT_EXISTS; }; -opt_with_if_not_exists: - /* empty */ { $$= 0; } - | WITH IF NOT EXISTS { $$=HA_LEX_CREATE_IF_NOT_EXISTS; }; - opt_create_table_options: /* empty */ | create_table_options; @@ -1461,20 +1458,24 @@ opt_to: | EQ {} | AS {}; +/* + The first two deprecate the last two--delete the last two for 4.1 release +*/ + slave: START_SYM SLAVE slave_thread_opts - { - LEX *lex=Lex; - lex->sql_command = SQLCOM_SLAVE_START; - lex->type = 0; - } - | - STOP_SYM SLAVE slave_thread_opts - { - LEX *lex=Lex; - lex->sql_command = SQLCOM_SLAVE_STOP; - lex->type = 0; - }; + { + LEX *lex=Lex; + lex->sql_command = SQLCOM_SLAVE_START; + lex->type = 0; + } + | STOP_SYM SLAVE slave_thread_opts + { + LEX *lex=Lex; + lex->sql_command = SQLCOM_SLAVE_STOP; + lex->type = 0; + } + ; slave_thread_opts: slave_thread_opt @@ -2490,15 +2491,24 @@ opt_table_alias: where_clause: /* empty */ { Select->select_lex()->where= 0; } - | WHERE expr { Select->select_lex()->where= $2; }; + | WHERE expr + { + Select->select_lex()->where= $2; + if ($2) + $2->top_level_item(); + } + ; having_clause: /* empty */ | HAVING { Select->select_lex()->create_refs= 1; } expr - { - SELECT_LEX *sel= Select->select_lex(); - sel->having= $3; sel->create_refs=0; - }; + { + SELECT_LEX *sel= Select->select_lex(); + sel->having= $3; sel->create_refs=0; + if ($3) + $3->top_level_item(); + } + ; opt_escape: ESCAPE_SYM TEXT_STRING { $$= $2.str; } @@ -2563,11 +2573,6 @@ order_clause: ORDER_SYM BY { LEX *lex=Lex; - if (lex->sql_command == SQLCOM_MULTI_UPDATE) - { - net_printf(lex->thd, ER_WRONG_USAGE, "UPDATE", "ORDER BY"); - YYABORT; - } if (lex->current_select->linkage != GLOBAL_OPTIONS_TYPE && lex->current_select->select_lex()->olap != UNSPECIFIED_OLAP_TYPE) @@ -2593,7 +2598,7 @@ order_dir: limit_clause: /* empty */ {} - | LIMIT ULONG_NUM + | LIMIT { LEX *lex= Lex; if (lex->current_select->linkage != GLOBAL_OPTIONS_TYPE && @@ -2604,35 +2609,36 @@ limit_clause: "LIMIT"); YYABORT; } + } + limit_options + ; + +limit_options: + ULONG_NUM + { + SELECT_LEX_NODE *sel= Select; + sel->select_limit= $1; + sel->offset_limit= 0L; + } + | ULONG_NUM ',' ULONG_NUM + { SELECT_LEX_NODE *sel= Select; - sel->select_limit= $2; - sel->offset_limit= 0L; + sel->select_limit= $3; + sel->offset_limit= $1; } - | LIMIT ULONG_NUM ',' ULONG_NUM + | ULONG_NUM OFFSET_SYM ULONG_NUM { - LEX *lex=Lex; - if (lex->current_select->linkage != GLOBAL_OPTIONS_TYPE && - lex->current_select->select_lex()->olap != - UNSPECIFIED_OLAP_TYPE) - { - net_printf(lex->thd, ER_WRONG_USAGE, "CUBE/ROLLUP", - "LIMIT"); - YYABORT; - } - SELECT_LEX_NODE *sel= lex->current_select; - sel->select_limit= $4; - sel->offset_limit= $2; - }; + SELECT_LEX_NODE *sel= Select; + sel->select_limit= $1; + sel->offset_limit= $3; + } + ; + delete_limit_clause: /* empty */ { LEX *lex=Lex; - if (lex->sql_command == SQLCOM_MULTI_UPDATE) - { - net_printf(lex->thd, ER_WRONG_USAGE, "DELETE", "LIMIT"); - YYABORT; - } lex->current_select->select_limit= HA_POS_ERROR; } | LIMIT ulonglong_num @@ -2754,11 +2760,12 @@ do: DO_SYM */ drop: - DROP TABLE_SYM if_exists table_list opt_restrict + DROP opt_temporary TABLE_SYM if_exists table_list opt_restrict { LEX *lex=Lex; lex->sql_command = SQLCOM_DROP_TABLE; - lex->drop_if_exists = $3; + lex->drop_temporary= $2; + lex->drop_if_exists= $4; } | DROP INDEX ident ON table_ident {} { @@ -2795,14 +2802,25 @@ table_name: if_exists: /* empty */ { $$=0; } - | IF EXISTS { $$= 1; }; + | IF EXISTS { $$= 1; } + ; +opt_temporary: + /* empty */ { $$= 0; } + | TEMPORARY { $$= 1; } + ; /* ** Insert : add new data to table */ insert: - INSERT { Lex->sql_command = SQLCOM_INSERT; } insert_lock_option opt_ignore insert2 insert_field_spec; + INSERT { Lex->sql_command = SQLCOM_INSERT; } insert_lock_option + opt_ignore insert2 + { + set_lock_for_tables($3); + } + insert_field_spec + ; replace: REPLACE @@ -2811,17 +2829,23 @@ replace: lex->sql_command = SQLCOM_REPLACE; lex->duplicates= DUP_REPLACE; } - replace_lock_option insert2 insert_field_spec; + replace_lock_option insert2 + { + set_lock_for_tables($3); + } + insert_field_spec + ; insert_lock_option: - /* empty */ { Lex->lock_option= TL_WRITE_CONCURRENT_INSERT; } - | LOW_PRIORITY { Lex->lock_option= TL_WRITE_LOW_PRIORITY; } - | DELAYED_SYM { Lex->lock_option= TL_WRITE_DELAYED; } - | HIGH_PRIORITY { Lex->lock_option= TL_WRITE; }; + /* empty */ { $$= TL_WRITE_CONCURRENT_INSERT; } + | LOW_PRIORITY { $$= TL_WRITE_LOW_PRIORITY; } + | DELAYED_SYM { $$= TL_WRITE_DELAYED; } + | HIGH_PRIORITY { $$= TL_WRITE; } + ; replace_lock_option: - opt_low_priority {} - | DELAYED_SYM { Lex->lock_option= TL_WRITE_DELAYED; }; + opt_low_priority { $$= $1; } + | DELAYED_SYM { $$= TL_WRITE_DELAYED; }; insert2: INTO insert_table {} @@ -2867,7 +2891,7 @@ insert_values: mysql_init_select(lex); } select_options select_item_list select_from select_lock_type - union {}; + opt_union {}; values_list: values_list ',' no_braces @@ -2940,7 +2964,12 @@ update: lex->sql_command= SQLCOM_UPDATE; lex->select_lex.init_order(); } - opt_low_priority opt_ignore join_table_list SET update_list where_clause opt_order_clause delete_limit_clause; + opt_low_priority opt_ignore join_table_list + SET update_list where_clause opt_order_clause delete_limit_clause + { + set_lock_for_tables($3); + } + ; update_list: update_list ',' simple_ident equal expr @@ -2955,8 +2984,8 @@ update_list: }; opt_low_priority: - /* empty */ { Lex->lock_option= current_thd->update_lock_default; } - | LOW_PRIORITY { Lex->lock_option= TL_WRITE_LOW_PRIORITY; }; + /* empty */ { $$= current_thd->update_lock_default; } + | LOW_PRIORITY { $$= TL_WRITE_LOW_PRIORITY; }; /* Delete rows from a table */ @@ -2969,13 +2998,20 @@ delete: lex->lock_option= lex->thd->update_lock_default; lex->select_lex.init_order(); } - opt_delete_options single_multi {}; + opt_delete_options single_multi {} + ; single_multi: - FROM table_name where_clause opt_order_clause delete_limit_clause {} + FROM table_ident + { + if (!add_table_to_list($2, NULL, 1, Lex->lock_option)) + YYABORT; + } + where_clause opt_order_clause + delete_limit_clause | table_wild_list { mysql_init_multi_delete(Lex); } - FROM join_table_list where_clause + FROM join_table_list where_clause | FROM table_wild_list { mysql_init_multi_delete(Lex); } USING join_table_list where_clause; @@ -2985,18 +3021,19 @@ table_wild_list: | table_wild_list ',' table_wild_one {}; table_wild_one: - ident opt_wild - { - if (!Select->add_table_to_list(new Table_ident($1), NULL, 1, - TL_WRITE)) - YYABORT; - } - | ident '.' ident opt_wild - { - if (!Select->add_table_to_list(new Table_ident($1, $3, 0), NULL, - 1, TL_WRITE)) + ident opt_wild + { + if (!Select->add_table_to_list(new Table_ident($1), NULL, 1, + Lex->lock_option)) + YYABORT; + } + | ident '.' ident opt_wild + { + if (!Select->add_table_to_list(new Table_ident($1, $3, 0), NULL, 1, + Lex->lock_option)) YYABORT; - }; + } + ; opt_wild: /* empty */ {} @@ -3018,7 +3055,8 @@ truncate: lex->sql_command= SQLCOM_TRUNCATE; lex->select_lex.options= 0; lex->select_lex.init_order(); - lex->lock_option= lex->thd->update_lock_default; }; + } + ; opt_table_sym: /* empty */ @@ -3145,7 +3183,7 @@ show_param: lex->grant_user=$3; lex->grant_user->password.str=NullS; } - | CREATE DATABASE opt_with_if_not_exists ident + | CREATE DATABASE opt_if_not_exists ident { Lex->sql_command=SQLCOM_SHOW_CREATE_DB; Lex->create_info.options=$3; @@ -3310,7 +3348,8 @@ load: LOAD DATA_SYM load_data_lock opt_local INFILE TEXT_STRING { LEX *lex=Lex; lex->sql_command= SQLCOM_LOAD; - lex->local_file= $4; + lex->lock_option= $3; + lex->local_file= $4; if (!(lex->exchange= new sql_exchange($6.str,0))) YYABORT; lex->field_list.empty(); @@ -3340,9 +3379,9 @@ opt_local: | LOCAL_SYM { $$=1;}; load_data_lock: - /* empty */ { Lex->lock_option= current_thd->update_lock_default; } - | CONCURRENT { Lex->lock_option= TL_WRITE_CONCURRENT_INSERT ; } - | LOW_PRIORITY { Lex->lock_option= TL_WRITE_LOW_PRIORITY; }; + /* empty */ { $$= current_thd->update_lock_default; } + | CONCURRENT { $$= TL_WRITE_CONCURRENT_INSERT ; } + | LOW_PRIORITY { $$= TL_WRITE_LOW_PRIORITY; }; opt_duplicate: @@ -3485,12 +3524,13 @@ ident: IDENT { $$=$1; } | keyword { - LEX *lex; - $$.str=sql_strmake($1.str,$1.length); + LEX *lex= Lex; + $$.str= lex->thd->strmake($1.str,$1.length); $$.length=$1.length; - if ((lex=Lex)->next_state != STATE_END) + if (lex->next_state != STATE_END) lex->next_state=STATE_OPERATOR_OR_IDENT; - }; + } + ; ident_or_text: ident { $$=$1;} @@ -3613,6 +3653,7 @@ keyword: | NEW_SYM {} | NO_SYM {} | NONE_SYM {} + | OFFSET_SYM {} | OPEN_SYM {} | PACK_KEYS_SYM {} | PARTIAL {} @@ -4198,7 +4239,7 @@ rollback: */ -union: +opt_union: /* empty */ {} | union_list; @@ -4225,11 +4266,14 @@ union_list: ; union_opt: - union {} + union_list {} | optional_order_or_limit {}; optional_order_or_limit: - /* empty */ {} + /* empty + intentional reduce/reduce conflict here !!! + { code } below should not be executed + when neither ORDER BY nor LIMIT are used */ {} | { LEX *lex=Lex; diff --git a/sql/stacktrace.c b/sql/stacktrace.c index 1aba73dda33..f5c0a59b572 100644 --- a/sql/stacktrace.c +++ b/sql/stacktrace.c @@ -206,7 +206,7 @@ resolve it\n"); /* Produce a core for the thread */ -#ifdef HAVE_LINUXTHREADS +#ifdef NOT_USED /* HAVE_LINUXTHREADS */ void write_core(int sig) { signal(sig, SIG_DFL); diff --git a/sql/table.cc b/sql/table.cc index bad453f2cad..84a072c886d 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -95,15 +95,15 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, if (my_read(file,(byte*) head,64,MYF(MY_NABP))) goto err_not_open; if (head[0] != (uchar) 254 || head[1] != 1 || - (head[2] < FRM_VER && head[2] > FRM_VER+2)) - goto err_not_open; /* purecov: inspected */ + (head[2] != FRM_VER && head[2] > FRM_VER+2)) + goto err_not_open; /* purecov: inspected */ new_field_pack_flag=head[27]; new_frm_ver= (head[2] - FRM_VER); field_pack_length= new_frm_ver < 2 ? 11 : 15; error=3; if (!(pos=get_form_pos(file,head,(TYPELIB*) 0))) - goto err_not_open; /* purecov: inspected */ + goto err_not_open; /* purecov: inspected */ *fn_ext(index_file)='\0'; // Remove .frm extension outparam->db_type=ha_checktype((enum db_type) (uint) *(head+3)); @@ -145,7 +145,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, goto err_not_open; /* purecov: inspected */ bzero((char*) keyinfo,n_length); outparam->key_info=keyinfo; - outparam->max_key_length=0; + outparam->max_key_length= outparam->total_key_length= 0; key_part= (KEY_PART_INFO*) (keyinfo+keys); strpos=disk_buff+6; @@ -203,11 +203,13 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, } set_if_bigger(outparam->max_key_length,keyinfo->key_length+ keyinfo->key_parts); + outparam->total_key_length+= keyinfo->key_length; if (keyinfo->flags & HA_NOSAME) set_if_bigger(outparam->max_unique_length,keyinfo->key_length); } keynames=(char*) key_part; strpos+= (strmov(keynames, (char *) strpos) - keynames)+1; + outparam->reclength = uint2korr((head+16)); if (*(head+26) == 1) outparam->system=1; /* one-record-database */ @@ -391,6 +393,11 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, (TYPELIB*) 0), outparam->fieldnames.type_names[i], outparam); + if (!reg_field) // Not supported field type + { + error= 4; + goto err_not_open; /* purecov: inspected */ + } reg_field->comment=comment; reg_field->set_charset(charset); if (!(reg_field->flags & NOT_NULL_FLAG)) diff --git a/sql/table.h b/sql/table.h index d09194442c8..18079e183ce 100644 --- a/sql/table.h +++ b/sql/table.h @@ -58,6 +58,7 @@ struct st_table { uint reclength; /* Recordlength */ uint rec_buff_length; uint keys,key_parts,primary_key,max_key_length,max_unique_length; + uint total_key_length; uint uniques; uint null_fields; /* number of null fields */ uint blob_fields; /* number of blob fields */ |