diff options
-rw-r--r-- | BUILD/SETUP.sh | 2 | ||||
-rwxr-xr-x | Build-tools/Do-compile | 53 | ||||
-rw-r--r-- | acinclude.m4 | 2 | ||||
-rw-r--r-- | configure.in | 5 | ||||
-rw-r--r-- | include/mysql.h | 1 | ||||
-rw-r--r-- | include/mysql_com.h | 3 | ||||
-rw-r--r-- | innobase/include/univ.i | 1 | ||||
-rw-r--r-- | innobase/os/os0file.c | 2 | ||||
-rw-r--r-- | innobase/trx/trx0sys.c | 6 | ||||
-rw-r--r-- | innobase/trx/trx0trx.c | 2 | ||||
-rw-r--r-- | innobase/ut/ut0ut.c | 1 | ||||
-rw-r--r-- | libmysql/libmysql.c | 17 | ||||
-rw-r--r-- | myisam/mi_check.c | 2 | ||||
-rw-r--r-- | myisam/mi_test1.c | 2 | ||||
-rw-r--r-- | mysql-test/r/packet.result | 25 | ||||
-rw-r--r-- | mysql-test/t/func_str.test | 3 | ||||
-rw-r--r-- | mysql-test/t/packet.test | 31 | ||||
-rw-r--r-- | mysys/my_compress.c | 41 | ||||
-rw-r--r-- | mysys/my_getopt.c | 4 | ||||
-rw-r--r-- | sql/ha_berkeley.cc | 4 | ||||
-rw-r--r-- | sql/mini_client.cc | 11 | ||||
-rw-r--r-- | sql/net_serv.cc | 231 | ||||
-rw-r--r-- | sql/protocol.cc | 2 | ||||
-rw-r--r-- | sql/sql_class.h | 2 | ||||
-rw-r--r-- | sql/sql_parse.cc | 29 | ||||
-rw-r--r-- | sql/table.cc | 2 | ||||
-rwxr-xr-x | tests/big_record.pl | 57 | ||||
-rw-r--r-- | tools/mysqlmanager.c | 2 |
28 files changed, 370 insertions, 173 deletions
diff --git a/BUILD/SETUP.sh b/BUILD/SETUP.sh index 859150c3954..9a092b84a8f 100644 --- a/BUILD/SETUP.sh +++ b/BUILD/SETUP.sh @@ -48,7 +48,7 @@ fast_cflags="-O3 -fno-omit-frame-pointer" # this is one is for someone who thinks 1% speedup is worth not being # able to backtrace reckless_cflags="-O3 -fomit-frame-pointer " -debug_cflags="-DUNIV_MUST_NOT_INLINE -DEXTRA_DEBUG -DFORCE_INIT_OF_VARS -DSAFEMALLOC -DPEDANTIC_SAFEMALLOC -DSAFE_MUTEX -O1" +debug_cflags="-DUNIV_MUST_NOT_INLINE -DEXTRA_DEBUG -DFORCE_INIT_OF_VARS -DSAFEMALLOC -DPEDANTIC_SAFEMALLOC -DSAFE_MUTEX -O1 -Wuninitialized" base_cxxflags="-felide-constructors -fno-exceptions -fno-rtti" diff --git a/Build-tools/Do-compile b/Build-tools/Do-compile index 52c1951f48f..4351a4f69f4 100755 --- a/Build-tools/Do-compile +++ b/Build-tools/Do-compile @@ -8,7 +8,7 @@ use Getopt::Long; $opt_distribution=$opt_user=$opt_config_env=""; $opt_dbd_options=$opt_perl_options=$opt_config_options=$opt_make_options=$opt_suffix=""; $opt_tmp=$opt_version_suffix=""; -$opt_help=$opt_delete=$opt_debug=$opt_stage=$opt_no_test=$opt_no_perl=$opt_with_low_memory=$opt_fast_benchmark=$opt_static_client=$opt_static_server=$opt_static_perl=$opt_sur=$opt_with_small_disk=$opt_local_perl=$opt_tcpip=$opt_build_thread=$opt_use_old_distribution=$opt_enable_shared=$opt_no_crash_me=$opt_no_strip=$opt_with_debug=0; +$opt_help=$opt_delete=$opt_debug=$opt_stage=$opt_no_test=$opt_no_perl=$opt_with_low_memory=$opt_fast_benchmark=$opt_static_client=$opt_static_server=$opt_static_perl=$opt_sur=$opt_with_small_disk=$opt_local_perl=$opt_tcpip=$opt_build_thread=$opt_use_old_distribution=$opt_enable_shared=$opt_no_crash_me=$opt_no_strip=$opt_with_debug=$opt_no_benchmark=$opt_no_mysqltest=0; $opt_innodb=$opt_bdb=$opt_raid=$opt_libwrap=0; GetOptions( @@ -30,7 +30,9 @@ GetOptions( "no-crash-me", "no-perl", "no-strip", - "no-test|no-mysqltest", + "no-test", + "no-mysqltest", + "no-benchmark", "perl-files=s", "perl-options=s", "raid", @@ -148,6 +150,7 @@ select STDOUT; $|=1; info("Compiling MySQL$opt_version_suffix at $host$opt_suffix, stage: $opt_stage\n"); +log_timestamp(); if (-x "$host/bin/mysqladmin") { @@ -161,6 +164,7 @@ kill_all("mysqlmanager"); if ($opt_stage == 0) { + log_timestamp(); print "$host: Removing old distribution\n" if ($opt_debug); if (!$opt_use_old_distribution) { @@ -209,6 +213,7 @@ safe_cd("$pwd/$host/$ver"); if ($opt_stage <= 1) { # Fix files if this is in another timezone than the build host + log_timestamp(); unlink("config.cache"); unlink("bdb/build_unix/config.cache"); unlink("innobase/config.cache"); @@ -252,6 +257,7 @@ if ($opt_stage <= 1) if ($opt_stage <= 2) { my ($command); + log_timestamp(); unlink($opt_distribution) if ($opt_delete && !$opt_use_old_distribution); $command=$make; $command.= " $opt_make_options" if (defined($opt_make_options) && $opt_make_options ne ""); @@ -264,6 +270,7 @@ if ($opt_stage <= 2) if ($opt_stage <= 3) { my $flags= ""; + log_timestamp(); log_system("rm -fr mysql-3* mysql-4* $pwd/$host/*.tar.gz"); log_system("nm -n sql/mysqld | gzip -9 -v 2>&1 > sql/mysqld.sym.gz | cat"); @@ -292,6 +299,7 @@ if (!defined($tar_file)) # if ($opt_stage <= 4 && !$opt_no_test) { + log_timestamp(); rm_all(<$pwd/$host/test/*>); safe_cd("$pwd/$host/test"); safe_system("gunzip < $tar_file | $tar xf -"); @@ -305,8 +313,9 @@ $ENV{"LD_LIBRARY_PATH"}= "$test_dir/lib:" . $ENV{"LD_LIBRARY_PATH"}; # # Run the test suite # -if ($opt_stage <= 5 && !$opt_no_test) +if ($opt_stage <= 5 && !$opt_no_test && !$opt_no_mysqltest) { + log_timestamp(); system("mkdir $bench_tmpdir") if (! -d $bench_tmpdir); safe_cd("${test_dir}/mysql-test"); check_system("./mysql-test-run --warnings --tmpdir=$bench_tmpdir --master_port=$mysql_tcp_port --slave_port=$slave_port --manager-port=$manager_port --no-manager --sleep=10", "tests were successful"); @@ -315,7 +324,7 @@ if ($opt_stage <= 5 && !$opt_no_test) # # Start the server if we are going to run any of the benchmarks # -if (!$opt_no_test) +if (!$opt_no_test && !$opt_no_benchmark) { my $extra; safe_cd($test_dir); @@ -339,8 +348,10 @@ if (!$opt_no_test) # # Compile and install the required Perl modules # -if ($opt_stage <= 7 && $opt_perl_files && !$opt_no_perl && !$opt_no_test) +if ($opt_stage <= 7 && $opt_perl_files && !$opt_no_perl && !$opt_no_test && + !$opt_no_benchmark) { + log_timestamp(); safe_cd($test_dir); rm_all("perl"); safe_system("mkdir perl"); @@ -376,6 +387,7 @@ if ($opt_stage <= 7 && $opt_perl_files && !$opt_no_perl && !$opt_no_test) # if ($opt_stage <= 8 && !$opt_no_test && !$opt_no_crash_me) { + log_timestamp(); safe_cd("$test_dir/sql-bench"); log_system("rm -f limits/mysql.cfg"); safe_system("perl ./crash-me --force --batch-mode $connect_option"); @@ -384,8 +396,9 @@ if ($opt_stage <= 8 && !$opt_no_test && !$opt_no_crash_me) # # Run sql-bench Benchmarks # -if ($opt_stage <= 9 && !$opt_no_test) +if ($opt_stage <= 9 && !$opt_no_test && !$opt_no_benchmark) { + log_timestamp(); safe_cd("$test_dir/sql-bench"); log_system("rm -f output/*"); $tmp= $opt_fast_benchmark ? "--fast --user root --small-test" : ""; @@ -469,7 +482,13 @@ Do not run the "crash-me" test Do not strip the binaries included in the binary distribution --no-test -Do not run any tests +Do not run any tests. + +--no-benchmark +Do not run the benchmark test (written in perl) + +--no-mysqltest +Do not run the the mysql-test-run test (Same as 'make test') --perl-files=list of files Compile and install the given perl modules. @@ -532,6 +551,7 @@ sub abort my($mail_header_file); print LOG "\n$message\n"; print "$host: $message\n" if ($opt_debug); + print LOG "Aborting\n"; close LOG; if ($opt_user) @@ -547,7 +567,6 @@ sub abort unlink($mail_header_file); unlink("$log.mail"); } - print LOG "Aborting\n"; exit 1; } @@ -689,9 +708,10 @@ sub rm_all sub kill_all { my ($pattern) = @_; - my ($USER,$BSD,$LINUX, $pscmd, $user, $pid); + my ($USER,$BSD,$LINUX, $pscmd, $user, $os, $pid); $user=$ENV{'USER'}; - $BSD = -f '/vmunix' || $ENV{"OS"} eq "SunOS4" || $^O eq 'darwin'; + $os=defined($ENV{'OS'}) ? $ENV{'OS'} : "unknown"; + $BSD = -f '/vmunix' || $os eq "SunOS4" || $^O eq 'darwin'; $LINUX = $^O eq 'linux'; $pscmd = $BSD ? "/bin/ps -auxww" : $LINUX ? "/bin/ps axuw" : "/bin/ps -ef"; @@ -707,7 +727,7 @@ sub kill_all { chop($cand); ($pid_user, $pid) = split(' ', $cand); - next if $pid == $$; + next if $pid eq $$; next process if (! ($cand =~ $pattern) || $pid_user ne $user); print LOG "Killing $_\n"; &killpid($pid); @@ -730,3 +750,14 @@ sub killpid } print LOG "$pid will not die!\n"; } + +# +# return the current date as a string (YYYY-MM-DD HH:MM:SS) +# +sub log_timestamp +{ + my @ta=localtime(time()); + print LOG sprintf("%4d-%02d-%02d %02d:%02d:%02d\n", + $ta[5]+1900, $ta[4]+1, $ta[3], $ta[2], $ta[1], $ta[0]); + +} diff --git a/acinclude.m4 b/acinclude.m4 index c9e32ea3fc3..15f08e44c27 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -623,7 +623,7 @@ main() FILE *file=fopen("conftestval", "w"); f = (float) ll; fprintf(file,"%g\n",f); - close(file); + fclose(file); exit (0); }], ac_cv_conv_longlong_to_float=`cat conftestval`, ac_cv_conv_longlong_to_float=0, ifelse([$2], , , ac_cv_conv_longlong_to_float=$2))])dnl if test "$ac_cv_conv_longlong_to_float" = "1" -o "$ac_cv_conv_longlong_to_float" = "yes" diff --git a/configure.in b/configure.in index eae4b52fdca..f2e64ddffe4 100644 --- a/configure.in +++ b/configure.in @@ -882,6 +882,7 @@ int main() # MAX_C_OPTIMIZE="-O3" +MAX_CXX_OPTIMIZE="-O3" case $SYSTEM_TYPE in *solaris2.7*) @@ -949,6 +950,8 @@ case $SYSTEM_TYPE in then CFLAGS="$CFLAGS +DD64 -DHAVE_BROKEN_INLINE" CXXFLAGS="$CXXFLAGS +DD64 +O2" + MAX_C_OPTIMIZE="" + MAX_CXX_OPTIMIZE="" fi ;; *rhapsody*) @@ -1407,7 +1410,7 @@ if test "$ac_cv_prog_cxx_g" = "yes" then DEBUG_CXXFLAGS="-g" DEBUG_OPTIMIZE_CXX="-O" - OPTIMIZE_CXXFLAGS="-O3" + OPTIMIZE_CXXFLAGS="$MAX_CXX_OPTIMIZE" else DEBUG_CXXFLAGS="-g" DEBUG_OPTIMIZE_CXX="" diff --git a/include/mysql.h b/include/mysql.h index a2b48c0c43d..e43136f8f69 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -127,6 +127,7 @@ struct st_mysql_options { char *ssl_ca; /* PEM CA file */ char *ssl_capath; /* PEM directory of CA-s? */ char *ssl_cipher; /* cipher to use */ + unsigned long max_allowed_packet; my_bool use_ssl; /* if to use SSL or not */ my_bool compress,named_pipe; /* diff --git a/include/mysql_com.h b/include/mysql_com.h index d4d0b63dc78..8716ef3a58f 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -42,7 +42,8 @@ enum enum_server_command COM_PROCESS_INFO, COM_CONNECT, COM_PROCESS_KILL, COM_DEBUG, COM_PING, COM_TIME, COM_DELAYED_INSERT, COM_CHANGE_USER, COM_BINLOG_DUMP, COM_TABLE_DUMP, COM_CONNECT_OUT, COM_REGISTER_SLAVE, - COM_PREPARE, COM_EXECUTE, COM_LONG_DATA, COM_CLOSE_STMT + COM_PREPARE, COM_EXECUTE, COM_LONG_DATA, COM_CLOSE_STMT, + COM_END /* Must be last */ }; diff --git a/innobase/include/univ.i b/innobase/include/univ.i index 43130549eae..bf606efcf64 100644 --- a/innobase/include/univ.i +++ b/innobase/include/univ.i @@ -57,6 +57,7 @@ of the 32-bit x86 assembler in mutex operations. */ Microsoft Visual C++ */ #if !defined(__GNUC__) && !defined(__WIN__) +#undef UNIV_MUST_NOT_INLINE /* Remove compiler warning */ #define UNIV_MUST_NOT_INLINE #endif diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c index 9eae358c7fb..fa5482a8cd1 100644 --- a/innobase/os/os0file.c +++ b/innobase/os/os0file.c @@ -2127,7 +2127,7 @@ os_aio_simulated_handle( ulint offs; ulint lowest_offset; byte* combined_buf; - byte* combined_buf2; + byte* combined_buf2= 0; /* Remove warning */ ibool ret; ulint n; ulint i; diff --git a/innobase/trx/trx0sys.c b/innobase/trx/trx0sys.c index 33c962772e8..0c10040847e 100644 --- a/innobase/trx/trx0sys.c +++ b/innobase/trx/trx0sys.c @@ -472,9 +472,9 @@ trx_sys_update_mysql_binlog_offset( if (0 != ut_memcmp(sys_header + field + TRX_SYS_MYSQL_LOG_NAME, file_name, 1 + ut_strlen(file_name))) { - mlog_write_string(sys_header + field - + TRX_SYS_MYSQL_LOG_NAME, - file_name, 1 + ut_strlen(file_name), mtr); + mlog_write_string((byte*) (sys_header + field + + TRX_SYS_MYSQL_LOG_NAME), + (byte*) file_name, 1 + ut_strlen(file_name), mtr); } if (mach_read_from_4(sys_header + field diff --git a/innobase/trx/trx0trx.c b/innobase/trx/trx0trx.c index f0077f941de..d2219ed019f 100644 --- a/innobase/trx/trx0trx.c +++ b/innobase/trx/trx0trx.c @@ -99,7 +99,7 @@ trx_create( trx->mysql_log_file_name = NULL; trx->mysql_log_offset = 0; - trx->mysql_master_log_file_name = ""; + trx->mysql_master_log_file_name = (char*) ""; trx->mysql_master_log_pos = 0; trx->ignore_duplicates_in_insert = FALSE; diff --git a/innobase/ut/ut0ut.c b/innobase/ut/ut0ut.c index ff5d11d84ed..bb5eb662cd7 100644 --- a/innobase/ut/ut0ut.c +++ b/innobase/ut/ut0ut.c @@ -197,7 +197,6 @@ ut_get_year_month_day( *month = (ulint)cal_tm.wMonth; *day = (ulint)cal_tm.wDay; #else - struct tm cal_tm; struct tm* cal_tm_ptr; time_t tm; diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index bb0059f8e25..5cae0a3813d 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -61,7 +61,7 @@ static my_bool mysql_client_init=0; uint mysql_port=0; my_string mysql_unix_port=0; ulong net_buffer_length=8192; -ulong max_allowed_packet=16*1024*1024L; +ulong max_allowed_packet= 1024L*1024L*1024L; ulong net_read_timeout= NET_READ_TIMEOUT; ulong net_write_timeout= NET_WRITE_TIMEOUT; @@ -928,7 +928,8 @@ static const char *default_options[]= "character-sets-dir", "default-character-set", "interactive-timeout", "connect-timeout", "local-infile", "disable-local-infile", "replication-probe", "enable-reads-from-master", "repl-parse-query", - "ssl-cipher","protocol", "shared_memory_base_name", + "ssl-cipher", "max-allowed-packet", + "protocol", "shared-memory-base-name", NullS }; @@ -1099,14 +1100,17 @@ static void mysql_read_default_options(struct st_mysql_options *options, case 25: /* repl-parse-query */ options->rpl_parse= 1; break; - case 27:/* protocol */ + case 27: + options->max_allowed_packet= atoi(opt_arg); + break; + case 28: /* protocol */ if ((options->protocol = find_type(opt_arg, &sql_protocol_typelib,0)) == ~(ulong) 0) { fprintf(stderr, "Unknown option to protocol: %s\n", opt_arg); exit(1); } break; - case 28: /*shared_memory_base_name*/ + case 29: /* shared_memory_base_name */ #ifdef HAVE_SMEM if (options->shared_memory_base_name != def_shared_memory_base_name) my_free(options->shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR)); @@ -2242,6 +2246,7 @@ Try also with PIPE or TCP/IP DBUG_PRINT("info",("Server version = '%s' capabilites: %ld status: %d client_flag: %d", mysql->server_version,mysql->server_capabilities, mysql->server_status, client_flag)); + /* This needs to be changed as it's not useful with big packets */ int3store(buff+2,max_allowed_packet); if (user && user[0]) strmake(buff+5,user,32); /* Max user name */ @@ -2350,6 +2355,8 @@ Try also with PIPE or TCP/IP if (client_flag & CLIENT_COMPRESS) /* We will use compression */ net->compress=1; + if (mysql->options.max_allowed_packet) + net->max_packet_size= mysql->options.max_allowed_packet; if (db && mysql_select_db(mysql,db)) goto error; @@ -2853,7 +2860,7 @@ mysql_real_query(MYSQL *mysql, const char *query, ulong length) { DBUG_ENTER("mysql_real_query"); DBUG_PRINT("enter",("handle: %lx",mysql)); - DBUG_PRINT("query",("Query = \"%s\"",query)); + DBUG_PRINT("query",("Query = '%-.4096s'",query)); if (mysql_send_query(mysql,query,length)) DBUG_RETURN(1); diff --git a/myisam/mi_check.c b/myisam/mi_check.c index 3e6e9d40fab..1ca342f3998 100644 --- a/myisam/mi_check.c +++ b/myisam/mi_check.c @@ -3656,7 +3656,7 @@ void update_key_parts(MI_KEYDEF *keyinfo, ulong *rec_per_key_part, } -ha_checksum mi_byte_checksum(const byte *buf, uint length) +static ha_checksum mi_byte_checksum(const byte *buf, uint length) { ha_checksum crc; const byte *end=buf+length; diff --git a/myisam/mi_test1.c b/myisam/mi_test1.c index 1c2b3f13baa..6aa4b9cf9f1 100644 --- a/myisam/mi_test1.c +++ b/myisam/mi_test1.c @@ -57,7 +57,7 @@ int main(int argc,char *argv[]) } -int run_test(const char *filename) +static int run_test(const char *filename) { MI_INFO *file; int i,j,error,deleted,rec_length,uniques=0; diff --git a/mysql-test/r/packet.result b/mysql-test/r/packet.result new file mode 100644 index 00000000000..e994e4d63da --- /dev/null +++ b/mysql-test/r/packet.result @@ -0,0 +1,25 @@ +set global max_allowed_packet=100; +set max_allowed_packet=100; +set global net_buffer_length=100; +set net_buffer_length=100; +SELECT length("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") as len; +len +1024 +select repeat('a',200); +repeat('a',200) +NULL +select @@net_buffer_length, @@max_allowed_packet; +@@net_buffer_length @@max_allowed_packet +1024 80 +SELECT length("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") as len; +Got a packet bigger than 'max_allowed_packet' +set global max_allowed_packet=default; +set max_allowed_packet=default; +set global net_buffer_length=default; +set net_buffer_length=default; +SELECT length("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") as len; +len +100 +select length(repeat('a',200)); +length(repeat('a',200)) +200 diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index 7e94f47f1e3..a87707746ba 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -71,7 +71,8 @@ select decode(encode("abcdef","monty"),"monty")="abcdef"; select quote('\'\"\\test'); select quote(concat('abc\'', '\\cba')); select quote(1/0), quote('\0\Z'); -select length(quote(concat(char(0), "test"))); +select length(quote(concat(char(0),"test"))); + # # Wrong usage of functions # diff --git a/mysql-test/t/packet.test b/mysql-test/t/packet.test new file mode 100644 index 00000000000..5c4e7efcaf3 --- /dev/null +++ b/mysql-test/t/packet.test @@ -0,0 +1,31 @@ + +# +# Check protocol handling +# + +connect (con1,localhost,root,,); + +connection con1; +set global max_allowed_packet=100; +set max_allowed_packet=100; +set global net_buffer_length=100; +set net_buffer_length=100; +# Have to be > 1024 as min value of net_buffer_length is 1024 +SELECT length("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") as len; +# Should return NULL as 200 is bigger than max_allowed_packet +select repeat('a',200); + +# +# Connection 2 should get error for too big packets +# +connect (con2,localhost,root,,); +connection con2; +select @@net_buffer_length, @@max_allowed_packet; +--error 1153 +SELECT length("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") as len; +set global max_allowed_packet=default; +set max_allowed_packet=default; +set global net_buffer_length=default; +set net_buffer_length=default; +SELECT length("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") as len; +select length(repeat('a',200)); diff --git a/mysys/my_compress.c b/mysys/my_compress.c index 1e46584d525..dd076311188 100644 --- a/mysys/my_compress.c +++ b/mysys/my_compress.c @@ -32,24 +32,28 @@ my_bool my_compress(byte *packet, ulong *len, ulong *complen) { + DBUG_ENTER("my_compress"); if (*len < MIN_COMPRESS_LENGTH) + { *complen=0; + DBUG_PRINT("note",("Packet too short: Not compressed")); + } else { byte *compbuf=my_compress_alloc(packet,len,complen); if (!compbuf) - return *complen ? 0 : 1; + DBUG_RETURN(*complen ? 0 : 1); memcpy(packet,compbuf,*len); my_free(compbuf,MYF(MY_WME)); } - return 0; + DBUG_RETURN(0); } byte *my_compress_alloc(const byte *packet, ulong *len, ulong *complen) { byte *compbuf; - *complen = *len * 120 / 100 + 12; - if (!(compbuf = (byte *) my_malloc(*complen,MYF(MY_WME)))) + *complen= *len * 120 / 100 + 12; + if (!(compbuf= (byte *) my_malloc(*complen,MYF(MY_WME)))) return 0; /* Not enough memory */ if (compress((Bytef*) compbuf,(ulong *) complen, (Bytef*) packet, (uLong) *len ) != Z_OK) @@ -59,31 +63,36 @@ byte *my_compress_alloc(const byte *packet, ulong *len, ulong *complen) } if (*complen >= *len) { - *complen=0; - my_free(compbuf,MYF(MY_WME)); + *complen= 0; + my_free(compbuf, MYF(MY_WME)); + DBUG_PRINT("note",("Packet got longer on compression; Not compressed")); return 0; } - swap(ulong,*len,*complen); /* *len is now packet length */ + swap(ulong, *len, *complen); /* *len is now packet length */ return compbuf; } my_bool my_uncompress (byte *packet, ulong *len, ulong *complen) { + DBUG_ENTER("my_uncompress"); if (*complen) /* If compressed */ { - byte *compbuf = (byte *) my_malloc (*complen,MYF(MY_WME)); + byte *compbuf= (byte *) my_malloc(*complen,MYF(MY_WME)); + int error; if (!compbuf) - return 1; /* Not enough memory */ - if (uncompress((Bytef*) compbuf, complen, (Bytef*) packet, *len) != Z_OK) + DBUG_RETURN(1); /* Not enough memory */ + if ((error=uncompress((Bytef*) compbuf, complen, (Bytef*) packet, *len)) + != Z_OK) { /* Probably wrong packet */ - my_free (compbuf,MYF(MY_WME)); - return 1; + DBUG_PRINT("error",("Can't uncompress packet, error: %d",error)); + my_free(compbuf, MYF(MY_WME)); + DBUG_RETURN(1); } - *len = *complen; - memcpy(packet,compbuf,*len); - my_free(compbuf,MYF(MY_WME)); + *len= *complen; + memcpy(packet, compbuf, *len); + my_free(compbuf, MYF(MY_WME)); } - return 0; + DBUG_RETURN(0); } #endif /* HAVE_COMPRESS */ diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c index b2ee6e0f373..21adb9374ce 100644 --- a/mysys/my_getopt.c +++ b/mysys/my_getopt.c @@ -572,7 +572,7 @@ static longlong eval_num_suffix (char *argument, int *error, char *option_name) In case of an error, set error value in *err. */ -longlong getopt_ll (char *arg, const struct my_option *optp, int *err) +static longlong getopt_ll(char *arg, const struct my_option *optp, int *err) { longlong num; @@ -596,7 +596,7 @@ longlong getopt_ll (char *arg, const struct my_option *optp, int *err) values. */ -static ulonglong getopt_ull (char *arg, const struct my_option *optp, int *err) +static ulonglong getopt_ull(char *arg, const struct my_option *optp, int *err) { ulonglong num; diff --git a/sql/ha_berkeley.cc b/sql/ha_berkeley.cc index 5d57e9cdf9b..168c3327d79 100644 --- a/sql/ha_berkeley.cc +++ b/sql/ha_berkeley.cc @@ -2119,7 +2119,7 @@ int ha_berkeley::analyze(THD* thd, HA_CHECK_OPT* check_opt) free(stat); stat=0; } - if (key_file[i]->stat(key_file[i], (void*) &stat, 0)) + if ((key_file[i]->stat)(key_file[i], (void*) &stat, 0)) goto err; /* purecov: inspected */ share->rec_per_key[i]= (stat->bt_ndata / (stat->bt_nkeys ? stat->bt_nkeys : 1)); @@ -2132,7 +2132,7 @@ int ha_berkeley::analyze(THD* thd, HA_CHECK_OPT* check_opt) free(stat); stat=0; } - if (file->stat(file, (void*) &stat, 0)) + if ((file->stat)(file, (void*) &stat, 0)) goto err; /* purecov: inspected */ } pthread_mutex_lock(&share->mutex); diff --git a/sql/mini_client.cc b/sql/mini_client.cc index 83f68a28228..02a0156ce5b 100644 --- a/sql/mini_client.cc +++ b/sql/mini_client.cc @@ -545,10 +545,13 @@ mc_mysql_connect(MYSQL *mysql,const char *host, const char *user, bzero((char*) &UNIXaddr,sizeof(UNIXaddr)); UNIXaddr.sun_family = AF_UNIX; strmov(UNIXaddr.sun_path, unix_socket); - if (mc_sock_connect(sock,(struct sockaddr *) &UNIXaddr, sizeof(UNIXaddr), + if (mc_sock_connect(sock, + my_reinterpret_cast(struct sockaddr *) (&UNIXaddr), + sizeof(UNIXaddr), mysql->options.connect_timeout) <0) { - DBUG_PRINT("error",("Got error %d on connect to local server",socket_errno)); + DBUG_PRINT("error",("Got error %d on connect to local server", + socket_errno)); net->last_errno=CR_CONNECTION_ERROR; sprintf(net->last_error,ER(net->last_errno),unix_socket,socket_errno); goto error; @@ -635,7 +638,9 @@ mc_mysql_connect(MYSQL *mysql,const char *host, const char *user, my_gethostbyname_r_free(); } sock_addr.sin_port = (ushort) htons((ushort) port); - if (mc_sock_connect(sock,(struct sockaddr *) &sock_addr, sizeof(sock_addr), + if (mc_sock_connect(sock, + my_reinterpret_cast(struct sockaddr *) (&sock_addr), + sizeof(sock_addr), mysql->options.connect_timeout) <0) { DBUG_PRINT("error",("Got error %d on connect to '%s'", diff --git a/sql/net_serv.cc b/sql/net_serv.cc index cd1238ff6d4..f284106d752 100644 --- a/sql/net_serv.cc +++ b/sql/net_serv.cc @@ -73,7 +73,7 @@ extern pthread_mutex_t LOCK_bytes_sent , LOCK_bytes_received; #include "thr_alarm.h" #define TEST_BLOCKING 8 -#define MAX_THREE_BYTES (256L*256L*256L-1) +#define MAX_PACKET_LENGTH (256L*256L*256L-1) static my_bool net_write_buff(NET *net,const char *packet,ulong len); @@ -132,13 +132,17 @@ my_bool net_realloc(NET *net, ulong length) { uchar *buff; ulong pkt_length; + DBUG_ENTER("net_realloc"); + DBUG_PRINT("enter",("length: %lu", length)); + if (length >= net->max_packet_size) { - DBUG_PRINT("error",("Packet too large (%lu)", length)); + DBUG_PRINT("error",("Packet too large. Max sixe: %lu", + net->max_packet_size)); net->error= 1; net->report_error= 1; net->last_errno= ER_NET_PACKET_TOO_LARGE; - return 1; + DBUG_RETURN(1); } pkt_length = (length+IO_SIZE-1) & ~(IO_SIZE-1); /* @@ -154,11 +158,11 @@ my_bool net_realloc(NET *net, ulong length) #ifdef MYSQL_SERVER net->last_errno= ER_OUT_OF_RESOURCES; #endif - return 1; + DBUG_RETURN(1); } net->buff=net->write_pos=buff; net->buff_end=buff+(net->max_packet=pkt_length); - return 0; + DBUG_RETURN(0); } /* Remove unwanted characters from connection */ @@ -220,13 +224,13 @@ my_net_write(NET *net,const char *packet,ulong len) { uchar buff[NET_HEADER_SIZE]; /* - Big packets are handled by splitting them in packets of MAX_THREE_BYTES - length. The last packet is always a packet that is < MAX_THREE_BYTES. - (The last packet may even have a lengt of 0) + Big packets are handled by splitting them in packets of MAX_PACKET_LENGTH + length. The last packet is always a packet that is < MAX_PACKET_LENGTH. + (The last packet may even have a length of 0) */ - while (len >= MAX_THREE_BYTES) + while (len >= MAX_PACKET_LENGTH) { - const ulong z_size = MAX_THREE_BYTES; + const ulong z_size = MAX_PACKET_LENGTH; int3store(buff, z_size); buff[3]= (uchar) net->pkt_nr++; if (net_write_buff(net, (char*) buff, NET_HEADER_SIZE) || @@ -241,7 +245,7 @@ my_net_write(NET *net,const char *packet,ulong len) if (net_write_buff(net,(char*) buff,NET_HEADER_SIZE)) return 1; DBUG_DUMP("packet_header",(char*) buff,NET_HEADER_SIZE); - return net_write_buff(net,packet,len); + return test(net_write_buff(net,packet,len)); } /* @@ -280,67 +284,110 @@ net_write_command(NET *net,uchar command, ulong length=len+1+head_len; /* 1 extra byte for command */ uchar buff[NET_HEADER_SIZE+1]; uint header_size=NET_HEADER_SIZE+1; + DBUG_ENTER("net_write_command"); + DBUG_PRINT("enter",("length: %lu", len)); + buff[4]=command; /* For first packet */ - if (length >= MAX_THREE_BYTES) + if (length >= MAX_PACKET_LENGTH) { /* Take into account that we have the command in the first header */ - len= MAX_THREE_BYTES - 1 - head_len; + len= MAX_PACKET_LENGTH - 1 - head_len; do { - int3store(buff, MAX_THREE_BYTES); + int3store(buff, MAX_PACKET_LENGTH); buff[3]= (uchar) net->pkt_nr++; if (net_write_buff(net,(char*) buff, header_size) || net_write_buff(net, header, head_len) || net_write_buff(net, packet, len)) - return 1; + DBUG_RETURN(1); packet+= len; - length-= MAX_THREE_BYTES; - len=MAX_THREE_BYTES; - head_len=0; - header_size=NET_HEADER_SIZE; - } while (length >= MAX_THREE_BYTES); + length-= MAX_PACKET_LENGTH; + len= MAX_PACKET_LENGTH; + head_len= 0; + header_size= NET_HEADER_SIZE; + } while (length >= MAX_PACKET_LENGTH); len=length; /* Data left to be written */ } int3store(buff,length); buff[3]= (uchar) net->pkt_nr++; - return test(net_write_buff(net, (char*) buff, header_size) || + DBUG_RETURN(test(net_write_buff(net, (char*) buff, header_size) || (head_len && net_write_buff(net, (char*) header, head_len)) || - net_write_buff(net, packet, len) || net_flush(net)); + net_write_buff(net, packet, len) || net_flush(net))); } /* Caching the data in a local buffer before sending it. - One can force the buffer to be flushed with 'net_flush'. + SYNOPSIS + net_write_buff() + net Network handler + packet Packet to send + len Length of packet + + DESCRIPTION + Fill up net->buffer and send it to the client when full. + + If the rest of the to-be-sent-packet is bigger than buffer, + send it in one big block (to avoid copying to internal buffer). + If not, copy the rest of the data to the buffer and return without + sending data. + + NOTES + The cached buffer can be sent as it is with 'net_flush()'. + + In this code we have to be careful to not send a packet longer than + MAX_PACKET_LENGTH to net_real_write() if we are using the compressed protocol + as we store the length of the compressed packet in 3 bytes. + + RETURN + 0 ok + 1 */ static my_bool net_write_buff(NET *net,const char *packet,ulong len) { - ulong left_length=(ulong) (net->buff_end - net->write_pos); + ulong left_length; + if (net->compress && net->max_packet > MAX_PACKET_LENGTH) + left_length= MAX_PACKET_LENGTH - (net->write_pos - net->buff); + else + left_length= (ulong) (net->buff_end - net->write_pos); if (len > left_length) { - memcpy((char*) net->write_pos,packet,left_length); - if (net_real_write(net,(char*) net->buff,net->max_packet)) - return 1; - net->write_pos=net->buff; - packet+=left_length; - len-= left_length; - left_length= net->max_packet; - - /* Send out rest of the blocks as full sized blocks */ - while (len > left_length) + if (net->write_pos != net->buff) { - if (net_real_write(net, packet, left_length)) + /* Fill up already used packet and write it */ + memcpy((char*) net->write_pos,packet,left_length); + if (net_real_write(net,(char*) net->buff, + (ulong) (net->write_pos - net->buff) + left_length)) return 1; + net->write_pos= net->buff; packet+= left_length; len-= left_length; } + if (net->compress) + { + /* + We can't have bigger packets than 16M with compression + Because the uncompressed length is stored in 3 bytes + */ + left_length= MAX_PACKET_LENGTH; + while (len > left_length) + { + if (net_real_write(net, packet, left_length)) + return 1; + packet+= left_length; + len-= left_length; + } + } + if (len > net->max_packet) + return net_real_write(net, packet, len) ? 1 : 0; + /* Send out rest of the blocks as full sized blocks */ } memcpy((char*) net->write_pos,packet,len); - net->write_pos+=len; + net->write_pos+= len; return 0; } @@ -393,11 +440,7 @@ net_real_write(NET *net,const char *packet,ulong len) memcpy(b+header_length,packet,len); if (my_compress((byte*) b+header_length,&len,&complen)) - { - DBUG_PRINT("warning", - ("Compression error; Continuing without compression")); complen=0; - } int3store(&b[NET_HEADER_SIZE],complen); int3store(b,len); b[3]=(uchar) (net->compress_pkt_nr++); @@ -500,28 +543,15 @@ net_real_write(NET *net,const char *packet,ulong len) *****************************************************************************/ #ifndef NO_ALARM -/* - Help function to clear the commuication buffer when we get a too - big packet -*/ -static void my_net_skip_rest(NET *net, uint32 remain, thr_alarm_t *alarmed) +static my_bool net_safe_read(NET *net, char *buff, uint32 length, + thr_alarm_t *alarmed) { - ALARM alarm_buff; uint retry_count=0; - my_bool old_mode; - uint32 old=remain; - - if (!thr_alarm_in_use(&alarmed)) + while (length > 0) { - if (!thr_alarm(alarmed,net->read_timeout,&alarm_buff) || - vio_blocking(net->vio, TRUE, &old_mode) < 0) - return; /* Can't setup, abort */ - } - while (remain > 0) - { - ulong length; - if ((int) (length=vio_read(net->vio,(char*) net->buff,remain)) <= 0L) + int tmp; + if ((tmp=vio_read(net->vio,(char*) net->buff, length)) <= 0) { my_bool interrupted = vio_should_retry(net->vio); if (!thr_got_alarm(&alarmed) && interrupted) @@ -529,17 +559,60 @@ static void my_net_skip_rest(NET *net, uint32 remain, thr_alarm_t *alarmed) if (retry_count++ < net->retry_count) continue; } - return; + return 1; } - remain -= (uint32) length; - if (!remain && old==MAX_THREE_BYTES && - (length=vio_read(net->vio,(char*) net->buff,NET_HEADER_SIZE))) + length-= tmp; + } + return 0; +} + +/* + Help function to clear the commuication buffer when we get a too big packet. + + SYNOPSIS + my_net_skip_rest() + net Communication handle + remain Bytes to read + alarmed Parameter for thr_alarm() + alarm_buff Parameter for thr_alarm() + + RETURN VALUES + 0 Was able to read the whole packet + 1 Got mailformed packet from client +*/ + +static my_bool my_net_skip_rest(NET *net, uint32 remain, thr_alarm_t *alarmed, + ALARM *alarm_buff) +{ + uint32 old=remain; + DBUG_ENTER("my_net_skip_rest"); + DBUG_PRINT("enter",("bytes_to_skip: %u", (uint) remain)); + + if (!thr_alarm_in_use(&alarmed)) + { + my_bool old_mode; + if (!thr_alarm(alarmed,net->read_timeout, alarm_buff) || + vio_blocking(net->vio, TRUE, &old_mode) < 0) + DBUG_RETURN(1); /* Can't setup, abort */ + } + for (;;) + { + while (remain > 0) { - old=remain= uint3korr(net->buff); - net->pkt_nr++; + uint length= min(remain, net->max_packet); + if (net_safe_read(net, (char*) net->buff, length, alarmed)) + DBUG_RETURN(1); + statistic_add(bytes_received, length, &LOCK_bytes_received); + remain -= (uint32) length; } - statistic_add(bytes_received,length,&LOCK_bytes_received); + if (old != MAX_PACKET_LENGTH) + break; + if (net_safe_read(net, (char*) net->buff, NET_HEADER_SIZE, alarmed)) + DBUG_RETURN(1); + old=remain= uint3korr(net->buff); + net->pkt_nr++; } + DBUG_RETURN(0); } #endif /* NO_ALARM */ @@ -639,9 +712,8 @@ my_real_read(NET *net, ulong *complen) continue; } #endif - DBUG_PRINT("error",("Couldn't read packet: remain: %lu errno: %d length: %ld alarmed: %d", - remain,vio_errno(net->vio), length, - thr_got_alarm(&alarmed))); + DBUG_PRINT("error",("Couldn't read packet: remain: %u errno: %d length: %ld", + remain, vio_errno(net->vio), length)); len= packet_error; net->error= 2; /* Close socket */ net->report_error= 1; @@ -701,19 +773,12 @@ my_real_read(NET *net, ulong *complen) { if (net_realloc(net,helping)) { -#ifdef MYSQL_SERVER -#ifndef NO_ALARM - if (net->compress) - { - len= packet_error; - goto end; - } - my_net_skip_rest(net, (uint32) len, &alarmed); - len=0; -#endif -#else - len= packet_error; /* Return error */ +#if defined(MYSQL_SERVER) && !defined(NO_ALARM) + if (!net->compress && + !my_net_skip_rest(net, (uint32) len, &alarmed, &alarm_buff)) + net->error= 3; /* Successfully skiped packet */ #endif + len= packet_error; /* Return error and close connection */ goto end; } } @@ -757,7 +822,7 @@ my_net_read(NET *net) { #endif len = my_real_read(net,&complen); - if (len == MAX_THREE_BYTES) + if (len == MAX_PACKET_LENGTH) { /* First packet of a multi-packet. Concatenate the packets */ ulong save_pos = net->where_b; @@ -767,7 +832,7 @@ my_net_read(NET *net) net->where_b += len; total_length += len; len = my_real_read(net,&complen); - } while (len == MAX_THREE_BYTES); + } while (len == MAX_PACKET_LENGTH); if (len != packet_error) len+= total_length; net->where_b = save_pos; @@ -825,7 +890,7 @@ my_net_read(NET *net) else start_of_packet+= read_length + NET_HEADER_SIZE; - if (read_length != MAX_THREE_BYTES) /* last package */ + if (read_length != MAX_PACKET_LENGTH) /* last package */ { multi_byte_packet= 0; /* No last zero len packet */ break; diff --git a/sql/protocol.cc b/sql/protocol.cc index d7cf9d39b5c..15f4ca9ad94 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -331,7 +331,7 @@ net_store_length(char *pkg, ulonglong length) } *packet++=254; int8store(packet,length); - return (char*) packet+9; + return (char*) packet+8; } diff --git a/sql/sql_class.h b/sql/sql_class.h index a053db72e64..bc72e6324e9 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -432,7 +432,7 @@ public: uint client_capabilities; /* What the client supports */ /* Determines if which non-standard SQL behaviour should be enabled */ uint sql_mode; - uint max_client_packet_length; + ulong max_client_packet_length; ulong master_access; /* Global privileges from mysql.user */ ulong db_access; /* Privileges for current db */ diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index b47ce194a57..4a0d2a803bf 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -74,7 +74,8 @@ const char *command_name[]={ "Drop DB", "Refresh", "Shutdown", "Statistics", "Processlist", "Connect","Kill","Debug","Ping","Time","Delayed_insert","Change user", "Binlog Dump","Table Dump", "Connect Out", "Register Slave", - "Prepare", "Prepare Execute", "Long Data", "Close stmt" + "Prepare", "Prepare Execute", "Long Data", "Close stmt", + "Error" // Last command number }; static char empty_c_string[1]= {0}; // Used for not defined 'db' @@ -211,7 +212,7 @@ static int check_user(THD *thd,enum_server_command command, const char *user, cur_priv_version,hint_user); DBUG_PRINT("info", - ("Capabilities: %d packet_length: %d Host: '%s' User: '%s' Using password: %s Access: %u db: '%s'", + ("Capabilities: %d packet_length: %ld Host: '%s' User: '%s' Using password: %s Access: %u db: '%s'", thd->client_capabilities, thd->max_client_packet_length, thd->host_or_ip, thd->priv_user, had_password ? "yes": "no", @@ -516,7 +517,8 @@ check_connections(THD *thd) { vio_in_addr(net->vio,&thd->remote.sin_addr); thd->host=ip_to_hostname(&thd->remote.sin_addr,&connect_errors); - thd->host[strnlen(thd->host, HOSTNAME_LENGTH)]= 0; + /* Cut very long hostnames to avoid possible overflows */ + thd->host[min(strlen(thd->host), HOSTNAME_LENGTH)]= 0; if (connect_errors > max_connect_errors) return(ER_HOST_IS_BLOCKED); } @@ -967,20 +969,22 @@ bool do_command(THD *thd) net_new_transaction(net); if ((packet_length=my_net_read(net)) == packet_error) { - DBUG_PRINT("info",("Got error reading command from socket %s", - vio_description(net->vio) )); - return TRUE; - } - else if (!packet_length) - { + DBUG_PRINT("info",("Got error %d reading command from socket %s", + net->error, + vio_description(net->vio))); + /* Check if we can continue without closing the connection */ + if (net->error != 3) + DBUG_RETURN(TRUE); // We have to close it. send_error(thd,net->last_errno,NullS); - net->error=0; + net->error= 0; DBUG_RETURN(FALSE); } else { packet=(char*) net->read_pos; command = (enum enum_server_command) (uchar) packet[0]; + if (command >= COM_END) + command= COM_END; // Wrong command DBUG_PRINT("info",("Command on %s = %d (%s)", vio_description(net->vio), command, command_name[command])); @@ -1184,7 +1188,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, if (alloc_query(thd, packet, packet_length)) break; // fatal error is set mysql_log.write(thd,command,"%s",thd->query); - DBUG_PRINT("query",("%s",thd->query)); + DBUG_PRINT("query",("%-.4096s",thd->query)); mysql_parse(thd,thd->query, thd->query_length); if (!(specialflag & SPECIAL_NO_PRIOR)) my_pthread_setprio(pthread_self(),WAIT_PRIOR); @@ -1381,6 +1385,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, case COM_CONNECT: // Impossible here case COM_TIME: // Impossible from client case COM_DELAYED_INSERT: + case COM_END: default: send_error(thd, ER_UNKNOWN_COM_ERROR); break; @@ -2282,6 +2287,7 @@ mysql_execute_command(THD *thd) for (auxi=(TABLE_LIST*) aux_tables ; auxi ; auxi=auxi->next) auxi->table= auxi->table_list->table; if (&lex->select_lex != lex->all_selects_list) + { for (TABLE_LIST *t= select_lex->get_table_list(); t; t= t->next) { @@ -2292,6 +2298,7 @@ mysql_execute_command(THD *thd) break; } } + } fix_tables_pointers(lex->all_selects_list); if (!thd->fatal_error && (result= new multi_delete(thd,aux_tables, table_count))) diff --git a/sql/table.cc b/sql/table.cc index 84a072c886d..72f0143115f 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -146,7 +146,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, bzero((char*) keyinfo,n_length); outparam->key_info=keyinfo; outparam->max_key_length= outparam->total_key_length= 0; - key_part= (KEY_PART_INFO*) (keyinfo+keys); + key_part= my_reinterpret_cast(KEY_PART_INFO*) (keyinfo+keys); strpos=disk_buff+6; ulong *rec_per_key; diff --git a/tests/big_record.pl b/tests/big_record.pl index 52d3dca5f7b..08547b50823 100755 --- a/tests/big_record.pl +++ b/tests/big_record.pl @@ -1,58 +1,69 @@ #!/usr/bin/perl -# This is a test with stores big records in a blob +# This is a test with stores big records in a blob. # Note that for the default test the mysql server should have been -# started with at least 'mysqld -O max_allowed_packet=200k' - -$host= shift || ""; -$test_db="test"; -$opt_user=$opt_password=""; +# started with at least 'mysqld -O max_allowed_packet=30M' and you should have +# at least 256M memory in your computer. use DBI; -$|= 1; # Autoflush +use Getopt::Long; + +$opt_host=""; +$opt_user=$opt_password=""; +$opt_db="test"; +$opt_rows=200; # Test of blobs up to ($rows-1)*100000+1 bytes +$opt_compress=0; +$opt_table="test_big_record"; -$table="test_big_record"; -$rows=20; # Test of blobs up to ($rows-1)*10000+1 bytes +GetOptions("host=s","db=s","user=s", "password=s", "table=s", "rows=i", + "compress") || die "Aborted"; print "Connection to database $test_db\n"; -$dbh = DBI->connect("DBI:mysql:$test_db:$host",$opt_user,$opt_password) || die "Can't connect: $DBI::errstr\n"; +$extra_options=""; +$extra_options.=":mysql_compression=1" if ($opt_compress); -$dbh->do("drop table if exists $table"); +$dbh = DBI->connect("DBI:mysql:$opt_db:$host$extra_options",$opt_user,$opt_password) || die "Can't connect: $DBI::errstr\n"; -print "Creating table $table\n"; +$dbh->do("drop table if exists $opt_table"); + +print "Creating table $opt_table\n"; ($dbh->do("\ -CREATE TABLE $table ( +CREATE TABLE $opt_table ( auto int(5) unsigned NOT NULL DEFAULT '0' auto_increment, - test mediumblob, + test longblob, PRIMARY KEY (auto))")) or die $DBI::errstr; -print "Inserting $rows records\n"; +print "Inserting $opt_rows records\n"; + +$|=1; # Flush output to stdout to be able to monitor process -for ($i=0 ; $i < $rows ; $i++) +for ($i=0 ; $i < $opt_rows ; $i++) { - $tmp= chr(65+$i) x ($i*10000+1); + $tmp= chr(65+($i % 16)) x ($i*100000+1); + print $i," ",length($tmp),"\n"; $tmp= $dbh->quote($tmp); - $dbh->do("insert into $table (test) values ($tmp)") or die $DBI::errstr; + $dbh->do("insert into $opt_table (test) values ($tmp)") or die $DBI::errstr; } -print "Testing records\n"; +print "Reading records\n"; + +$sth=$dbh->prepare("select * from $opt_table", { "mysql_use_result" => 1}) or die $dbh->errstr; -$sth=$dbh->prepare("select * from $table") or die $dbh->errstr; $sth->execute() or die $sth->errstr; $i=0; while (($row = $sth->fetchrow_arrayref)) { print $row->[0]," ",length($row->[1]),"\n"; - die "Record $i had wrong data in blob" if ($row->[1] ne (chr(65+$i)) x ($i*10000+1)); + die "Record $i had wrong data in blob" if ($row->[1] ne (chr(65+($i % 16)) x ($i*100000+1))); $i++; } -die "Didn't get all rows from server" if ($i != $rows); +die "Didn't get all rows from server" if ($i != $opt_rows); -$dbh->do("drop table $table") or die $DBI::errstr; +$dbh->do("drop table $opt_table") or die $DBI::errstr; print "Test ok\n"; exit 0; diff --git a/tools/mysqlmanager.c b/tools/mysqlmanager.c index 6a246f096c8..4f2deeb0052 100644 --- a/tools/mysqlmanager.c +++ b/tools/mysqlmanager.c @@ -1241,7 +1241,7 @@ static void handle_child(int __attribute__((unused)) sig) signal(SIGCHLD,handle_child); } -struct manager_thd* manager_thd_new(Vio* vio) +static struct manager_thd* manager_thd_new(Vio* vio) { struct manager_thd* tmp; if (!(tmp=(struct manager_thd*)my_malloc(sizeof(*tmp), |