diff options
58 files changed, 1022 insertions, 309 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 890ee2676e8..54df0befad9 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -158,7 +158,7 @@ IF(EMBED_MANIFESTS) STRING(REGEX MATCH "MANIFEST:NO" tmp_manifest ${CMAKE_EXE_LINKER_FLAGS}) IF(NOT tmp_manifest) SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /MANIFEST:NO") - ENDIF(tmp_manifest) + ENDIF(NOT tmp_manifest) # Set the processor architecture. IF(CMAKE_GENERATOR MATCHES "Visual Studio 8 2005 Win64") SET(PROCESSOR_ARCH "X64") diff --git a/client/mysqldump.c b/client/mysqldump.c index 93b9b373ecb..fc461a5f559 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -3271,10 +3271,41 @@ static int do_unlock_tables(MYSQL *mysql_con) return mysql_query_with_error_report(mysql_con, 0, "UNLOCK TABLES"); } +static int get_bin_log_name(MYSQL *mysql_con, + char* buff_log_name, uint buff_len) +{ + MYSQL_RES *res; + MYSQL_ROW row; + + if (mysql_query(mysql_con, "SHOW MASTER STATUS") || + !(res= mysql_store_result(mysql))) + return 1; + + if (!(row= mysql_fetch_row(res))) + { + mysql_free_result(res); + return 1; + } + /* + Only one row is returned, and the first column is the name of the + active log. + */ + strmake(buff_log_name, row[0], buff_len - 1); -static int do_reset_master(MYSQL *mysql_con) + mysql_free_result(res); + return 0; +} + +static int purge_bin_logs_to(MYSQL *mysql_con, char* log_name) { - return mysql_query_with_error_report(mysql_con, 0, "RESET MASTER"); + DYNAMIC_STRING str; + int err; + init_dynamic_string_checked(&str, "PURGE BINARY LOGS TO '", 1024, 1024); + dynstr_append_checked(&str, log_name); + dynstr_append_checked(&str, "'"); + err = mysql_query_with_error_report(mysql_con, 0, str.str); + dynstr_free(&str); + return err; } @@ -3798,6 +3829,7 @@ static void dynstr_realloc_checked(DYNAMIC_STRING *str, ulong additional_size) int main(int argc, char **argv) { + char bin_log_name[FN_REFLEN]; int exit_code; MY_INIT("mysqldump"); @@ -3834,8 +3866,13 @@ int main(int argc, char **argv) goto err; if (opt_single_transaction && start_transaction(mysql)) goto err; - if (opt_delete_master_logs && do_reset_master(mysql)) - goto err; + if (opt_delete_master_logs) + { + if (mysql_refresh(mysql, REFRESH_LOG) || + get_bin_log_name(mysql, bin_log_name, sizeof(bin_log_name))) + goto err; + flush_logs= 0; + } if (opt_lock_all_tables || opt_master_data) { if (flush_logs && mysql_refresh(mysql, REFRESH_LOG)) @@ -3859,6 +3896,18 @@ int main(int argc, char **argv) /* One or more databases, all tables */ dump_databases(argv); } + + /* ensure dumped data flushed */ + if (md_result_file && fflush(md_result_file)) + { + if (!first_error) + first_error= EX_MYSQLERR; + goto err; + } + /* everything successful, purge the old logs files */ + if (opt_delete_master_logs && purge_bin_logs_to(mysql, bin_log_name)) + goto err; + #ifdef HAVE_SMEM my_free(shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR)); #endif diff --git a/client/mysqltest.c b/client/mysqltest.c index 5640d0c24ba..2d9ee74891c 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -1143,6 +1143,50 @@ void check_require(DYNAMIC_STRING* ds, const char *fname) } +/* + Remove surrounding chars from string + + Return 1 if first character is found but not last +*/ +static int strip_surrounding(char* str, char c1, char c2) +{ + char* ptr= str; + + /* Check if the first non space character is c1 */ + while(*ptr && my_isspace(charset_info, *ptr)) + ptr++; + if (*ptr == c1) + { + /* Replace it with a space */ + *ptr= ' '; + + /* Last non space charecter should be c2 */ + ptr= strend(str)-1; + while(*ptr && my_isspace(charset_info, *ptr)) + ptr--; + if (*ptr == c2) + { + /* Replace it with \0 */ + *ptr= 0; + } + else + { + /* Mismatch detected */ + return 1; + } + } + return 0; +} + + +static void strip_parentheses(struct st_command *command) +{ + if (strip_surrounding(command->first_argument, '(', ')')) + die("%.*s - argument list started with '%c' must be ended with '%c'", + command->first_word_len, command->query, '(', ')'); +} + + static byte *get_var_key(const byte* var, uint* len, my_bool __attribute__((unused)) t) { @@ -1398,12 +1442,11 @@ void var_query_set(VAR *var, const char *query, const char** query_end) init_dynamic_string(&ds_query, 0, (end - query) + 32, 256); do_eval(&ds_query, query, end, FALSE); - if (mysql_real_query(mysql, ds_query.str, ds_query.length) || - !(res = mysql_store_result(mysql))) - { + if (mysql_real_query(mysql, ds_query.str, ds_query.length)) die("Error running query '%s': %d %s", ds_query.str, mysql_errno(mysql), mysql_error(mysql)); - } + if (!(res= mysql_store_result(mysql))) + die("Query '%s' didn't return a result set", ds_query.str); dynstr_free(&ds_query); if ((row = mysql_fetch_row(res)) && row[0]) @@ -1457,6 +1500,130 @@ void var_query_set(VAR *var, const char *query, const char** query_end) } +/* + Set variable from the result of a field in a query + + This function is useful when checking for a certain value + in the output from a query that can't be restricted to only + return some values. A very good example of that is most SHOW + commands. + + SYNOPSIS + var_set_query_get_value() + + DESCRIPTION + let $variable= query_get_value(<query to run>,<column name>,<row no>); + + <query to run> - The query that should be sent to the server + <column name> - Name of the column that holds the field be compared + against the expected value + <row no> - Number of the row that holds the field to be + compared against the expected value + +*/ + +void var_set_query_get_value(struct st_command *command, VAR *var) +{ + ulong row_no; + int col_no= -1; + MYSQL_RES* res; + MYSQL* mysql= &cur_con->mysql; + + static DYNAMIC_STRING ds_query; + static DYNAMIC_STRING ds_col; + static DYNAMIC_STRING ds_row; + const struct command_arg query_get_value_args[] = { + "query", ARG_STRING, TRUE, &ds_query, "Query to run", + "column name", ARG_STRING, TRUE, &ds_col, "Name of column", + "row number", ARG_STRING, TRUE, &ds_row, "Number for row", + }; + + DBUG_ENTER("var_set_query_get_value"); + LINT_INIT(res); + + strip_parentheses(command); + DBUG_PRINT("info", ("query: %s", command->query)); + check_command_args(command, command->first_argument, query_get_value_args, + sizeof(query_get_value_args)/sizeof(struct command_arg), + ','); + + DBUG_PRINT("info", ("query: %s", ds_query.str)); + DBUG_PRINT("info", ("col: %s", ds_col.str)); + + /* Convert row number to int */ + if (!str2int(ds_row.str, 10, (long) 0, (long) INT_MAX, &row_no)) + die("Invalid row number: '%s'", ds_row.str); + DBUG_PRINT("info", ("row: %s, row_no: %ld", ds_row.str, row_no)); + dynstr_free(&ds_row); + + /* Remove any surrounding "'s from the query - if there is any */ + if (strip_surrounding(ds_query.str, '"', '"')) + die("Mismatched \"'s around query '%s'", ds_query.str); + + /* Run the query */ + if (mysql_real_query(mysql, ds_query.str, ds_query.length)) + die("Error running query '%s': %d %s", ds_query.str, + mysql_errno(mysql), mysql_error(mysql)); + if (!(res= mysql_store_result(mysql))) + die("Query '%s' didn't return a result set", ds_query.str); + + { + /* Find column number from the given column name */ + uint i; + uint num_fields= mysql_num_fields(res); + MYSQL_FIELD *fields= mysql_fetch_fields(res); + + for (i= 0; i < num_fields; i++) + { + if (strcmp(fields[i].name, ds_col.str) == 0 && + strlen(fields[i].name) == ds_col.length) + { + col_no= i; + break; + } + } + if (col_no == -1) + { + mysql_free_result(res); + die("Could not find column '%s' in the result of '%s'", + ds_col.str, ds_query.str); + } + DBUG_PRINT("info", ("Found column %d with name '%s'", + i, fields[i].name)); + } + dynstr_free(&ds_col); + + { + /* Get the value */ + MYSQL_ROW row; + ulong rows= 0; + const char* value= "No such row"; + + while ((row= mysql_fetch_row(res))) + { + if (++rows == row_no) + { + + DBUG_PRINT("info", ("At row %ld, column %d is '%s'", + row_no, col_no, row[col_no])); + /* Found the row to get */ + if (row[col_no]) + value= row[col_no]; + else + value= "NULL"; + + break; + } + } + eval_expr(var, value, 0); + } + dynstr_free(&ds_query); + mysql_free_result(res); + + DBUG_VOID_RETURN; +} + + void var_copy(VAR *dest, VAR *src) { dest->int_val= src->int_val; @@ -1480,26 +1647,47 @@ void var_copy(VAR *dest, VAR *src) void eval_expr(VAR *v, const char *p, const char **p_end) { - static int MIN_VAR_ALLOC= 32; /* MASV why 32? */ - VAR *vp; + + DBUG_ENTER("eval_expr"); + DBUG_PRINT("enter", ("p: '%s'", p)); + if (*p == '$') { + VAR *vp; if ((vp= var_get(p, p_end, 0, 0))) - { var_copy(v, vp); - return; - } + DBUG_VOID_RETURN; } - else if (*p == '`') + + if (*p == '`') { var_query_set(v, p, p_end); + DBUG_VOID_RETURN; } - else + + { + /* Check if this is a "let $var= query_get_value()" */ + const char* get_value_str= "query_get_value"; + const size_t len= strlen(get_value_str); + if (strncmp(p, get_value_str, len)==0) + { + struct st_command command; + memset(&command, 0, sizeof(command)); + command.query= (char*)p; + command.first_word_len= len; + command.first_argument= command.query + len; + command.end= (char*)*p_end; + var_set_query_get_value(&command, v); + DBUG_VOID_RETURN; + } + } + { int new_val_len = (p_end && *p_end) ? (int) (*p_end - p) : (int) strlen(p); if (new_val_len + 1 >= v->alloced_len) { + static int MIN_VAR_ALLOC= 32; v->alloced_len = (new_val_len < MIN_VAR_ALLOC - 1) ? MIN_VAR_ALLOC : new_val_len + 1; if (!(v->str_val = @@ -1512,9 +1700,10 @@ void eval_expr(VAR *v, const char *p, const char **p_end) memcpy(v->str_val, p, new_val_len); v->str_val[new_val_len] = 0; v->int_val=atoi(p); + DBUG_PRINT("info", ("atoi on '%s', returns: %d", p, v->int_val)); v->int_dirty=0; } - return; + DBUG_VOID_RETURN; } @@ -3453,7 +3642,6 @@ void do_connect(struct st_command *command) int con_port= opt_port; char *con_options; bool con_ssl= 0, con_compress= 0; - char *ptr; static DYNAMIC_STRING ds_connection_name; static DYNAMIC_STRING ds_host; @@ -3481,20 +3669,7 @@ void do_connect(struct st_command *command) DBUG_ENTER("do_connect"); DBUG_PRINT("enter",("connect: %s", command->first_argument)); - /* Remove parenteses around connect arguments */ - if ((ptr= strstr(command->first_argument, "("))) - { - /* Replace it with a space */ - *ptr= ' '; - if ((ptr= strstr(command->first_argument, ")"))) - { - /* Replace it with \0 */ - *ptr= 0; - } - else - die("connect - argument list started with '(' must be ended with ')'"); - } - + strip_parentheses(command); check_command_args(command, command->first_argument, connect_args, sizeof(connect_args)/sizeof(struct command_arg), ','); @@ -4192,16 +4367,12 @@ int read_command(struct st_command** command_ptr) DBUG_RETURN(0); } if (!(*command_ptr= command= - (struct st_command*) my_malloc(sizeof(*command), MYF(MY_WME))) || + (struct st_command*) my_malloc(sizeof(*command), + MYF(MY_WME|MY_ZEROFILL))) || insert_dynamic(&q_lines, (gptr) &command)) die(NullS); - - command->require_file[0]= 0; - command->first_word_len= 0; - command->query_len= 0; - command->type= Q_UNKNOWN; - command->query_buf= command->query= 0; + read_command_buf[0]= 0; if (read_line(read_command_buf, sizeof(read_command_buf))) { diff --git a/include/m_string.h b/include/m_string.h index 349084ab21e..981111b8718 100644 --- a/include/m_string.h +++ b/include/m_string.h @@ -105,6 +105,9 @@ extern char *stpcpy(char *, const char *); /* For AIX with gcc 2.95.3 */ extern char NEAR _dig_vec_upper[]; extern char NEAR _dig_vec_lower[]; +/* Defined in strtod.c */ +extern const double log_10[309]; + #ifdef BAD_STRING_COMPILER #define strmov(A,B) (memccpy(A,B,0,INT_MAX)-1) #else diff --git a/include/mysql_com.h b/include/mysql_com.h index 93409b2ea1d..889579e3622 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -345,6 +345,11 @@ my_bool net_write_command(NET *net,unsigned char command, int net_real_write(NET *net,const char *packet,unsigned long len); unsigned long my_net_read(NET *net); +#ifdef _global_h +void my_net_set_write_timeout(NET *net, uint timeout); +void my_net_set_read_timeout(NET *net, uint timeout); +#endif + /* The following function is not meant for normal usage Currently it's used internally by manager.c diff --git a/include/violite.h b/include/violite.h index 63388c170c9..e0172008565 100644 --- a/include/violite.h +++ b/include/violite.h @@ -88,7 +88,6 @@ my_bool vio_peer_addr(Vio* vio, char *buf, uint16 *port); /* Remotes in_addr */ void vio_in_addr(Vio *vio, struct in_addr *in); my_bool vio_poll_read(Vio *vio,uint timeout); -void vio_timeout(Vio *vio,uint which, uint timeout); #ifdef HAVE_OPENSSL #include <openssl/opensslv.h> diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index e80684a1b1e..e426d2c549e 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -67,8 +67,6 @@ ulong net_buffer_length=8192; ulong max_allowed_packet= 1024L*1024L*1024L; -ulong net_read_timeout= CLIENT_NET_READ_TIMEOUT; -ulong net_write_timeout= CLIENT_NET_WRITE_TIMEOUT; #ifdef EMBEDDED_LIBRARY @@ -1528,8 +1526,8 @@ my_bool STDCALL mysql_embedded(void) void my_net_local_init(NET *net) { net->max_packet= (uint) net_buffer_length; - net->read_timeout= (uint) net_read_timeout; - net->write_timeout=(uint) net_write_timeout; + my_net_set_read_timeout(net, CLIENT_NET_READ_TIMEOUT); + my_net_set_write_timeout(net, CLIENT_NET_WRITE_TIMEOUT); net->retry_count= 1; net->max_packet_size= max(net_buffer_length, max_allowed_packet); } diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index fffee6134d9..24931955867 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -2330,16 +2330,23 @@ sub check_running_as_root () { close FILE; } - chmod(oct("0755"), $test_file); - unlink($test_file); + # Some filesystems( for example CIFS) allows reading a file + # although mode was set to 0000, but in that case a stat on + # the file will not return 0000 + my $file_mode= (stat($test_file))[2] & 07777; $ENV{'MYSQL_TEST_ROOT'}= "NO"; - if ($result eq "MySQL") + mtr_verbose("result: $result, file_mode: $file_mode"); + if ($result eq "MySQL" && $file_mode == 0) { mtr_warning("running this script as _root_ will cause some " . "tests to be skipped"); $ENV{'MYSQL_TEST_ROOT'}= "YES"; } + + chmod(oct("0755"), $test_file); + unlink($test_file); + } @@ -3623,6 +3630,9 @@ sub do_before_start_master ($) { # FIXME what about second master..... + # Don't delete anything if starting dirty + return if ($opt_start_dirty); + foreach my $bin ( glob("$opt_vardir/log/master*-bin*") ) { unlink($bin); @@ -3654,6 +3664,9 @@ sub do_before_start_slave ($) { my $tname= $tinfo->{'name'}; my $init_script= $tinfo->{'master_sh'}; + # Don't delete anything if starting dirty + return if ($opt_start_dirty); + foreach my $bin ( glob("$opt_vardir/log/slave*-bin*") ) { unlink($bin); diff --git a/mysql-test/r/ctype_cp932_binlog.result b/mysql-test/r/ctype_cp932_binlog.result index ff295961008..3385cd20ec4 100644 --- a/mysql-test/r/ctype_cp932_binlog.result +++ b/mysql-test/r/ctype_cp932_binlog.result @@ -9,8 +9,7 @@ EXECUTE stmt1 USING @var1; SHOW BINLOG EVENTS FROM 98; Log_name Pos Event_type Server_id End_log_pos Info master-bin.000001 98 Query 1 188 use `test`; CREATE TABLE t1(f1 blob) -master-bin.000001 188 User var 1 227 @`var1`=_binary 0x8300 COLLATE binary -master-bin.000001 227 Query 1 323 use `test`; INSERT INTO t1 VALUES(@'var1') +master-bin.000001 188 Query 1 283 use `test`; INSERT INTO t1 VALUES(0x8300) SELECT HEX(f1) FROM t1; HEX(f1) 8300 @@ -30,17 +29,17 @@ HEX(s1) HEX(s2) d 466F6F2773206120426172 ED40ED41ED42 47.93 DROP PROCEDURE bug18293| DROP TABLE t4| -SHOW BINLOG EVENTS FROM 402| +SHOW BINLOG EVENTS FROM 362| Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 402 Query 1 568 use `test`; CREATE TABLE t4 (s1 CHAR(50) CHARACTER SET latin1, +master-bin.000001 362 Query 1 528 use `test`; CREATE TABLE t4 (s1 CHAR(50) CHARACTER SET latin1, s2 CHAR(50) CHARACTER SET cp932, d DECIMAL(10,2)) -master-bin.000001 568 Query 1 816 use `test`; CREATE DEFINER=`root`@`localhost` PROCEDURE bug18293 (IN ins1 CHAR(50), +master-bin.000001 528 Query 1 776 use `test`; CREATE DEFINER=`root`@`localhost` PROCEDURE bug18293 (IN ins1 CHAR(50), IN ins2 CHAR(50) CHARACTER SET cp932, IN ind DECIMAL(10,2)) BEGIN INSERT INTO t4 VALUES (ins1, ins2, ind); END -master-bin.000001 816 Query 1 1035 use `test`; INSERT INTO t4 VALUES ( NAME_CONST('ins1',_latin1 0x466F6F2773206120426172), NAME_CONST('ins2',_cp932 0xED40ED41ED42), NAME_CONST('ind',47.93)) -master-bin.000001 1035 Query 1 1124 use `test`; DROP PROCEDURE bug18293 -master-bin.000001 1124 Query 1 1203 use `test`; DROP TABLE t4 +master-bin.000001 776 Query 1 995 use `test`; INSERT INTO t4 VALUES ( NAME_CONST('ins1',_latin1 0x466F6F2773206120426172), NAME_CONST('ins2',_cp932 0xED40ED41ED42), NAME_CONST('ind',47.93)) +master-bin.000001 995 Query 1 1084 use `test`; DROP PROCEDURE bug18293 +master-bin.000001 1084 Query 1 1163 use `test`; DROP TABLE t4 diff --git a/mysql-test/r/ctype_cp932_notembedded.result b/mysql-test/r/ctype_cp932_notembedded.result index c58bfc65454..241fa0d1db7 100644 --- a/mysql-test/r/ctype_cp932_notembedded.result +++ b/mysql-test/r/ctype_cp932_notembedded.result @@ -9,8 +9,7 @@ EXECUTE stmt1 USING @var1; SHOW BINLOG EVENTS FROM 98; Log_name Pos Event_type Server_id End_log_pos Info master-bin.000001 98 Query 1 188 use `test`; CREATE TABLE t1(f1 blob) -master-bin.000001 188 User var 1 227 @`var1`=_binary 0x8300 COLLATE binary -master-bin.000001 227 Query 1 323 use `test`; INSERT INTO t1 VALUES(@'var1') +master-bin.000001 188 Query 1 283 use `test`; INSERT INTO t1 VALUES(0x8300) SELECT HEX(f1) FROM t1; HEX(f1) 8300 diff --git a/mysql-test/r/ctype_ucs2_def.result b/mysql-test/r/ctype_ucs2_def.result index 2f9dc4ae616..c076ca36cdb 100644 --- a/mysql-test/r/ctype_ucs2_def.result +++ b/mysql-test/r/ctype_ucs2_def.result @@ -7,3 +7,11 @@ character_set_server ucs2 DROP TABLE IF EXISTS t1; create table t1 (a int); drop table t1; +CREATE TABLE t1(col1 VARCHAR(32) CHARACTER SET ucs2 COLLATE ucs2_bin NOT NULL, +col2 VARCHAR(32) CHARACTER SET ucs2 COLLATE ucs2_bin NOT NULL, +UNIQUE KEY key1 USING HASH (col1, col2)) ENGINE=MEMORY; +INSERT INTO t1 VALUES('A', 'A'), ('B', 'B'), ('C', 'C'); +INSERT INTO t1 VALUES('A ', 'A '); +ERROR 23000: Duplicate entry '' for key 1 +DROP TABLE t1; +End of 5.0 tests diff --git a/mysql-test/r/heap_hash.result b/mysql-test/r/heap_hash.result index 80abcebbfea..cb47573b502 100644 --- a/mysql-test/r/heap_hash.result +++ b/mysql-test/r/heap_hash.result @@ -366,3 +366,19 @@ explain select a from t1 where a in (1,3); id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 range a a 5 NULL 4 Using where drop table t1; +End of 4.1 tests +CREATE TABLE t1(col1 VARCHAR(32) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, +col2 VARCHAR(32) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, +UNIQUE KEY key1 USING HASH (col1, col2)) ENGINE=MEMORY; +INSERT INTO t1 VALUES('A', 'A'); +INSERT INTO t1 VALUES('A ', 'A '); +ERROR 23000: Duplicate entry 'A -A ' for key 1 +DROP TABLE t1; +CREATE TABLE t1(col1 VARCHAR(32) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL, +col2 VARCHAR(32) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL, +UNIQUE KEY key1 USING HASH (col1, col2)) ENGINE=MEMORY; +INSERT INTO t1 VALUES('A', 'A'); +INSERT INTO t1 VALUES('A ', 'A '); +ERROR 23000: Duplicate entry 'A -A ' for key 1 +DROP TABLE t1; +End of 5.0 tests diff --git a/mysql-test/r/innodb_mysql.result b/mysql-test/r/innodb_mysql.result index 45cb116f08b..34eb831e7db 100644 --- a/mysql-test/r/innodb_mysql.result +++ b/mysql-test/r/innodb_mysql.result @@ -617,4 +617,12 @@ EXPLAIN SELECT COUNT(*) FROM t2 WHERE stat_id IN (1,3) AND acct_id=785; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 range idx1,idx2 idx1 9 NULL 2 Using where; Using index DROP TABLE t1,t2; +create table t1(a int) engine=innodb; +alter table t1 comment '123'; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) default NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='123' +drop table t1; End of 5.0 tests diff --git a/mysql-test/r/limit.result b/mysql-test/r/limit.result index ac96ac8ff17..01d7d7ca218 100644 --- a/mysql-test/r/limit.result +++ b/mysql-test/r/limit.result @@ -91,3 +91,14 @@ select sum(a) c FROM t1 WHERE a > 0 ORDER BY c LIMIT 3; c 28 drop table t1; +prepare s from "select 1 limit ?"; +set @a='qwe'; +execute s using @a; +ERROR HY000: Incorrect arguments to EXECUTE +prepare s from "select 1 limit 1, ?"; +execute s using @a; +ERROR HY000: Incorrect arguments to EXECUTE +prepare s from "select 1 limit ?, ?"; +execute s using @a, @a; +ERROR HY000: Incorrect arguments to EXECUTE +End of 5.0 tests diff --git a/mysql-test/r/mysqltest.result b/mysql-test/r/mysqltest.result index 35dcf9b62d2..6f283677bf7 100644 --- a/mysql-test/r/mysqltest.result +++ b/mysql-test/r/mysqltest.result @@ -410,7 +410,6 @@ mysqltest: At line 1: Wrong column number to replace_column in 'replace_column a mysqltest: At line 1: Wrong column number to replace_column in 'replace_column a 1' mysqltest: At line 1: Wrong column number to replace_column in 'replace_column 1 b c ' mysqltest: At line 1: Invalid integer argument "10!" -mysqltest: At line 1: End of line junk detected: "!" mysqltest: At line 1: Invalid integer argument "a" mysqltest: At line 1: Missing required argument 'connection name' to command 'connect' mysqltest: At line 1: Missing required argument 'connection name' to command 'connect' @@ -666,4 +665,43 @@ INSERT INTO t1 SELECT f1 - 256 FROM t1; INSERT INTO t1 SELECT f1 - 512 FROM t1; SELECT * FROM t1; DROP TABLE t1; +CREATE TABLE t1( +a int, b varchar(255), c datetime +); +SHOW COLUMNS FROM t1; +Field Type Null Key Default Extra +a int(11) YES NULL +b varchar(255) YES NULL +c datetime YES NULL +statement=SHOW COLUMNS FROM t1 row_number=1, column_name="Type", Value=int(11) +statement="SHOW COLUMNS FROM t1" row_number=1, column_name="Type", Value=int(11) +statement=SHOW COLUMNS FROM t1 row_number=1, column_name=Default, Value=NULL +value= ->A B<- +value= 1 +mysqltest: At line 1: query_get_value - argument list started with '(' must be ended with ')' +mysqltest: At line 1: Missing required argument 'query' to command 'query_get_value' +mysqltest: At line 1: Missing required argument 'column name' to command 'query_get_value' +mysqltest: At line 1: Missing required argument 'row number' to command 'query_get_value' +value= No such row +value= No such row +mysqltest: At line 1: Invalid row number: 'notnumber' +mysqltest: At line 1: Could not find column 'column_not_exists' in the result of 'SHOW COLUMNS FROM t1' +mysqltest: At line 1: Query 'SET @A = 1' didn't return a result set +mysqltest: At line 1: Could not find column '1 AS B' in the result of 'SELECT 1 AS A' +value= No such row +mysqltest: At line 1: Error running query 'SHOW COLNS FROM t1': 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'COLNS FROM t1' at line 1 + +Field Type Null Key Default Extra +a int(11) YES -><- NULL +b varchar(255) YES -><- NULL +c datetime YES -><- NULL + +Number of columns with Default NULL: 3 + +SHOW COLUMNS FROM t1; +Field Type Null Key Default Extra +a int(11) YES NULL +b varchar(255) YES NULL +c datetime YES NULL +drop table t1; End of tests diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index 8a10a52ee65..482c9f42f42 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -1683,4 +1683,13 @@ execute stmt; ERROR 42S22: Unknown column 'y.value' in 'field list' deallocate prepare stmt; drop tables t1; +prepare stmt from "create table t1 select ?"; +set @a=1.0; +execute stmt using @a; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `?` decimal(2,1) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +drop table t1; End of 5.0 tests. diff --git a/mysql-test/r/rpl_rotate_logs.result b/mysql-test/r/rpl_rotate_logs.result index bf2ef98c87f..df42e76a0c8 100644 --- a/mysql-test/r/rpl_rotate_logs.result +++ b/mysql-test/r/rpl_rotate_logs.result @@ -50,7 +50,10 @@ show binary logs; Log_name File_size master-bin.000002 363 master-bin.000003 407 -purge master logs before now(); +select @time_for_purge:=DATE_ADD(UPDATE_TIME, INTERVAL 1 SECOND) +from information_schema.tables +where TABLE_SCHEMA="test" and TABLE_NAME="t2"; +purge master logs before (@time_for_purge); show binary logs; Log_name File_size master-bin.000003 407 diff --git a/mysql-test/r/rpl_user_variables.result b/mysql-test/r/rpl_user_variables.result index 05f2b68042e..26ac2b26aaa 100644 --- a/mysql-test/r/rpl_user_variables.result +++ b/mysql-test/r/rpl_user_variables.result @@ -253,10 +253,44 @@ SELECT * from t2; k 100 42 +drop table t1, t2; +reset master; +create table t1 (a int); +prepare s from "insert into t1 values (@a),(?)"; +set @a=98; +execute s using @a; +prepare s from "insert into t1 values (?)"; +set @a=99; +execute s using @a; +prepare s from "insert into t1 select 100 limit ?"; +set @a=100; +execute s using @a; +show binlog events from 98; +Log_name Pos Event_type Server_id End_log_pos Info +slave-bin.000001 98 Query 1 184 use `test`; create table t1 (a int) +slave-bin.000001 184 User var 2 226 @`a`=98 +slave-bin.000001 226 Query 1 320 use `test`; insert into t1 values (@a),(98) +slave-bin.000001 320 Query 1 409 use `test`; insert into t1 values (99) +slave-bin.000001 409 Query 1 507 use `test`; insert into t1 select 100 limit 100 +select * from t1; +a +98 +98 +99 +100 +drop table t1; +create table t1(a int, b int); +prepare s1 from 'insert into t1 values (@x:=@x+1, ?)'; +set @x=1; +execute s1 using @x; +select * from t1; +a b +2 1 +select * from t1; +a b +2 1 +drop table t1; End of 5.0 tests. -DROP TABLE t1; -DROP TABLE t2; -DROP TABLE IF EXISTS t1; DROP FUNCTION IF EXISTS f1; DROP FUNCTION IF EXISTS f2; CREATE TABLE t1 (i INT); diff --git a/mysql-test/r/type_float.result b/mysql-test/r/type_float.result index 188963c5bdf..53844d2cfe2 100644 --- a/mysql-test/r/type_float.result +++ b/mysql-test/r/type_float.result @@ -344,3 +344,36 @@ create table t1 (s1 float(0,2)); ERROR 42000: For float(M,D), double(M,D) or decimal(M,D), M must be >= D (column 's1'). create table t1 (s1 float(1,2)); ERROR 42000: For float(M,D), double(M,D) or decimal(M,D), M must be >= D (column 's1'). +create table t1 (f1 double(200, 0)); +insert into t1 values (1e199), (-1e199); +insert into t1 values (1e200), (-1e200); +insert into t1 values (2e200), (-2e200); +Warnings: +Warning 1264 Out of range value adjusted for column 'f1' at row 1 +Warning 1264 Out of range value adjusted for column 'f1' at row 2 +select f1 + 0e0 from t1; +f1 + 0e0 +1e+199 +-1e+199 +1e+200 +-1e+200 +1e+200 +-1e+200 +drop table t1; +create table t1 (f1 float(30, 0)); +insert into t1 values (1e29), (-1e29); +insert into t1 values (1e30), (-1e30); +insert into t1 values (2e30), (-2e30); +Warnings: +Warning 1264 Out of range value adjusted for column 'f1' at row 1 +Warning 1264 Out of range value adjusted for column 'f1' at row 2 +select f1 + 0e0 from t1; +f1 + 0e0 +1.0000000150475e+29 +-1.0000000150475e+29 +1.0000000150475e+30 +-1.0000000150475e+30 +1.0000000150475e+30 +-1.0000000150475e+30 +drop table t1; +End of 5.0 tests diff --git a/mysql-test/t/ctype_cp932_binlog.test b/mysql-test/t/ctype_cp932_binlog.test index ee0e588fdae..443036910d0 100644 --- a/mysql-test/t/ctype_cp932_binlog.test +++ b/mysql-test/t/ctype_cp932_binlog.test @@ -51,7 +51,7 @@ CALL bug18293("Foo's a Bar", _cp932 0xED40ED41ED42, 47.93)| SELECT HEX(s1),HEX(s2),d FROM t4| DROP PROCEDURE bug18293| DROP TABLE t4| -SHOW BINLOG EVENTS FROM 402| +SHOW BINLOG EVENTS FROM 362| delimiter ;| # End of 5.0 tests diff --git a/mysql-test/t/ctype_ucs2_def.test b/mysql-test/t/ctype_ucs2_def.test index e435d1fb07d..050710b208b 100644 --- a/mysql-test/t/ctype_ucs2_def.test +++ b/mysql-test/t/ctype_ucs2_def.test @@ -14,3 +14,19 @@ DROP TABLE IF EXISTS t1; --enable_warnings create table t1 (a int); drop table t1; + +# +# Bug #27643: query failed : 1114 (The table '' is full) +# +# Check that HASH indexes ignore trailing spaces when comparing +# strings with the ucs2_bin collation + +CREATE TABLE t1(col1 VARCHAR(32) CHARACTER SET ucs2 COLLATE ucs2_bin NOT NULL, + col2 VARCHAR(32) CHARACTER SET ucs2 COLLATE ucs2_bin NOT NULL, + UNIQUE KEY key1 USING HASH (col1, col2)) ENGINE=MEMORY; +INSERT INTO t1 VALUES('A', 'A'), ('B', 'B'), ('C', 'C'); +--error ER_DUP_ENTRY +INSERT INTO t1 VALUES('A ', 'A '); +DROP TABLE t1; + +--echo End of 5.0 tests diff --git a/mysql-test/t/grant.test b/mysql-test/t/grant.test index aa43e4225c5..32eb262fd51 100644 --- a/mysql-test/t/grant.test +++ b/mysql-test/t/grant.test @@ -890,7 +890,7 @@ REVOKE EXECUTE ON PROCEDURE t1 FROM some_user_name@1234567890abcdefghij123456789 # Bug #6774: Replication fails with Wrong usage of DB GRANT and GLOBAL PRIVILEGES # # Check if GRANT ... ON * ... fails when no database is selected -connect (con1, localhost, root,,*NO-ONE*) +connect (con1, localhost, root,,*NO-ONE*); connection con1; --error ER_NO_DB_ERROR GRANT PROCESS ON * TO user@localhost; diff --git a/mysql-test/t/heap_hash.test b/mysql-test/t/heap_hash.test index 28a75a5ee11..c0f37fe490e 100644 --- a/mysql-test/t/heap_hash.test +++ b/mysql-test/t/heap_hash.test @@ -260,4 +260,27 @@ select a from t1 where a in (1,3); explain select a from t1 where a in (1,3); drop table t1; -# End of 4.1 tests +--echo End of 4.1 tests + +# +# Bug #27643: query failed : 1114 (The table '' is full) +# +# Check that HASH indexes disregard trailing spaces when comparing +# strings with binary collations + +CREATE TABLE t1(col1 VARCHAR(32) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, + col2 VARCHAR(32) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, + UNIQUE KEY key1 USING HASH (col1, col2)) ENGINE=MEMORY; +INSERT INTO t1 VALUES('A', 'A'); +--error ER_DUP_ENTRY +INSERT INTO t1 VALUES('A ', 'A '); +DROP TABLE t1; +CREATE TABLE t1(col1 VARCHAR(32) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL, + col2 VARCHAR(32) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL, + UNIQUE KEY key1 USING HASH (col1, col2)) ENGINE=MEMORY; +INSERT INTO t1 VALUES('A', 'A'); +--error ER_DUP_ENTRY +INSERT INTO t1 VALUES('A ', 'A '); +DROP TABLE t1; + +--echo End of 5.0 tests diff --git a/mysql-test/t/innodb_mysql.test b/mysql-test/t/innodb_mysql.test index d9e50add8bf..e6d94fe1627 100644 --- a/mysql-test/t/innodb_mysql.test +++ b/mysql-test/t/innodb_mysql.test @@ -597,4 +597,12 @@ EXPLAIN SELECT COUNT(*) FROM t2 WHERE stat_id IN (1,3) AND acct_id=785; DROP TABLE t1,t2; +# +# Bug #28652: assert when alter innodb table operation +# +create table t1(a int) engine=innodb; +alter table t1 comment '123'; +show create table t1; +drop table t1; + --echo End of 5.0 tests diff --git a/mysql-test/t/limit.test b/mysql-test/t/limit.test index bc599b20d36..286c04785ff 100644 --- a/mysql-test/t/limit.test +++ b/mysql-test/t/limit.test @@ -71,3 +71,20 @@ explain select sum(a) c FROM t1 WHERE a > 0 ORDER BY c LIMIT 3; select sum(a) c FROM t1 WHERE a > 0 ORDER BY c LIMIT 3; drop table t1; # End of 4.1 tests + +# +# Bug #28464: a string argument to 'limit ?' PS +# + +prepare s from "select 1 limit ?"; +set @a='qwe'; +--error 1210 +execute s using @a; +prepare s from "select 1 limit 1, ?"; +--error 1210 +execute s using @a; +prepare s from "select 1 limit ?, ?"; +--error 1210 +execute s using @a, @a; + +--echo End of 5.0 tests diff --git a/mysql-test/t/mysqltest.test b/mysql-test/t/mysqltest.test index 54d17df1fd9..d7c9945fe18 100644 --- a/mysql-test/t/mysqltest.test +++ b/mysql-test/t/mysqltest.test @@ -1222,11 +1222,9 @@ select "a" as col1, "c" as col2; # Test sync_with_master # ---------------------------------------------------------------------------- --error 1 ---exec echo "save_master_pos; sync_with_master 10!;" | $MYSQL_TEST 2>&1 +--exec echo "sync_with_master 10!;" | $MYSQL_TEST 2>&1 --error 1 ---exec echo "save_master_pos; sync_with_master 10 !;" | $MYSQL_TEST 2>&1 ---error 1 ---exec echo "save_master_pos; sync_with_master a;" | $MYSQL_TEST 2>&1 +--exec echo "sync_with_master a;" | $MYSQL_TEST 2>&1 # ---------------------------------------------------------------------------- # Test connect @@ -1871,5 +1869,127 @@ DROP TABLE t1; --error 1 --exec $MYSQL_TEST a b c 2>&1 > /dev/null --enable_abort_on_error +--enable_query_log + +# ---------------------------------------------------------------------------- +# test for query_get_value +# ---------------------------------------------------------------------------- + +CREATE TABLE t1( + a int, b varchar(255), c datetime +); +SHOW COLUMNS FROM t1; + +#------------ Positive tests ------------ +# 1. constant parameters +# value is simple string without spaces +let $value= query_get_value(SHOW COLUMNS FROM t1, Type, 1); +--echo statement=SHOW COLUMNS FROM t1 row_number=1, column_name="Type", Value=$value +let $value= query_get_value("SHOW COLUMNS FROM t1", Type, 1); +--echo statement="SHOW COLUMNS FROM t1" row_number=1, column_name="Type", Value=$value +# +# 2. $variables as parameters +# value IS NULL +let $my_show= SHOW COLUMNS FROM t1; +let $column_name= Default; +let $row_number= 1; +let $value= query_get_value($my_show, $column_name, $row_number); +--echo statement=$my_show row_number=$row_number, column_name=$column_name, Value=$value +# +# 3. result set of a SELECT (not recommended, because projection and +# selection could be done much better by pure SELECT functionality) +# value is string with space in the middle +let $value= query_get_value(SELECT 'A B' AS "MyColumn", MyColumn, 1); +--echo value= ->$value<- +# +# 4. column name with space +let $value= query_get_value(SELECT 1 AS "My Column", My Column, 1); +--echo value= $value +# +#------------ Negative tests ------------ +# 5. Incomplete statement including missing parameters +# 5.1 incomplete statement +--error 1 +--exec echo "let \$value= query_get_value(SHOW;" | $MYSQL_TEST 2>&1 +# 5.2 missing query +--error 1 +--exec echo "let \$value= query_get_value;" | $MYSQL_TEST 2>&1 +# 5.3 missing column name +--error 1 +--exec echo "let \$value= query_get_value(SHOW COLUMNS FROM t1);" | $MYSQL_TEST 2>&1 +# 5.4 missing row number +--error 1 +--exec echo "let \$value= query_get_value(SHOW COLUMNS FROM t1, Field);" | $MYSQL_TEST 2>&1 +# +# 6. Somehow "wrong" value of parameters +# 6.1 row parameter +# 6.1.1 non sense number 0 +let $value= initialized; +let $value= query_get_value(SHOW COLUMNS FROM t1, Field, 0); +--echo value= $value +# 6.1.2 after the last row +let $value= initialized; +let $value= query_get_value(SHOW COLUMNS FROM t1, Field, 10); +--echo value= $value +# 6.1.3 invalid row number +--error 1 +--exec echo "let \$value= query_get_value(SHOW COLUMNS FROM t1, Field, notnumber);" | $MYSQL_TEST 2>&1 +# 6.2 column name parameter, name of not existing column +--error 1 +--exec echo "let \$value= query_get_value(SHOW COLUMNS FROM t1, column_not_exists, 1);" | $MYSQL_TEST 2>&1 +# 6.3. statement which never gives a result set +--error 1 +--exec echo "let \$value= query_get_value(SET @A = 1, Field, 1);" | $MYSQL_TEST 2>&1 +# 6.4. statement contains a "," +# Note: There is no need to improve this, because we need query_get_value +# for SHOW commands only. +--error 1 +--exec echo "let \$value= query_get_value(SELECT 1 AS "A", 1 AS "B", 1);" | $MYSQL_TEST 2>&1 +# +# 7. empty result set +let $value= initialized; +let $value= query_get_value(SELECT a FROM t1, a, 1); +--echo value= $value +# +# 9. failing statement +--error 1 +--exec echo "let \$value= query_get_value(SHOW COLNS FROM t1, Field, 1);" | $MYSQL_TEST 2>&1 +# +# 10. Artificial example how to process a complete SHOW result set: +let $show_statement= SHOW COLUMNS FROM t1; +let $rowno= 1; +let $run=1; +let $count= 0; +--echo +--echo Field Type Null Key Default Extra +while ($run) +{ + let $Field= query_get_value($show_statement, Field, $rowno); + if (`SELECT '$Field' = 'No such row'`) + { + let $run= 0; + } + if (`SELECT '$Field' <> 'No such row'`) + { + let $Type= query_get_value($show_statement, Type, $rowno); + let $Null= query_get_value($show_statement, Null, $rowno); + if (`SELECT '$Null' = 'YES'`) + { + inc $count; + } + let $Key= query_get_value($show_statement, Key, $rowno); + let $Default= query_get_value($show_statement, Default, $rowno); + let $Extra= query_get_value($show_statement, Extra, $rowno); + --echo $Field $Type $Null ->$Key<- $Default $Extra + inc $rowno; + } +} +--echo +--echo Number of columns with Default NULL: $count +--echo +eval $show_statement; + +drop table t1; --echo End of tests + diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index 5b7adc40755..93a89c2b275 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -1791,5 +1791,13 @@ execute stmt; deallocate prepare stmt; drop tables t1; +# +# Bug #28509: strange behaviour: passing a decimal value to PS +# +prepare stmt from "create table t1 select ?"; +set @a=1.0; +execute stmt using @a; +show create table t1; +drop table t1; --echo End of 5.0 tests. diff --git a/mysql-test/t/rpl_packet.test b/mysql-test/t/rpl_packet.test index db6f475dc94..f410b561663 100644 --- a/mysql-test/t/rpl_packet.test +++ b/mysql-test/t/rpl_packet.test @@ -56,7 +56,7 @@ START SLAVE; # Reconnect to master for new setting to take effect disconnect master; -connect (master, localhost, root) +connect (master, localhost, root); connection master; CREATE TABLe `t1` (`f1` LONGTEXT) ENGINE=MyISAM; diff --git a/mysql-test/t/rpl_rotate_logs.test b/mysql-test/t/rpl_rotate_logs.test index 5d9f1c29fe2..01f556c3c8f 100644 --- a/mysql-test/t/rpl_rotate_logs.test +++ b/mysql-test/t/rpl_rotate_logs.test @@ -107,9 +107,18 @@ show master logs; # we just tests if synonyms are accepted purge binary logs to 'master-bin.000002'; show binary logs; -# sleeping 10 seconds or more would make the slave believe connection is down ---real_sleep 1 -purge master logs before now(); + +# Calculate time to use in "purge master logs before" by taking +# last modification time of t2 and adding 1 second +# This is donw in order to handle the case where file system +# time differs from mysqld's time +--disable_result_log +select @time_for_purge:=DATE_ADD(UPDATE_TIME, INTERVAL 1 SECOND) + from information_schema.tables + where TABLE_SCHEMA="test" and TABLE_NAME="t2"; +--enable_result_log + +purge master logs before (@time_for_purge); show binary logs; insert into t2 values (65); sync_slave_with_master; diff --git a/mysql-test/t/rpl_user_variables.test b/mysql-test/t/rpl_user_variables.test index b2f4bfbb29d..8f8f0accbd1 100644 --- a/mysql-test/t/rpl_user_variables.test +++ b/mysql-test/t/rpl_user_variables.test @@ -296,13 +296,48 @@ SELECT * from t1; SELECT * from t2; connection master; +drop table t1, t2; ---echo End of 5.0 tests. +# +# Bug #26842: master binary log contains invalid queries - replication fails +# +save_master_pos; +connection slave; +sync_with_master; +reset master; -# Cleanup +connection master; +create table t1 (a int); +prepare s from "insert into t1 values (@a),(?)"; +set @a=98; execute s using @a; +prepare s from "insert into t1 values (?)"; +set @a=99; execute s using @a; +prepare s from "insert into t1 select 100 limit ?"; +set @a=100; execute s using @a; -DROP TABLE t1; -DROP TABLE t2; +save_master_pos; +connection slave; +sync_with_master; +show binlog events from 98; +select * from t1; +connection master; +drop table t1; + +# +# Bug #12826: Possible to get inconsistent slave using SQL syntax Prepared Statements +# +connection master; +create table t1(a int, b int); +prepare s1 from 'insert into t1 values (@x:=@x+1, ?)'; +set @x=1; execute s1 using @x; +select * from t1; +sync_slave_with_master; +connection slave; +select * from t1; +connection master; +drop table t1; + +--echo End of 5.0 tests. # This test uses a stored function that uses user-defined variables to return data # The test ensures the value of the user-defined variable is replicated correctly @@ -310,7 +345,6 @@ DROP TABLE t2; # This test was constructed for BUG#20141 --disable_warnings -DROP TABLE IF EXISTS t1; DROP FUNCTION IF EXISTS f1; DROP FUNCTION IF EXISTS f2; --enable_warnings @@ -358,4 +392,3 @@ DROP TABLE t1; sync_slave_with_master; stop slave; - diff --git a/mysql-test/t/type_float.test b/mysql-test/t/type_float.test index f790bcf6daa..a55200c8853 100644 --- a/mysql-test/t/type_float.test +++ b/mysql-test/t/type_float.test @@ -222,3 +222,23 @@ drop table t1; create table t1 (s1 float(0,2)); --error 1427 create table t1 (s1 float(1,2)); + +# +# Bug #28121 "INSERT or UPDATE into DOUBLE(200,0) field being truncated to 31 digits" +# + +create table t1 (f1 double(200, 0)); +insert into t1 values (1e199), (-1e199); +insert into t1 values (1e200), (-1e200); +insert into t1 values (2e200), (-2e200); +select f1 + 0e0 from t1; +drop table t1; + +create table t1 (f1 float(30, 0)); +insert into t1 values (1e29), (-1e29); +insert into t1 values (1e30), (-1e30); +insert into t1 values (2e30), (-2e30); +select f1 + 0e0 from t1; +drop table t1; + +--echo End of 5.0 tests diff --git a/mysys/my_init.c b/mysys/my_init.c index 2bcf5f44c4d..32d3f07fd31 100644 --- a/mysys/my_init.c +++ b/mysys/my_init.c @@ -262,6 +262,34 @@ void my_parameter_handler(const wchar_t * expression, const wchar_t * function, } +#ifdef __MSVC_RUNTIME_CHECKS +#include <rtcapi.h> + +/* Turn off runtime checks for 'handle_rtc_failure' */ +#pragma runtime_checks("", off) + +/* + handle_rtc_failure + Catch the RTC error and dump it to stderr +*/ + +int handle_rtc_failure(int err_type, const char *file, int line, + const char* module, const char *format, ...) +{ + va_list args; + va_start(args, format); + fprintf(stderr, "Error:"); + vfprintf(stderr, format, args); + fprintf(stderr, " At %s:%d\n", file, line); + va_end(args); + (void) fflush(stderr); + + return 0; /* Error is handled */ +} +#pragma runtime_checks("", on) +#endif + + static void my_win_init(void) { HKEY hSoftMysql ; @@ -292,6 +320,14 @@ static void my_win_init(void) _set_invalid_parameter_handler(my_parameter_handler); #endif #endif +#ifdef __MSVC_RUNTIME_CHECKS + /* + Install handler to send RTC (Runtime Error Check) warnings + to log file + */ + _RTC_SetErrorFunc(handle_rtc_failure); +#endif + _tzset(); /* apre la chiave HKEY_LOCAL_MACHINES\software\MySQL */ diff --git a/server-tools/instance-manager/mysql_connection.cc b/server-tools/instance-manager/mysql_connection.cc index 3e1694e24ee..2b377d60ad0 100644 --- a/server-tools/instance-manager/mysql_connection.cc +++ b/server-tools/instance-manager/mysql_connection.cc @@ -112,8 +112,8 @@ C_MODE_START void my_net_local_init(NET *net) { net->max_packet= net_buffer_length; - net->read_timeout= net_read_timeout; - net->write_timeout= net_write_timeout; + my_net_set_read_timeout(net, (uint)net_read_timeout); + my_net_set_write_timeout(net, (uint)net_write_timeout); net->retry_count= net_retry_count; net->max_packet_size= max_allowed_packet; } diff --git a/sql-common/client.c b/sql-common/client.c index 3342db4bcfe..40512da0492 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -2047,13 +2047,11 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, /* If user set read_timeout, let it override the default */ if (mysql->options.read_timeout) - net->read_timeout= mysql->options.read_timeout; - vio_timeout(net->vio, 0, net->read_timeout); + my_net_set_read_timeout(net, mysql->options.read_timeout); /* If user set write_timeout, let it override the default */ if (mysql->options.write_timeout) - net->write_timeout= mysql->options.write_timeout; - vio_timeout(net->vio, 1, net->write_timeout); + my_net_set_write_timeout(net, mysql->options.write_timeout); if (mysql->options.max_allowed_packet) net->max_packet_size= mysql->options.max_allowed_packet; diff --git a/sql/field.cc b/sql/field.cc index 8ff615ee798..83c17c43ee4 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -3675,56 +3675,9 @@ int Field_float::store(const char *from,uint len,CHARSET_INFO *cs) int Field_float::store(double nr) { - float j; - int error= 0; + int error= truncate(&nr, FLT_MAX); + float j= (float)nr; - if (isnan(nr)) - { - j= 0; - set_null(); - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); - error= 1; - } - else if (unsigned_flag && nr < 0) - { - j= 0; - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); - error= 1; - } - else - { - double max_value; - if (dec >= NOT_FIXED_DEC) - { - max_value= FLT_MAX; - } - else - { - uint tmp=min(field_length,array_elements(log_10)-1); - max_value= (log_10[tmp]-1)/log_10[dec]; - /* - The following comparison is needed to not get an overflow if nr - is close to FLT_MAX - */ - if (fabs(nr) < FLT_MAX/10.0e+32) - nr= floor(nr*log_10[dec]+0.5)/log_10[dec]; - } - if (nr < -max_value) - { - j= (float)-max_value; - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); - error= 1; - } - else if (nr > max_value) - { - j= (float)max_value; - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); - error= 1; - } - else - j= (float) nr; - } - #ifdef WORDS_BIGENDIAN if (table->s->db_low_byte_first) { @@ -3963,48 +3916,7 @@ int Field_double::store(const char *from,uint len,CHARSET_INFO *cs) int Field_double::store(double nr) { - int error= 0; - - if (isnan(nr)) - { - nr= 0; - set_null(); - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); - error= 1; - } - else if (unsigned_flag && nr < 0) - { - nr= 0; - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); - error= 1; - } - else - { - double max_value; - if (not_fixed) - { - max_value= DBL_MAX; - } - else - { - uint tmp=min(field_length,array_elements(log_10)-1); - max_value= (log_10[tmp]-1)/log_10[dec]; - if (fabs(nr) < DBL_MAX/10.0e+32) - nr= floor(nr*log_10[dec]+0.5)/log_10[dec]; - } - if (nr < -max_value) - { - nr= -max_value; - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); - error= 1; - } - else if (nr > max_value) - { - nr= max_value; - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); - error= 1; - } - } + int error= truncate(&nr, DBL_MAX); #ifdef WORDS_BIGENDIAN if (table->s->db_low_byte_first) @@ -4023,6 +3935,63 @@ int Field_double::store(longlong nr, bool unsigned_val) return store(unsigned_val ? ulonglong2double((ulonglong) nr) : (double) nr); } +/* + If a field has fixed length, truncate the double argument pointed to by 'nr' + appropriately. + Also ensure that the argument is within [-max_value; max_value] range. +*/ + +int Field_real::truncate(double *nr, double max_value) +{ + int error= 1; + double res= *nr; + + if (isnan(res)) + { + res= 0; + set_null(); + set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + goto end; + } + else if (unsigned_flag && res < 0) + { + res= 0; + set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + goto end; + } + + if (!not_fixed) + { + uint order= field_length - dec; + uint step= array_elements(log_10) - 1; + max_value= 1.0; + for (; order > step; order-= step) + max_value*= log_10[step]; + max_value*= log_10[order]; + max_value-= 1.0 / log_10[dec]; + + double tmp= rint((res - floor(res)) * log_10[dec]) / log_10[dec]; + res= floor(res) + tmp; + } + + if (res < -max_value) + { + res= -max_value; + set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + } + else if (res > max_value) + { + res= max_value; + set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + } + else + error= 0; + +end: + *nr= res; + return error; +} + int Field_real::store_decimal(const my_decimal *dm) { diff --git a/sql/field.h b/sql/field.h index 37ce6b88453..46efb150205 100644 --- a/sql/field.h +++ b/sql/field.h @@ -453,6 +453,7 @@ public: /* base class for float and double and decimal (old one) */ class Field_real :public Field_num { public: + my_bool not_fixed; Field_real(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, utype unireg_check_arg, @@ -460,13 +461,16 @@ public: struct st_table *table_arg, uint8 dec_arg, bool zero_arg, bool unsigned_arg) :Field_num(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, - field_name_arg, table_arg, dec_arg, zero_arg, unsigned_arg) + field_name_arg, table_arg, dec_arg, zero_arg, unsigned_arg), + not_fixed(dec_arg >= NOT_FIXED_DEC) {} int store_decimal(const my_decimal *); my_decimal *val_decimal(my_decimal *); + int truncate(double *nr, double max_length); uint32 max_display_length() { return field_length; } + uint size_of() const { return sizeof(*this); } }; @@ -758,7 +762,6 @@ public: class Field_double :public Field_real { public: - my_bool not_fixed; Field_double(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const char *field_name_arg, @@ -766,21 +769,18 @@ public: uint8 dec_arg,bool zero_arg,bool unsigned_arg) :Field_real(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, table_arg, - dec_arg, zero_arg, unsigned_arg), - not_fixed(dec_arg >= NOT_FIXED_DEC) + dec_arg, zero_arg, unsigned_arg) {} Field_double(uint32 len_arg, bool maybe_null_arg, const char *field_name_arg, struct st_table *table_arg, uint8 dec_arg) :Field_real((char*) 0, len_arg, maybe_null_arg ? (uchar*) "" : 0, (uint) 0, - NONE, field_name_arg, table_arg, dec_arg, 0, 0), - not_fixed(dec_arg >= NOT_FIXED_DEC) + NONE, field_name_arg, table_arg, dec_arg, 0, 0) {} Field_double(uint32 len_arg, bool maybe_null_arg, const char *field_name_arg, - struct st_table *table_arg, uint8 dec_arg, my_bool not_fixed_srg) + struct st_table *table_arg, uint8 dec_arg, my_bool not_fixed_arg) :Field_real((char*) 0, len_arg, maybe_null_arg ? (uchar*) "" : 0, (uint) 0, - NONE, field_name_arg, table_arg, dec_arg, 0, 0), - not_fixed(not_fixed_srg) - {} + NONE, field_name_arg, table_arg, dec_arg, 0, 0) + {not_fixed= not_fixed_arg; } enum_field_types type() const { return FIELD_TYPE_DOUBLE;} enum ha_base_keytype key_type() const { return HA_KEYTYPE_DOUBLE; } int store(const char *to,uint length,CHARSET_INFO *charset); @@ -795,7 +795,6 @@ public: void sort_string(char *buff,uint length); uint32 pack_length() const { return sizeof(double); } void sql_type(String &str) const; - uint size_of() const { return sizeof(*this); } }; diff --git a/sql/init.cc b/sql/init.cc index ad55a2a8b24..b3b68926683 100644 --- a/sql/init.cc +++ b/sql/init.cc @@ -21,8 +21,6 @@ void unireg_init(ulong options) { - uint i; - double nr; DBUG_ENTER("unireg_init"); MYSYS_PROGRAM_DONT_USE_CURSES(); @@ -39,16 +37,5 @@ void unireg_init(ulong options) VOID(strmov(reg_ext,".frm")); specialflag=SPECIAL_SAME_DB_NAME | options; /* Set options from argv */ - /* Make a tab of powers of 10 */ - for (i=0,nr=1.0; i < array_elements(log_10) ; i++) - { /* It's used by filesort... */ - log_10[i]= nr ; nr*= 10.0; - } - /* Make a tab of powers of 0.1 */ - for (i= 0, nr= 0.1; i < array_elements(log_01); i++) - { - log_01[i]= nr; - nr*= 0.1; - } DBUG_VOID_RETURN; } diff --git a/sql/item.cc b/sql/item.cc index 92ea35072f9..a5dfa0db6b6 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -2313,6 +2313,7 @@ default_set_param_func(Item_param *param, Item_param::Item_param(unsigned pos_in_query_arg) : + strict_type(FALSE), state(NO_VALUE), item_result_type(STRING_RESULT), /* Don't pretend to be a literal unless value for this item is set. */ @@ -2507,16 +2508,16 @@ bool Item_param::set_from_user_var(THD *thd, const user_var_entry *entry) if (entry && entry->value) { item_result_type= entry->type; - switch (entry->type) { + if (strict_type && required_result_type != item_result_type) + DBUG_RETURN(1); + switch (item_result_type) { case REAL_RESULT: set_double(*(double*)entry->value); item_type= Item::REAL_ITEM; - item_result_type= REAL_RESULT; break; case INT_RESULT: set_int(*(longlong*)entry->value, MY_INT64_NUM_DECIMAL_DIGITS); item_type= Item::INT_ITEM; - item_result_type= INT_RESULT; break; case STRING_RESULT: { @@ -2538,7 +2539,6 @@ bool Item_param::set_from_user_var(THD *thd, const user_var_entry *entry) charset of connection, so we have to set it later. */ item_type= Item::STRING_ITEM; - item_result_type= STRING_RESULT; if (set_str((const char *)entry->value, entry->length)) DBUG_RETURN(1); @@ -2552,6 +2552,7 @@ bool Item_param::set_from_user_var(THD *thd, const user_var_entry *entry) decimals= ent_value->frac; max_length= my_decimal_precision_to_length(ent_value->precision(), decimals, unsigned_flag); + item_type= Item::DECIMAL_ITEM; break; } default: diff --git a/sql/item.h b/sql/item.h index 11dce3a7758..a1704aa6103 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1359,8 +1359,10 @@ class Item_param :public Item char cnvbuf[MAX_FIELD_WIDTH]; String cnvstr; Item *cnvitem; -public: + bool strict_type; + enum Item_result required_result_type; +public: enum enum_item_param_state { NO_VALUE, NULL_VALUE, INT_VALUE, REAL_VALUE, @@ -1488,6 +1490,11 @@ public: Otherwise return FALSE. */ bool eq(const Item *item, bool binary_cmp) const; + void set_strict_type(enum Item_result result_type_arg) + { + strict_type= TRUE; + required_result_type= result_type_arg; + } }; diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 06c825334c2..516d0fcf3e1 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -507,7 +507,7 @@ int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type) { if ((*a)->decimals < NOT_FIXED_DEC && (*b)->decimals < NOT_FIXED_DEC) { - precision= 5 * log_01[max((*a)->decimals, (*b)->decimals)]; + precision= 5 / log_10[max((*a)->decimals, (*b)->decimals) + 1]; if (func == &Arg_comparator::compare_real) func= &Arg_comparator::compare_real_fixed; else if (func == &Arg_comparator::compare_e_real) diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 7a307c3be85..0aaa1744fe1 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -89,9 +89,6 @@ void kill_one_thread(THD *thd, ulong id, bool only_kill_query); bool net_request_file(NET* net, const char* fname); char* query_table_status(THD *thd,const char *db,const char *table_name); -void net_set_write_timeout(NET *net, uint timeout); -void net_set_read_timeout(NET *net, uint timeout); - #define x_free(A) { my_free((gptr) (A),MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR)); } #define safeFree(x) { if(x) { my_free((gptr) x,MYF(0)); x = NULL; } } #define PREV_BITS(type,A) ((type) (((type) 1 << (A)) -1)) @@ -179,7 +176,7 @@ MY_LOCALE *my_locale_by_number(uint number); #define STACK_MIN_SIZE 12000 // Abort if less stack during eval. #define STACK_MIN_SIZE_FOR_OPEN 1024*80 -#define STACK_BUFF_ALLOC 256 // For stack overrun checks +#define STACK_BUFF_ALLOC 352 // For stack overrun checks #ifndef MYSQLD_NET_RETRY_COUNT #define MYSQLD_NET_RETRY_COUNT 10 // Abort read after this many int. #endif @@ -1271,8 +1268,6 @@ extern char language[FN_REFLEN], reg_ext[FN_EXTLEN]; extern char glob_hostname[FN_REFLEN], mysql_home[FN_REFLEN]; extern char pidfile_name[FN_REFLEN], system_time_zone[30], *opt_init_file; extern char log_error_file[FN_REFLEN], *opt_tc_log_file; -extern double log_10[32]; -extern double log_01[32]; extern ulonglong log_10_int[20]; extern ulonglong keybuff_size; extern ulonglong thd_startup_options; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index ce6e49249e0..d01e56d0fb2 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -442,8 +442,6 @@ ulong slow_launch_threads = 0, sync_binlog_period; ulong expire_logs_days = 0; ulong rpl_recovery_rank=0; -double log_10[32]; /* 10 potences */ -double log_01[32]; time_t server_start_time; char mysql_home[FN_REFLEN], pidfile_name[FN_REFLEN], system_time_zone[30]; @@ -2156,6 +2154,16 @@ later when used with nscd), disable LDAP in your nsswitch.conf, or use a\n\ mysqld that is not statically linked.\n"); #endif +#ifdef HAVE_NPTL + if (thd_lib_detected == THD_LIB_LT && !getenv("LD_ASSUME_KERNEL")) + fprintf(stderr,"\n\ +You are running a statically-linked LinuxThreads binary on an NPTL system.\n\ +This can result in crashes on some distributions due to LT/NPTL conflicts.\n\ +You should either build a dynamically-linked binary, or force LinuxThreads\n\ +to be used with the LD_ASSUME_KERNEL environment variable. Please consult\n\ +the documentation for your distribution on how to do that.\n"); +#endif + if (locked_in_memory) { fprintf(stderr, "\n\ diff --git a/sql/net_serv.cc b/sql/net_serv.cc index a635d058cd5..c56e9c0b073 100644 --- a/sql/net_serv.cc +++ b/sql/net_serv.cc @@ -609,10 +609,10 @@ net_real_write(NET *net,const char *packet,ulong len) #ifndef NO_ALARM thr_alarm_init(&alarmed); if (net_blocking) - thr_alarm(&alarmed,(uint) net->write_timeout,&alarm_buff); + thr_alarm(&alarmed, net->write_timeout, &alarm_buff); #else alarmed=0; - /* Write timeout is set in net_set_write_timeout */ + /* Write timeout is set in my_net_set_write_timeout */ #endif /* NO_ALARM */ pos=(char*) packet; end=pos+len; @@ -624,7 +624,7 @@ net_real_write(NET *net,const char *packet,ulong len) #if (!defined(__WIN__) && !defined(__EMX__) && !defined(OS2)) if ((interrupted || length==0) && !thr_alarm_in_use(&alarmed)) { - if (!thr_alarm(&alarmed,(uint) net->write_timeout,&alarm_buff)) + if (!thr_alarm(&alarmed, net->write_timeout, &alarm_buff)) { /* Always true for client */ my_bool old_mode; while (vio_blocking(net->vio, TRUE, &old_mode) < 0) @@ -805,7 +805,7 @@ my_real_read(NET *net, ulong *complen) if (net_blocking) thr_alarm(&alarmed,net->read_timeout,&alarm_buff); #else - /* Read timeout is set in net_set_read_timeout */ + /* Read timeout is set in my_net_set_read_timeout */ #endif /* NO_ALARM */ pos = net->buff + net->where_b; /* net->packet -4 */ @@ -1117,25 +1117,27 @@ my_net_read(NET *net) } -void net_set_read_timeout(NET *net, uint timeout) +void my_net_set_read_timeout(NET *net, uint timeout) { - DBUG_ENTER("net_set_read_timeout"); + DBUG_ENTER("my_net_set_read_timeout"); DBUG_PRINT("enter", ("timeout: %d", timeout)); net->read_timeout= timeout; #ifdef NO_ALARM - vio_timeout(net->vio, 0, timeout); + if (net->vio) + vio_timeout(net->vio, 0, timeout); #endif DBUG_VOID_RETURN; } -void net_set_write_timeout(NET *net, uint timeout) +void my_net_set_write_timeout(NET *net, uint timeout) { - DBUG_ENTER("net_set_write_timeout"); + DBUG_ENTER("my_net_set_write_timeout"); DBUG_PRINT("enter", ("timeout: %d", timeout)); net->write_timeout= timeout; #ifdef NO_ALARM - vio_timeout(net->vio, 1, timeout); + if (net->vio) + vio_timeout(net->vio, 1, timeout); #endif DBUG_VOID_RETURN; } diff --git a/sql/set_var.cc b/sql/set_var.cc index daebd924a89..09cdc34f803 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -1295,14 +1295,14 @@ static int check_completion_type(THD *thd, set_var *var) static void fix_net_read_timeout(THD *thd, enum_var_type type) { if (type != OPT_GLOBAL) - net_set_read_timeout(&thd->net, thd->variables.net_read_timeout); + my_net_set_read_timeout(&thd->net, thd->variables.net_read_timeout); } static void fix_net_write_timeout(THD *thd, enum_var_type type) { if (type != OPT_GLOBAL) - net_set_write_timeout(&thd->net, thd->variables.net_write_timeout); + my_net_set_write_timeout(&thd->net, thd->variables.net_write_timeout); } static void fix_net_retry_count(THD *thd, enum_var_type type) diff --git a/sql/sql_client.cc b/sql/sql_client.cc index d6f1183806e..032a2e26e3a 100644 --- a/sql/sql_client.cc +++ b/sql/sql_client.cc @@ -28,8 +28,11 @@ void my_net_local_init(NET *net) { #ifndef EMBEDDED_LIBRARY net->max_packet= (uint) global_system_variables.net_buffer_length; - net->read_timeout= (uint) global_system_variables.net_read_timeout; - net->write_timeout=(uint) global_system_variables.net_write_timeout; + + my_net_set_read_timeout(net, (uint)global_system_variables.net_read_timeout); + my_net_set_write_timeout(net, + (uint)global_system_variables.net_write_timeout); + net->retry_count= (uint) global_system_variables.net_retry_count; net->max_packet_size= max(global_system_variables.net_buffer_length, global_system_variables.max_allowed_packet); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 6277a6c0c10..ec7e8a5f997 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1140,8 +1140,8 @@ pthread_handler_t handle_one_connection(void *arg) net->no_send_error= 0; /* Use "connect_timeout" value during connection phase */ - net_set_read_timeout(net, connect_timeout); - net_set_write_timeout(net, connect_timeout); + my_net_set_read_timeout(net, connect_timeout); + my_net_set_write_timeout(net, connect_timeout); if ((error=check_connection(thd))) { // Wrong permissions @@ -1184,8 +1184,8 @@ pthread_handler_t handle_one_connection(void *arg) } /* Connect completed, set read/write timeouts back to tdefault */ - net_set_read_timeout(net, thd->variables.net_read_timeout); - net_set_write_timeout(net, thd->variables.net_write_timeout); + my_net_set_read_timeout(net, thd->variables.net_read_timeout); + my_net_set_write_timeout(net, thd->variables.net_write_timeout); while (!net->error && net->vio != 0 && !(thd->killed == THD::KILL_CONNECTION)) @@ -1537,7 +1537,7 @@ bool do_command(THD *thd) the client, the connection is closed or "net_wait_timeout" number of seconds has passed */ - net_set_read_timeout(net, thd->variables.net_wait_timeout); + my_net_set_read_timeout(net, thd->variables.net_wait_timeout); thd->clear_error(); // Clear error message @@ -1569,7 +1569,7 @@ bool do_command(THD *thd) } /* Restore read timeout value */ - net_set_read_timeout(net, thd->variables.net_read_timeout); + my_net_set_read_timeout(net, thd->variables.net_read_timeout); /* packet_length contains length of data, as it was stored in packet diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 42655608196..d2f90141fa6 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -969,6 +969,7 @@ static bool insert_params_from_vars_with_log(Prepared_statement *stmt, String buf; const String *val; uint32 length= 0; + THD *thd= stmt->thd; DBUG_ENTER("insert_params_from_vars"); @@ -979,34 +980,20 @@ static bool insert_params_from_vars_with_log(Prepared_statement *stmt, { Item_param *param= *it; varname= var_it++; - if (get_var_with_binlog(stmt->thd, stmt->lex->sql_command, - *varname, &entry)) - DBUG_RETURN(1); - if (param->set_from_user_var(stmt->thd, entry)) + entry= (user_var_entry *) hash_search(&thd->user_vars, (byte*) varname->str, + varname->length); + /* + We have to call the setup_one_conversion_function() here to set + the parameter's members that might be needed further + (e.g. value.cs_info.character_set_client is used in the query_val_str()). + */ + setup_one_conversion_function(thd, param, param->param_type); + if (param->set_from_user_var(thd, entry)) DBUG_RETURN(1); - /* Insert @'escaped-varname' instead of parameter in the query */ - if (entry) - { - char *start, *ptr; - buf.length(0); - if (buf.reserve(entry->name.length*2+3)) - DBUG_RETURN(1); + val= param->query_val_str(&buf); - start= ptr= buf.c_ptr_quick(); - *ptr++= '@'; - *ptr++= '\''; - ptr+= escape_string_for_mysql(&my_charset_utf8_general_ci, - ptr, 0, entry->name.str, - entry->name.length); - *ptr++= '\''; - buf.length(ptr - start); - val= &buf; - } - else - val= &my_null_string; - - if (param->convert_str_value(stmt->thd)) + if (param->convert_str_value(thd)) DBUG_RETURN(1); /* out of memory */ if (query->replace(param->pos_in_query+length, 1, *val)) diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index b451c612398..86ededd5587 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -94,7 +94,7 @@ static int send_file(THD *thd) the job */ old_timeout= net->read_timeout; - net_set_read_timeout(net, thd->variables.net_wait_timeout); + my_net_set_read_timeout(net, thd->variables.net_wait_timeout); /* We need net_flush here because the client will not know it needs to send @@ -138,7 +138,7 @@ static int send_file(THD *thd) error = 0; err: - net_set_read_timeout(net, old_timeout); + my_net_set_read_timeout(net, old_timeout); if (fd >= 0) (void) my_close(fd, MYF(0)); if (errmsg) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 41688794721..d04a6adba15 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -10174,7 +10174,7 @@ bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param, err: DBUG_PRINT("error",("Got error: %d",write_err)); - table->file->print_error(error,MYF(0)); // Give table is full error + table->file->print_error(write_err, MYF(0)); (void) table->file->ha_rnd_end(); (void) new_table.file->close(); err1: diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 29ecf43a531..202882d9a48 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -3797,6 +3797,9 @@ view_err: alter_info->keys_onoff); table->file->external_lock(thd, F_UNLCK); VOID(pthread_mutex_unlock(&LOCK_open)); + error= ha_commit_stmt(thd); + if (ha_commit(thd)) + error= 1; } thd->last_insert_id=next_insert_id; // Needed for correct log @@ -3967,16 +3970,6 @@ view_err: goto err; } } - /* The ALTER TABLE is always in its own transaction */ - error = ha_commit_stmt(thd); - if (ha_commit(thd)) - error=1; - if (error) - { - VOID(pthread_mutex_unlock(&LOCK_open)); - broadcast_refresh(); - goto err; - } thd->proc_info="end"; if (mysql_bin_log.is_open()) { @@ -4225,8 +4218,12 @@ copy_data_between_tables(TABLE *from,TABLE *to, } to->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY); - ha_enable_transaction(thd,TRUE); - + if (ha_enable_transaction(thd, TRUE)) + { + error= 1; + goto err; + } + /* Ensure that the new table is saved properly to disk so that we can do a rename diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 5ae2f6db581..d1da36dfa5b 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -6201,6 +6201,9 @@ limit_options: ; limit_option: param_marker + { + ((Item_param *) $1)->set_strict_type(INT_RESULT); + } | ULONGLONG_NUM { $$= new Item_uint($1.str, $1.length); } | LONG_NUM { $$= new Item_uint($1.str, $1.length); } | NUM { $$= new Item_uint($1.str, $1.length); } diff --git a/strings/ctype-bin.c b/strings/ctype-bin.c index e9de0ade557..f9d29ca1739 100644 --- a/strings/ctype-bin.c +++ b/strings/ctype-bin.c @@ -271,6 +271,29 @@ static int my_wc_mb_bin(CHARSET_INFO *cs __attribute__((unused)), } +void my_hash_sort_8bit_bin(CHARSET_INFO *cs __attribute__((unused)), + const uchar *key, uint len,ulong *nr1, ulong *nr2) +{ + const uchar *pos = key; + + key+= len; + + /* + Remove trailing spaces. We have to do this to be able to compare + 'A ' and 'A' as identical + */ + while (key > pos && key[-1] == ' ') + key--; + + for (; pos < (uchar*) key ; pos++) + { + nr1[0]^=(ulong) ((((uint) nr1[0] & 63)+nr2[0]) * + ((uint)*pos)) + (nr1[0] << 8); + nr2[0]+=3; + } +} + + void my_hash_sort_bin(CHARSET_INFO *cs __attribute__((unused)), const uchar *key, uint len,ulong *nr1, ulong *nr2) { @@ -471,7 +494,7 @@ MY_COLLATION_HANDLER my_collation_8bit_bin_handler = my_wildcmp_bin, my_strcasecmp_bin, my_instr_bin, - my_hash_sort_bin, + my_hash_sort_8bit_bin, my_propagate_simple }; diff --git a/strings/ctype-mb.c b/strings/ctype-mb.c index 40cec669766..c12426b555f 100644 --- a/strings/ctype-mb.c +++ b/strings/ctype-mb.c @@ -467,6 +467,13 @@ static void my_hash_sort_mb_bin(CHARSET_INFO *cs __attribute__((unused)), key+= len; + /* + Remove trailing spaces. We have to do this to be able to compare + 'A ' and 'A' as identical + */ + while (key > pos && key[-1] == ' ') + key--; + for (; pos < (uchar*) key ; pos++) { nr1[0]^=(ulong) ((((uint) nr1[0] & 63)+nr2[0]) * diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c index 6b1ba3c1ef6..f3abbaa6e7e 100644 --- a/strings/ctype-ucs2.c +++ b/strings/ctype-ucs2.c @@ -1484,7 +1484,10 @@ void my_hash_sort_ucs2_bin(CHARSET_INFO *cs __attribute__((unused)), const uchar *pos = key; key+= len; - + + while (key > pos+1 && key[-1] == ' ' && key[-2] == '\0') + key-= 2; + for (; pos < (uchar*) key ; pos++) { nr1[0]^=(ulong) ((((uint) nr1[0] & 63)+nr2[0]) * diff --git a/strings/strtod.c b/strings/strtod.c index 7196cafb2c9..5fe59d10bd2 100644 --- a/strings/strtod.c +++ b/strings/strtod.c @@ -31,13 +31,40 @@ #define MAX_DBL_EXP 308 #define MAX_RESULT_FOR_MAX_EXP 1.7976931348623157 -static double scaler10[] = { - 1.0, 1e10, 1e20, 1e30, 1e40, 1e50, 1e60, 1e70, 1e80, 1e90 -}; -static double scaler1[] = { - 1.0, 10.0, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9 -}; +const double log_10[] = { + 1e000, 1e001, 1e002, 1e003, 1e004, 1e005, 1e006, 1e007, 1e008, 1e009, + 1e010, 1e011, 1e012, 1e013, 1e014, 1e015, 1e016, 1e017, 1e018, 1e019, + 1e020, 1e021, 1e022, 1e023, 1e024, 1e025, 1e026, 1e027, 1e028, 1e029, + 1e030, 1e031, 1e032, 1e033, 1e034, 1e035, 1e036, 1e037, 1e038, 1e039, + 1e040, 1e041, 1e042, 1e043, 1e044, 1e045, 1e046, 1e047, 1e048, 1e049, + 1e050, 1e051, 1e052, 1e053, 1e054, 1e055, 1e056, 1e057, 1e058, 1e059, + 1e060, 1e061, 1e062, 1e063, 1e064, 1e065, 1e066, 1e067, 1e068, 1e069, + 1e070, 1e071, 1e072, 1e073, 1e074, 1e075, 1e076, 1e077, 1e078, 1e079, + 1e080, 1e081, 1e082, 1e083, 1e084, 1e085, 1e086, 1e087, 1e088, 1e089, + 1e090, 1e091, 1e092, 1e093, 1e094, 1e095, 1e096, 1e097, 1e098, 1e099, + 1e100, 1e101, 1e102, 1e103, 1e104, 1e105, 1e106, 1e107, 1e108, 1e109, + 1e110, 1e111, 1e112, 1e113, 1e114, 1e115, 1e116, 1e117, 1e118, 1e119, + 1e120, 1e121, 1e122, 1e123, 1e124, 1e125, 1e126, 1e127, 1e128, 1e129, + 1e130, 1e131, 1e132, 1e133, 1e134, 1e135, 1e136, 1e137, 1e138, 1e139, + 1e140, 1e141, 1e142, 1e143, 1e144, 1e145, 1e146, 1e147, 1e148, 1e149, + 1e150, 1e151, 1e152, 1e153, 1e154, 1e155, 1e156, 1e157, 1e158, 1e159, + 1e160, 1e161, 1e162, 1e163, 1e164, 1e165, 1e166, 1e167, 1e168, 1e169, + 1e170, 1e171, 1e172, 1e173, 1e174, 1e175, 1e176, 1e177, 1e178, 1e179, + 1e180, 1e181, 1e182, 1e183, 1e184, 1e185, 1e186, 1e187, 1e188, 1e189, + 1e190, 1e191, 1e192, 1e193, 1e194, 1e195, 1e196, 1e197, 1e198, 1e199, + 1e200, 1e201, 1e202, 1e203, 1e204, 1e205, 1e206, 1e207, 1e208, 1e209, + 1e210, 1e211, 1e212, 1e213, 1e214, 1e215, 1e216, 1e217, 1e218, 1e219, + 1e220, 1e221, 1e222, 1e223, 1e224, 1e225, 1e226, 1e227, 1e228, 1e229, + 1e230, 1e231, 1e232, 1e233, 1e234, 1e235, 1e236, 1e237, 1e238, 1e239, + 1e240, 1e241, 1e242, 1e243, 1e244, 1e245, 1e246, 1e247, 1e248, 1e249, + 1e250, 1e251, 1e252, 1e253, 1e254, 1e255, 1e256, 1e257, 1e258, 1e259, + 1e260, 1e261, 1e262, 1e263, 1e264, 1e265, 1e266, 1e267, 1e268, 1e269, + 1e270, 1e271, 1e272, 1e273, 1e274, 1e275, 1e276, 1e277, 1e278, 1e279, + 1e280, 1e281, 1e282, 1e283, 1e284, 1e285, 1e286, 1e287, 1e288, 1e289, + 1e290, 1e291, 1e292, 1e293, 1e294, 1e295, 1e296, 1e297, 1e298, 1e299, + 1e300, 1e301, 1e302, 1e303, 1e304, 1e305, 1e306, 1e307, 1e308 +}; /* Convert string to double (string doesn't have to be null terminated) @@ -57,7 +84,7 @@ double my_strtod(const char *str, char **end_ptr, int *error) { double result= 0.0; uint negative= 0, ndigits, dec_digits= 0, neg_exp= 0; - int exponent= 0, digits_after_dec_point= 0, tmp_exp; + int exponent= 0, digits_after_dec_point= 0, tmp_exp, step; const char *old_str, *end= *end_ptr, *start_of_number; char next_char; my_bool overflow=0; @@ -179,16 +206,10 @@ double my_strtod(const char *str, char **end_ptr, int *error) exponent= -exponent; neg_exp= 1; /* neg_exp was 0 before */ } - while (exponent >= 100) - { - result= neg_exp ? result/1.0e100 : result*1.0e100; - exponent-= 100; - } - scaler= scaler10[exponent/10]*scaler1[exponent%10]; - if (neg_exp) - result/= scaler; - else - result*= scaler; + step= array_elements(log_10) - 1; + for (; exponent > step; exponent-= step) + result= neg_exp ? result / log_10[step] : result * log_10[step]; + result= neg_exp ? result / log_10[exponent] : result * log_10[exponent]; } done: diff --git a/vio/vio_priv.h b/vio/vio_priv.h index 4a272e519a3..9036952d575 100644 --- a/vio/vio_priv.h +++ b/vio/vio_priv.h @@ -23,6 +23,7 @@ #include <violite.h> void vio_ignore_timeout(Vio *vio, uint which, uint timeout); +void vio_timeout(Vio *vio,uint which, uint timeout); #ifdef HAVE_OPENSSL #include "my_net.h" /* needed because of struct in_addr */ diff --git a/vio/viosocket.c b/vio/viosocket.c index 01abde6e0f7..84fdd6f57e4 100644 --- a/vio/viosocket.c +++ b/vio/viosocket.c @@ -204,13 +204,14 @@ int vio_fastsend(Vio * vio __attribute__((unused))) { #ifdef __WIN__ BOOL nodelay= 1; - r= setsockopt(vio->sd, IPPROTO_TCP, TCP_NODELAY, (const char*) &nodelay, - sizeof(nodelay)); #else int nodelay = 1; - r= setsockopt(vio->sd, IPPROTO_TCP, TCP_NODELAY, (void*) &nodelay, +#endif + + r= setsockopt(vio->sd, IPPROTO_TCP, TCP_NODELAY, + IF_WIN(const char*, void*) &nodelay, sizeof(nodelay)); -#endif /* __WIN__ */ + } if (r) { @@ -380,28 +381,39 @@ my_bool vio_poll_read(Vio *vio,uint timeout) void vio_timeout(Vio *vio, uint which, uint timeout) { -/* TODO: some action should be taken if socket timeouts are not supported. */ #if defined(SO_SNDTIMEO) && defined(SO_RCVTIMEO) + int r; + DBUG_ENTER("vio_timeout"); + { #ifdef __WIN__ - - /* Windows expects time in milliseconds as int. */ + /* Windows expects time in milliseconds as int */ int wait_timeout= (int) timeout * 1000; - -#else /* ! __WIN__ */ - +#else /* POSIX specifies time as struct timeval. */ struct timeval wait_timeout; wait_timeout.tv_sec= timeout; wait_timeout.tv_usec= 0; +#endif + + r= setsockopt(vio->sd, SOL_SOCKET, which ? SO_SNDTIMEO : SO_RCVTIMEO, + IF_WIN(const char*, const void*)&wait_timeout, + sizeof(wait_timeout)); -#endif /* ! __WIN__ */ + } - /* TODO: return value should be checked. */ - (void) setsockopt(vio->sd, SOL_SOCKET, which ? SO_SNDTIMEO : SO_RCVTIMEO, - (char*) &wait_timeout, sizeof(wait_timeout)); +#ifndef DBUG_OFF + if (r != 0) + DBUG_PRINT("error", ("setsockopt failed: %d, errno: %d", r, socket_errno)); +#endif -#endif /* defined(SO_SNDTIMEO) && defined(SO_RCVTIMEO) */ + DBUG_VOID_RETURN; +#else +/* + Platforms not suporting setting of socket timeout should either use + thr_alarm or just run without read/write timeout(s) +*/ +#endif } diff --git a/win/create_manifest.js b/win/create_manifest.js index ac62cb2a8c2..520ecec21b8 100755 --- a/win/create_manifest.js +++ b/win/create_manifest.js @@ -27,7 +27,11 @@ try var app_name= parts[1]; break; case "version": - var app_version= parts[1]; + var supp_version= parts[1]; + // Clean up the supplied version string. + var end= supp_version.indexOf("-"); + if (end == -1) end= supp_version.length; + var app_version= supp_version.substring(0, end); app_version+= ".0"; break; case "arch": |