summaryrefslogtreecommitdiff
path: root/client
diff options
context:
space:
mode:
Diffstat (limited to 'client')
-rw-r--r--client/my_readline.h2
-rw-r--r--client/mysql.cc61
-rw-r--r--client/mysqladmin.cc2
-rw-r--r--client/mysqlbinlog.cc18
-rw-r--r--client/mysqlcheck.c9
-rw-r--r--client/mysqldump.c5
-rw-r--r--client/mysqlslap.c2
-rw-r--r--client/mysqltest.cc38
-rw-r--r--client/readline.cc46
-rw-r--r--client/sql_string.cc2
10 files changed, 116 insertions, 69 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 ccbd4583079..132b5cec7a3 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -49,7 +49,7 @@ const char *VER= "14.15";
#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;
@@ -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));
@@ -1817,13 +1820,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
@@ -1920,7 +1924,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 */
@@ -2007,7 +2011,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;
@@ -2257,9 +2261,10 @@ static bool add_line(String &buffer,char *line,char *in_string,
{
uint length=(uint) (out-line);
- if (length < 9 ||
- my_strnncoll (charset_info,
- (uchar *)line, 9, (const uchar *) "delimiter", 9))
+ 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
@@ -2672,7 +2677,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);
}
@@ -3932,7 +3937,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);
@@ -4381,16 +4386,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)))
@@ -4398,17 +4398,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 f06bc6ee9ed..9a9377026fb 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 0f75f0b7315..5a1fa3cc090 100644
--- a/client/mysqldump.c
+++ b/client/mysqldump.c
@@ -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)
{
@@ -4588,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 a2de6a16af3..69a5969c3b0 100644
--- a/client/mysqlslap.c
+++ b/client/mysqlslap.c
@@ -1936,7 +1936,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 d1fa33fcf00..eadaf9eba24 100644
--- a/client/mysqltest.cc
+++ b/client/mysqltest.cc
@@ -1325,7 +1325,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)
@@ -1454,6 +1454,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
@@ -1461,11 +1462,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")))
@@ -1497,7 +1499,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");
@@ -1510,15 +1512,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,
@@ -1529,7 +1536,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,
@@ -1540,20 +1547,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
@@ -2682,7 +2689,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",
@@ -7209,7 +7217,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);
}
}
@@ -7265,7 +7273,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;
}
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 5a922b9361c..dc6147b563f 100644
--- a/client/sql_string.cc
+++ b/client/sql_string.cc
@@ -465,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));
}