diff options
Diffstat (limited to 'client')
-rw-r--r-- | client/my_readline.h | 2 | ||||
-rw-r--r-- | client/mysql.cc | 77 | ||||
-rw-r--r-- | client/mysqladmin.cc | 2 | ||||
-rw-r--r-- | client/mysqlbinlog.cc | 18 | ||||
-rw-r--r-- | client/mysqlcheck.c | 9 | ||||
-rw-r--r-- | client/mysqldump.c | 18 | ||||
-rw-r--r-- | client/mysqlslap.c | 2 | ||||
-rw-r--r-- | client/mysqltest.cc | 54 | ||||
-rw-r--r-- | client/readline.cc | 46 | ||||
-rw-r--r-- | client/sql_string.cc | 21 |
10 files changed, 161 insertions, 88 deletions
diff --git a/client/my_readline.h b/client/my_readline.h index 3ebe24b75b8..62ad19bece9 100644 --- a/client/my_readline.h +++ b/client/my_readline.h @@ -29,5 +29,5 @@ typedef struct st_line_buffer extern LINE_BUFFER *batch_readline_init(ulong max_size,FILE *file); extern LINE_BUFFER *batch_readline_command(LINE_BUFFER *buffer, char * str); -extern char *batch_readline(LINE_BUFFER *buffer); +extern char *batch_readline(LINE_BUFFER *buffer, bool *truncated); extern void batch_readline_end(LINE_BUFFER *buffer); diff --git a/client/mysql.cc b/client/mysql.cc index 65512e695b8..46141cd975f 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -49,7 +49,7 @@ const char *VER= "14.14"; #define MAX_COLUMN_LENGTH 1024 /* Buffer to hold 'version' and 'version_comment' */ -#define MAX_SERVER_VERSION_LENGTH 128 +static char *server_version= NULL; /* Array of options to pass to libemysqld */ #define MAX_SERVER_ARGS 64 @@ -115,6 +115,8 @@ extern "C" { #define PROMPT_CHAR '\\' #define DEFAULT_DELIMITER ";" +#define MAX_BATCH_BUFFER_SIZE (1024L * 1024L) + typedef struct st_status { int exit_status; @@ -246,11 +248,11 @@ typedef struct { static COMMANDS commands[] = { { "?", '?', com_help, 1, "Synonym for `help'." }, - { "clear", 'c', com_clear, 0, "Clear command."}, + { "clear", 'c', com_clear, 0, "Clear the current input statement."}, { "connect",'r', com_connect,1, "Reconnect to the server. Optional arguments are db and host." }, { "delimiter", 'd', com_delimiter, 1, - "Set statement delimiter. NOTE: Takes the rest of the line as new delimiter." }, + "Set statement delimiter." }, #ifdef USE_POPEN { "edit", 'e', com_edit, 0, "Edit command with $EDITOR."}, #endif @@ -1045,7 +1047,7 @@ static void fix_history(String *final_command); static COMMANDS *find_command(char *name,char cmd_name); static bool add_line(String &buffer,char *line,char *in_string, - bool *ml_comment); + bool *ml_comment, bool truncated); static void remove_cntrl(String &buffer); static void print_table_data(MYSQL_RES *result); static void print_table_data_html(MYSQL_RES *result); @@ -1117,7 +1119,7 @@ int main(int argc,char *argv[]) exit(1); } if (status.batch && !status.line_buff && - !(status.line_buff=batch_readline_init(opt_max_allowed_packet+512,stdin))) + !(status.line_buff= batch_readline_init(MAX_BATCH_BUFFER_SIZE, stdin))) { free_defaults(defaults_argv); my_end(0); @@ -1198,7 +1200,7 @@ int main(int argc,char *argv[]) #endif sprintf(buff, "%s", #ifndef NOT_YET - "Type 'help;' or '\\h' for help. Type '\\c' to clear the buffer.\n"); + "Type 'help;' or '\\h' for help. Type '\\c' to clear the current input statement.\n"); #else "Type 'help [[%]function name[%]]' to get help on usage of function.\n"); #endif @@ -1234,6 +1236,7 @@ sig_handler mysql_end(int sig) glob_buffer.free(); old_buffer.free(); processed_prompt.free(); + my_free(server_version,MYF(MY_ALLOW_ZERO_PTR)); my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR)); my_free(opt_mysql_unix_port,MYF(MY_ALLOW_ZERO_PTR)); my_free(histfile,MYF(MY_ALLOW_ZERO_PTR)); @@ -1810,13 +1813,14 @@ static int read_and_execute(bool interactive) ulong line_number=0; bool ml_comment= 0; COMMANDS *com; + bool truncated= 0; status.exit_status=1; for (;;) { if (!interactive) { - line=batch_readline(status.line_buff); + line=batch_readline(status.line_buff, &truncated); /* Skip UTF8 Byte Order Marker (BOM) 0xEFBBBF. Editors like "notepad" put this marker in @@ -1913,7 +1917,7 @@ static int read_and_execute(bool interactive) #endif continue; } - if (add_line(glob_buffer,line,&in_string,&ml_comment)) + if (add_line(glob_buffer,line,&in_string,&ml_comment, truncated)) break; } /* if in batch mode, send last query even if it doesn't end with \g or go */ @@ -1999,7 +2003,7 @@ static COMMANDS *find_command(char *name,char cmd_char) static bool add_line(String &buffer,char *line,char *in_string, - bool *ml_comment) + bool *ml_comment, bool truncated) { uchar inchar; char buff[80], *pos, *out; @@ -2245,8 +2249,23 @@ static bool add_line(String &buffer,char *line,char *in_string, } if (out != line || !buffer.is_empty()) { - *out++='\n'; uint length=(uint) (out-line); + + if (!truncated && + (length < 9 || + my_strnncoll (charset_info, + (uchar *)line, 9, (const uchar *) "delimiter", 9))) + { + /* + Don't add a new line in case there's a DELIMITER command to be + added to the glob buffer (e.g. on processing a line like + "<command>;DELIMITER <non-eof>") : similar to how a new line is + not added in the case when the DELIMITER is the first command + entered with an empty glob buffer. + */ + *out++='\n'; + length++; + } if (buffer.length() + length >= buffer.alloced_length()) buffer.realloc(buffer.length()+length+IO_SIZE); if ((!*ml_comment || preserve_comments) && buffer.append(line, length)) @@ -2648,7 +2667,7 @@ static void get_current_db() (res= mysql_use_result(&mysql))) { MYSQL_ROW row= mysql_fetch_row(res); - if (row[0]) + if (row && row[0]) current_db= my_strdup(row[0], MYF(MY_WME)); mysql_free_result(res); } @@ -2855,7 +2874,7 @@ com_charset(String *buffer __attribute__((unused)), char *line) param= get_arg(buff, 0); if (!param || !*param) { - return put_info("Usage: \\C char_setname | charset charset_name", + return put_info("Usage: \\C charset_name | charset charset_name", INFO_ERROR, 0); } new_cs= get_charset_by_csname(param, MY_CS_PRIMARY, MYF(MY_WME)); @@ -3907,7 +3926,7 @@ static int com_source(String *buffer, char *line) return put_info(buff, INFO_ERROR, 0); } - if (!(line_buff=batch_readline_init(opt_max_allowed_packet+512,sql_file))) + if (!(line_buff= batch_readline_init(MAX_BATCH_BUFFER_SIZE, sql_file))) { my_fclose(sql_file,MYF(0)); return put_info("Can't initialize batch_readline", INFO_ERROR, 0); @@ -4347,16 +4366,11 @@ select_limit, max_join_size); static const char * server_version_string(MYSQL *con) { - static char buf[MAX_SERVER_VERSION_LENGTH] = ""; - /* Only one thread calls this, so no synchronization is needed */ - if (buf[0] == '\0') + if (server_version == NULL) { - char *bufp = buf; MYSQL_RES *result; - bufp= strnmov(buf, mysql_get_server_info(con), sizeof buf); - /* "limit 1" is protection against SQL_SELECT_LIMIT=0 */ if (!mysql_query(con, "select @@version_comment limit 1") && (result = mysql_use_result(con))) @@ -4364,17 +4378,32 @@ server_version_string(MYSQL *con) MYSQL_ROW cur = mysql_fetch_row(result); if (cur && cur[0]) { - bufp = strxnmov(bufp, sizeof buf - (bufp - buf), " ", cur[0], NullS); + /* version, space, comment, \0 */ + size_t len= strlen(mysql_get_server_info(con)) + strlen(cur[0]) + 2; + + if ((server_version= (char *) my_malloc(len, MYF(MY_WME)))) + { + char *bufp; + bufp = strmov(server_version, mysql_get_server_info(con)); + bufp = strmov(bufp, " "); + (void) strmov(bufp, cur[0]); + } } mysql_free_result(result); } - /* str*nmov doesn't guarantee NUL-termination */ - if (bufp == buf + sizeof buf) - buf[sizeof buf - 1] = '\0'; + /* + If for some reason we didn't get a version_comment, we'll + keep things simple. + */ + + if (server_version == NULL) + { + server_version= strdup(mysql_get_server_info(con)); + } } - return buf; + return server_version ? server_version : ""; } static int diff --git a/client/mysqladmin.cc b/client/mysqladmin.cc index 1e3249dd92a..df0dc1e7049 100644 --- a/client/mysqladmin.cc +++ b/client/mysqladmin.cc @@ -837,7 +837,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv) bool old= (find_type(argv[0], &command_typelib, 2) == ADMIN_OLD_PASSWORD); #ifdef __WIN__ - uint pw_len= strlen(pw); + uint pw_len= (uint) strlen(pw); if (pw_len > 1 && pw[0] == '\'' && pw[pw_len-1] == '\'') printf("Warning: single quotes were not trimmed from the password by" " your command\nline client, as you might have expected.\n"); diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index 0b8e843887d..1621db5ded8 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -128,7 +128,7 @@ static Exit_status safe_connect(); class Load_log_processor { char target_dir_name[FN_REFLEN]; - int target_dir_name_len; + size_t target_dir_name_len; /* When we see first event corresponding to some LOAD DATA statement in @@ -285,9 +285,9 @@ public: File prepare_new_file_for_old_format(Load_log_event *le, char *filename); Exit_status load_old_format_file(NET* net, const char *server_fname, uint server_fname_len, File file); - Exit_status process_first_event(const char *bname, uint blen, + Exit_status process_first_event(const char *bname, size_t blen, const uchar *block, - uint block_len, uint file_id, + size_t block_len, uint file_id, Create_file_log_event *ce); }; @@ -305,7 +305,7 @@ public: File Load_log_processor::prepare_new_file_for_old_format(Load_log_event *le, char *filename) { - uint len; + size_t len; char *tail; File file; @@ -319,7 +319,7 @@ File Load_log_processor::prepare_new_file_for_old_format(Load_log_event *le, return -1; } - le->set_fname_outside_temp_buf(filename,len+strlen(tail)); + le->set_fname_outside_temp_buf(filename,len+(uint) strlen(tail)); return file; } @@ -411,9 +411,9 @@ Exit_status Load_log_processor::load_old_format_file(NET* net, @retval OK_CONTINUE No error, the program should continue. */ Exit_status Load_log_processor::process_first_event(const char *bname, - uint blen, + size_t blen, const uchar *block, - uint block_len, + size_t block_len, uint file_id, Create_file_log_event *ce) { @@ -456,7 +456,7 @@ Exit_status Load_log_processor::process_first_event(const char *bname, } if (ce) - ce->set_fname_outside_temp_buf(fname, strlen(fname)); + ce->set_fname_outside_temp_buf(fname, (uint) strlen(fname)); if (my_write(file, (uchar*)block, block_len, MYF(MY_WME|MY_NABP))) { @@ -1189,7 +1189,7 @@ static my_time_t convert_str_to_timestamp(const char* str) long dummy_my_timezone; my_bool dummy_in_dst_time_gap; /* We require a total specification (date AND time) */ - if (str_to_datetime(str, strlen(str), &l_time, 0, &was_cut) != + if (str_to_datetime(str, (uint) strlen(str), &l_time, 0, &was_cut) != MYSQL_TIMESTAMP_DATETIME || was_cut) { error("Incorrect date and time argument: %s", str); diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c index 86e1b3352b4..d2edd084c57 100644 --- a/client/mysqlcheck.c +++ b/client/mysqlcheck.c @@ -349,7 +349,7 @@ static int get_options(int *argc, char ***argv) if (!what_to_do) { - int pnlen = strlen(my_progname); + size_t pnlen= strlen(my_progname); if (pnlen < 6) /* name too short */ what_to_do = DO_CHECK; @@ -448,7 +448,8 @@ static int process_selected_tables(char *db, char **table_names, int tables) space is for more readable output in logs and in case of error */ char *table_names_comma_sep, *end; - int i, tot_length = 0; + size_t tot_length= 0; + int i= 0; for (i = 0; i < tables; i++) tot_length+= fixed_name_length(*(table_names + i)) + 2; @@ -464,7 +465,7 @@ static int process_selected_tables(char *db, char **table_names, int tables) *end++= ','; } *--end = 0; - handle_request_for_tables(table_names_comma_sep + 1, tot_length - 1); + handle_request_for_tables(table_names_comma_sep + 1, (uint) (tot_length - 1)); my_free(table_names_comma_sep, MYF(0)); } else @@ -486,7 +487,7 @@ static uint fixed_name_length(const char *name) else if (*p == '.') extra_length+= 2; } - return (p - name) + extra_length; + return (uint) ((p - name) + extra_length); } diff --git a/client/mysqldump.c b/client/mysqldump.c index 44c53a0e4c2..5a1fa3cc090 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -1,4 +1,4 @@ -/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. +/* Copyright 2000-2008 MySQL AB, 2008, 2009 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -802,7 +802,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), opt_set_charset= 0; opt_compatible_mode_str= argument; opt_compatible_mode= find_set(&compatible_mode_typelib, - argument, strlen(argument), + argument, (uint) strlen(argument), &err_ptr, &err_len); if (err_len) { @@ -1475,7 +1475,8 @@ static int connect_to_db(char *host, char *user,char *passwd) DB_error(&mysql_connection, "when trying to connect"); DBUG_RETURN(1); } - if (mysql_get_server_version(&mysql_connection) < 40100) + if ((mysql_get_server_version(&mysql_connection) < 40100) || + (opt_compatible_mode & 3)) { /* Don't dump SET NAMES with a pre-4.1 server (bug#7997). */ opt_set_charset= 0; @@ -2421,11 +2422,11 @@ static uint get_table_structure(char *table, char *db, char *table_type, row= mysql_fetch_row(result); - fprintf(sql_file, - "SET @saved_cs_client = @@character_set_client;\n" - "SET character_set_client = utf8;\n" + fprintf(sql_file, (opt_compatible_mode & 3) ? "%s;\n" : + "/*!40101 SET @saved_cs_client = @@character_set_client */;\n" + "/*!40101 SET character_set_client = utf8 */;\n" "%s;\n" - "SET character_set_client = @saved_cs_client;\n", + "/*!40101 SET character_set_client = @saved_cs_client */;\n", row[1]); check_io(sql_file); @@ -4587,7 +4588,8 @@ char check_if_ignore_table(const char *table_name, char *table_type) */ if (!opt_no_data && (!my_strcasecmp(&my_charset_latin1, table_type, "MRG_MyISAM") || - !strcmp(table_type,"MRG_ISAM"))) + !strcmp(table_type,"MRG_ISAM") || + !strcmp(table_type,"FEDERATED"))) result= IGNORE_DATA; } mysql_free_result(res); diff --git a/client/mysqlslap.c b/client/mysqlslap.c index 9ba912d646c..b8515289df5 100644 --- a/client/mysqlslap.c +++ b/client/mysqlslap.c @@ -1929,7 +1929,7 @@ parse_option(const char *origin, option_string **stmt, char delm) char *ptr= (char *)origin; option_string **sptr= stmt; option_string *tmp; - uint length= strlen(origin); + size_t length= strlen(origin); uint count= 0; /* We know that there is always one */ for (tmp= *sptr= (option_string *)my_malloc(sizeof(option_string), diff --git a/client/mysqltest.cc b/client/mysqltest.cc index 89b9c78a049..fdd4ff141bc 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -1316,7 +1316,7 @@ void log_msg(const char *fmt, ...) void cat_file(DYNAMIC_STRING* ds, const char* filename) { int fd; - uint len; + size_t len; char buff[512]; if ((fd= my_open(filename, O_RDONLY, MYF(0))) < 0) @@ -1445,6 +1445,7 @@ static int run_tool(const char *tool_path, DYNAMIC_STRING *ds_res, ...) Test if diff is present. This is needed on Windows systems as the OS returns 1 whether diff is successful or if it is not present. + Takes name of diff program as argument We run diff -v and look for output in stdout. We don't redirect stderr to stdout to make for a simplified check @@ -1452,11 +1453,12 @@ static int run_tool(const char *tool_path, DYNAMIC_STRING *ds_res, ...) not present. */ -int diff_check() +int diff_check (const char *diff_name) { char buf[512]= {0}; FILE *res_file; - const char *cmd = "diff -v"; + char cmd[128]; + my_snprintf (cmd, sizeof(cmd), "%s -v", diff_name); int have_diff = 0; if (!(res_file= popen(cmd, "r"))) @@ -1488,7 +1490,7 @@ void show_diff(DYNAMIC_STRING* ds, const char* filename1, const char* filename2) { DYNAMIC_STRING ds_tmp; - int have_diff = 0; + const char *diff_name = 0; if (init_dynamic_string(&ds_tmp, "", 256, 256)) die("Out of memory"); @@ -1501,15 +1503,20 @@ void show_diff(DYNAMIC_STRING* ds, the way it's implemented does not work with default 'diff' on Solaris. */ #ifdef __WIN__ - have_diff = diff_check(); + if (diff_check("diff")) + diff_name = "diff"; + else if (diff_check("mtrdiff")) + diff_name = "mtrdiff"; + else + diff_name = 0; #else - have_diff = 1; + diff_name = "diff"; // Otherwise always assume it's called diff #endif - if (have_diff) + if (diff_name) { /* First try with unified diff */ - if (run_tool("diff", + if (run_tool(diff_name, &ds_tmp, /* Get output from diff in ds_tmp */ "-u", filename1, @@ -1520,7 +1527,7 @@ void show_diff(DYNAMIC_STRING* ds, dynstr_set(&ds_tmp, ""); /* Fallback to context diff with "diff -c" */ - if (run_tool("diff", + if (run_tool(diff_name, &ds_tmp, /* Get output from diff in ds_tmp */ "-c", filename1, @@ -1531,20 +1538,20 @@ void show_diff(DYNAMIC_STRING* ds, dynstr_set(&ds_tmp, ""); /* Fallback to simple diff with "diff" */ - if (run_tool("diff", + if (run_tool(diff_name, &ds_tmp, /* Get output from diff in ds_tmp */ filename1, filename2, "2>&1", NULL) > 1) /* Most "diff" tools return >1 if error */ { - have_diff= 0; + diff_name= 0; } } } } - if (! have_diff) + if (! diff_name) { /* Fallback to dump both files to result file and inform @@ -1614,7 +1621,7 @@ int compare_files2(File fd, const char* filename2) { int error= RESULT_OK; File fd2; - uint len, len2; + size_t len, len2; char buff[512], buff2[512]; if ((fd2= my_open(filename2, O_RDONLY, MYF(0))) < 0) @@ -2653,7 +2660,8 @@ void do_exec(struct st_command *command) log_msg("exec of '%s' failed, error: %d, status: %d, errno: %d", ds_cmd.str, error, status, errno); dynstr_free(&ds_cmd); - die("command \"%s\" failed", command->first_argument); + die("command \"%s\" failed\n\nOutput from before failure:\n%s\n", + command->first_argument, ds_res.str); } DBUG_PRINT("info", @@ -4647,6 +4655,10 @@ void safe_connect(MYSQL* mysql, const char *name, const char *host, int failed_attempts= 0; DBUG_ENTER("safe_connect"); + + verbose_msg("Connecting to server %s:%d (socket %s) as '%s'" + ", connection '%s', attempt %d ...", + host, port, sock, user, name, failed_attempts); while(!mysql_real_connect(mysql, host,user, pass, db, port, sock, CLIENT_MULTI_STATEMENTS | CLIENT_REMEMBER_OPTIONS)) { @@ -4678,6 +4690,7 @@ void safe_connect(MYSQL* mysql, const char *name, const char *host, } failed_attempts++; } + verbose_msg("... Connected."); DBUG_VOID_RETURN; } @@ -7156,7 +7169,7 @@ void init_re_comp(my_regex_t *re, const char* str) char erbuf[100]; int len= my_regerror(err, re, erbuf, sizeof(erbuf)); die("error %s, %d/%d `%s'\n", - re_eprint(err), len, (int)sizeof(erbuf), erbuf); + re_eprint(err), (int)len, (int)sizeof(erbuf), erbuf); } } @@ -7212,7 +7225,7 @@ int match_re(my_regex_t *re, char *str) char erbuf[100]; int len= my_regerror(err, re, erbuf, sizeof(erbuf)); die("error %s, %d/%d `%s'\n", - re_eprint(err), len, (int)sizeof(erbuf), erbuf); + re_eprint(err), (int)len, (int)sizeof(erbuf), erbuf); } return 0; } @@ -7511,8 +7524,12 @@ int main(int argc, char **argv) parse_args(argc, argv); log_file.open(opt_logdir, result_file_name, ".log"); + verbose_msg("Logging to '%s'.", log_file.file_name()); if (opt_mark_progress) + { progress_file.open(opt_logdir, result_file_name, ".progress"); + verbose_msg("Tracing progress in '%s'.", progress_file.file_name()); + } var_set_int("$PS_PROTOCOL", ps_protocol); var_set_int("$SP_PROTOCOL", sp_protocol); @@ -7521,6 +7538,8 @@ int main(int argc, char **argv) DBUG_PRINT("info",("result_file: '%s'", result_file_name ? result_file_name : "")); + verbose_msg("Results saved in '%s'.", + result_file_name ? result_file_name : ""); if (mysql_server_init(embedded_server_arg_count, embedded_server_args, (char**) embedded_server_groups)) @@ -7591,6 +7610,7 @@ int main(int argc, char **argv) open_file(opt_include); } + verbose_msg("Start processing test commands from '%s' ...", cur_file->file_name); while (!read_command(&command) && !abort_flag) { int current_line_inc = 1, processed = 0; @@ -7908,6 +7928,7 @@ int main(int argc, char **argv) log_file.close(); start_lineno= 0; + verbose_msg("... Done processing test commands."); if (parsing_disabled) die("Test ended with parsing disabled"); @@ -7958,6 +7979,7 @@ int main(int argc, char **argv) if (!command_executed && result_file_name) die("No queries executed but result file found!"); + verbose_msg("Test has succeeded!"); timer_output(); /* Yes, if we got this far the test has suceeded! Sakila smiles */ cleanup_and_exit(0); diff --git a/client/readline.cc b/client/readline.cc index 7afdbc9531e..b32cb71b0de 100644 --- a/client/readline.cc +++ b/client/readline.cc @@ -24,7 +24,7 @@ static bool init_line_buffer(LINE_BUFFER *buffer,File file,ulong size, ulong max_size); static bool init_line_buffer_from_string(LINE_BUFFER *buffer,char * str); static size_t fill_buffer(LINE_BUFFER *buffer); -static char *intern_read_line(LINE_BUFFER *buffer,ulong *out_length); +static char *intern_read_line(LINE_BUFFER *buffer, ulong *out_length, bool *truncated); LINE_BUFFER *batch_readline_init(ulong max_size,FILE *file) @@ -42,12 +42,13 @@ LINE_BUFFER *batch_readline_init(ulong max_size,FILE *file) } -char *batch_readline(LINE_BUFFER *line_buff) +char *batch_readline(LINE_BUFFER *line_buff, bool *truncated) { char *pos; ulong out_length; + DBUG_ASSERT(truncated != NULL); - if (!(pos=intern_read_line(line_buff,&out_length))) + if (!(pos=intern_read_line(line_buff,&out_length, truncated))) return 0; if (out_length && pos[out_length-1] == '\n') if (--out_length && pos[out_length-1] == '\r') /* Remove '\n' */ @@ -149,6 +150,14 @@ static size_t fill_buffer(LINE_BUFFER *buffer) read_count=(buffer->bufread - bufbytes)/IO_SIZE; if ((read_count*=IO_SIZE)) break; + if (buffer->bufread * 2 > buffer->max_size) + { + /* + So we must grow the buffer but we cannot due to the max_size limit. + Return 0 w/o setting buffer->eof to signal this condition. + */ + return 0; + } buffer->bufread *= 2; if (!(buffer->buffer = (char*) my_realloc(buffer->buffer, buffer->bufread+1, @@ -172,11 +181,15 @@ static size_t fill_buffer(LINE_BUFFER *buffer) DBUG_PRINT("fill_buff", ("Got %lu bytes", (ulong) read_count)); - /* Kludge to pretend every nonempty file ends with a newline. */ - if (!read_count && bufbytes && buffer->end[-1] != '\n') + if (!read_count) { - buffer->eof = read_count = 1; - *buffer->end = '\n'; + buffer->eof = 1; + /* Kludge to pretend every nonempty file ends with a newline. */ + if (bufbytes && buffer->end[-1] != '\n') + { + read_count = 1; + *buffer->end = '\n'; + } } buffer->end_of_line=(buffer->start_of_line=buffer->buffer)+bufbytes; buffer->end+=read_count; @@ -186,7 +199,7 @@ static size_t fill_buffer(LINE_BUFFER *buffer) -char *intern_read_line(LINE_BUFFER *buffer,ulong *out_length) +char *intern_read_line(LINE_BUFFER *buffer, ulong *out_length, bool *truncated) { char *pos; size_t length; @@ -200,14 +213,23 @@ char *intern_read_line(LINE_BUFFER *buffer,ulong *out_length) pos++; if (pos == buffer->end) { - if ((uint) (pos - buffer->start_of_line) < buffer->max_size) + /* + fill_buffer() can return 0 either on EOF in which case we abort + or when the internal buffer has hit the size limit. In the latter case + return what we have read so far and signal string truncation. + */ + if (!(length=fill_buffer(buffer)) || length == (uint) -1) { - if (!(length=fill_buffer(buffer)) || length == (size_t) -1) - DBUG_RETURN(0); - continue; + if (buffer->eof) + DBUG_RETURN(0); } + else + continue; pos--; /* break line here */ + *truncated= 1; } + else + *truncated= 0; buffer->end_of_line=pos+1; *out_length=(ulong) (pos + 1 - buffer->eof - buffer->start_of_line); DBUG_RETURN(buffer->start_of_line); diff --git a/client/sql_string.cc b/client/sql_string.cc index c41463999aa..dc6147b563f 100644 --- a/client/sql_string.cc +++ b/client/sql_string.cc @@ -71,25 +71,22 @@ bool String::realloc(uint32 alloc_length) char *new_ptr; if (alloced) { - if ((new_ptr= (char*) my_realloc(Ptr,len,MYF(MY_WME)))) - { - Ptr=new_ptr; - Alloced_length=len; - } - else - return TRUE; // Signal error + if (!(new_ptr= (char*) my_realloc(Ptr,len,MYF(MY_WME)))) + return TRUE; // Signal error } else if ((new_ptr= (char*) my_malloc(len,MYF(MY_WME)))) { + if (str_length > len - 1) + str_length= 0; if (str_length) // Avoid bugs in memcpy on AIX memcpy(new_ptr,Ptr,str_length); new_ptr[str_length]=0; - Ptr=new_ptr; - Alloced_length=len; alloced=1; } else return TRUE; // Signal error + Ptr= new_ptr; + Alloced_length= len; } Ptr[alloc_length]=0; // This make other funcs shorter return FALSE; @@ -125,7 +122,7 @@ bool String::set(double num,uint decimals, CHARSET_INFO *cs) str_charset=cs; if (decimals >= NOT_FIXED_DEC) { - uint32 len= my_sprintf(buff,(buff, "%.14g",num));// Enough for a DATETIME + uint32 len= my_sprintf(buff,(buff, "%.15g",num));// Enough for a DATETIME return copy(buff, len, &my_charset_latin1, cs, &dummy_errors); } #ifdef HAVE_FCONVERT @@ -468,7 +465,7 @@ bool String::append(const char *s,uint32 arg_length) bool String::append(const char *s) { - return append(s, strlen(s)); + return append(s, (uint) strlen(s)); } @@ -677,7 +674,7 @@ void String::qs_append(const char *str, uint32 len) void String::qs_append(double d) { char *buff = Ptr + str_length; - str_length+= my_sprintf(buff, (buff, "%.14g", d)); + str_length+= my_sprintf(buff, (buff, "%.15g", d)); } void String::qs_append(double *d) |