Skip to content

Commit 62f4505

Browse files
committed
MDEV-36269: improve error handling for source command
- refactor and move batch_readline_init to mysql.cc for proper error handling - add unit test and move it to the end of main/mysql_client_test.test to resolve embedded test failures - remove unnecessary code and duplicates to clean up implementation - redirect error message from stderr to stdout in .test file - use labels to avoid code duplication
1 parent c4264c9 commit 62f4505

File tree

5 files changed

+92
-45
lines changed

5 files changed

+92
-45
lines changed

client/my_readline.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@ typedef struct st_line_buffer
3434
bool truncated;
3535
} LINE_BUFFER;
3636

37-
extern LINE_BUFFER *batch_readline_init(ulong max_size,FILE *file);
3837
extern LINE_BUFFER *batch_readline_command(LINE_BUFFER *buffer, char * str);
3938
extern char *batch_readline(LINE_BUFFER *buffer, bool binary_mode);
4039
extern void batch_readline_end(LINE_BUFFER *buffer);
40+
extern bool init_line_buffer(LINE_BUFFER *buffer, File file, ulong size, ulong max_size);
4141

4242
#endif /* CLIENT_MY_READLINE_INCLUDED */

client/mysql.cc

Lines changed: 73 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1207,6 +1207,75 @@ inline int get_command_index(char cmd_char)
12071207
return -1;
12081208
}
12091209

1210+
static LINE_BUFFER *batch_readline_init(ulong max_size, const char *path)
1211+
{
1212+
LINE_BUFFER *line_buff;
1213+
File file;
1214+
MY_STAT input_file_stat;
1215+
char buff[FN_REFLEN + 512];
1216+
1217+
if (path)
1218+
{
1219+
if ((file= my_open(path, O_RDONLY | O_BINARY, MYF(0))) < 0)
1220+
{
1221+
my_snprintf(buff, sizeof(buff), "Failed to open file '%.*s', error: %d",
1222+
FN_REFLEN, path, my_errno);
1223+
goto err1;
1224+
return 0;
1225+
}
1226+
}
1227+
else
1228+
{
1229+
file= my_fileno(stdin);
1230+
}
1231+
1232+
if (my_fstat(file, &input_file_stat, MYF(0)))
1233+
{
1234+
my_snprintf(buff, sizeof(buff), "Failed to stat file '%.*s', error: %d",
1235+
FN_REFLEN, path ? path : "stdin", my_errno);
1236+
goto err1;
1237+
goto err;
1238+
}
1239+
1240+
if (MY_S_ISDIR(input_file_stat.st_mode))
1241+
{
1242+
my_snprintf(buff, sizeof(buff), "Can't read from a directory '%.*s'",
1243+
FN_REFLEN, path ? path : "stdin");
1244+
goto err1;
1245+
goto err;
1246+
}
1247+
1248+
if (MY_S_ISBLK(input_file_stat.st_mode))
1249+
{
1250+
my_snprintf(buff, sizeof(buff), "Can't read from a block device '%.*s'",
1251+
FN_REFLEN, path ? path : "stdin");
1252+
goto err1;
1253+
goto err;
1254+
}
1255+
1256+
if (!(line_buff= (LINE_BUFFER*) my_malloc(PSI_NOT_INSTRUMENTED,
1257+
sizeof(*line_buff),
1258+
MYF(MY_WME | MY_ZEROFILL))))
1259+
{
1260+
goto err;
1261+
}
1262+
1263+
if (init_line_buffer(line_buff, file, IO_SIZE, max_size))
1264+
{
1265+
my_free(line_buff);
1266+
goto err;
1267+
}
1268+
1269+
return line_buff;
1270+
1271+
err1:
1272+
put_info(buff, INFO_ERROR, 0);
1273+
err:
1274+
if (path)
1275+
my_close(file, MYF(0));
1276+
return 0;
1277+
}
1278+
12101279
static int delimiter_index= -1;
12111280
static int charset_index= -1;
12121281
static int sandbox_index= -1;
@@ -1281,10 +1350,8 @@ int main(int argc,char *argv[])
12811350
}
12821351

12831352
if (status.batch && !status.line_buff &&
1284-
!(status.line_buff= batch_readline_init(MAX_BATCH_BUFFER_SIZE, stdin)))
1353+
!(status.line_buff= batch_readline_init(MAX_BATCH_BUFFER_SIZE, NULL)))
12851354
{
1286-
put_info("Can't initialize batch_readline - may be the input source is "
1287-
"a directory or a block device.", INFO_ERROR, 0);
12881355
free_defaults(defaults_argv);
12891356
my_end(0);
12901357
exit(1);
@@ -4682,7 +4749,6 @@ static int com_source(String *, char *line)
46824749
LINE_BUFFER *line_buff;
46834750
int error;
46844751
STATUS old_status;
4685-
FILE *sql_file;
46864752
my_bool save_ignore_errors;
46874753

46884754
if (status.sandbox)
@@ -4702,18 +4768,10 @@ static int com_source(String *, char *line)
47024768
end--;
47034769
end[0]=0;
47044770
unpack_filename(source_name,source_name);
4705-
/* open file name */
4706-
if (!(sql_file = my_fopen(source_name, O_RDONLY | O_BINARY,MYF(0))))
4707-
{
4708-
char buff[FN_REFLEN+60];
4709-
sprintf(buff,"Failed to open file '%s', error: %d", source_name,errno);
4710-
return put_info(buff, INFO_ERROR, 0);
4711-
}
47124771

4713-
if (!(line_buff= batch_readline_init(MAX_BATCH_BUFFER_SIZE, sql_file)))
4772+
if (!(line_buff= batch_readline_init(MAX_BATCH_BUFFER_SIZE, source_name)))
47144773
{
4715-
my_fclose(sql_file,MYF(0));
4716-
return put_info("Can't initialize batch_readline", INFO_ERROR, 0);
4774+
return 1;
47174775
}
47184776

47194777
/* Save old status */
@@ -4732,7 +4790,7 @@ static int com_source(String *, char *line)
47324790
ignore_errors= save_ignore_errors;
47334791
status=old_status; // Continue as before
47344792
in_com_source= aborted= 0;
4735-
my_fclose(sql_file,MYF(0));
4793+
my_close(line_buff->file, MYF(0));
47364794
batch_readline_end(line_buff);
47374795
/*
47384796
If we got an error during source operation, don't abort the client

client/readline.cc

Lines changed: 1 addition & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -23,38 +23,11 @@
2323
#include <my_dir.h>
2424
#include "my_readline.h"
2525

26-
static bool init_line_buffer(LINE_BUFFER *buffer,File file,ulong size,
27-
ulong max_size);
2826
static bool init_line_buffer_from_string(LINE_BUFFER *buffer,char * str);
2927
static size_t fill_buffer(LINE_BUFFER *buffer);
3028
static char *intern_read_line(LINE_BUFFER *buffer, ulong *out_length);
3129

3230

33-
LINE_BUFFER *batch_readline_init(ulong max_size,FILE *file)
34-
{
35-
LINE_BUFFER *line_buff;
36-
37-
#ifndef _WIN32
38-
MY_STAT input_file_stat;
39-
if (my_fstat(fileno(file), &input_file_stat, MYF(MY_WME)) ||
40-
MY_S_ISDIR(input_file_stat.st_mode) ||
41-
MY_S_ISBLK(input_file_stat.st_mode))
42-
return 0;
43-
#endif
44-
45-
if (!(line_buff=(LINE_BUFFER*)
46-
my_malloc(PSI_NOT_INSTRUMENTED, sizeof(*line_buff),
47-
MYF(MY_WME | MY_ZEROFILL))))
48-
return 0;
49-
if (init_line_buffer(line_buff,my_fileno(file),IO_SIZE,max_size))
50-
{
51-
my_free(line_buff);
52-
return 0;
53-
}
54-
return line_buff;
55-
}
56-
57-
5831
char *batch_readline(LINE_BUFFER *line_buff, bool binary_mode)
5932
{
6033
char *pos;
@@ -105,8 +78,7 @@ LINE_BUFFER *batch_readline_command(LINE_BUFFER *line_buff, char * str)
10578
Functions to handle buffered readings of lines from a stream
10679
******************************************************************************/
10780

108-
static bool
109-
init_line_buffer(LINE_BUFFER *buffer,File file,ulong size,ulong max_buffer)
81+
bool init_line_buffer(LINE_BUFFER *buffer,File file,ulong size,ulong max_buffer)
11082
{
11183
buffer->file=file;
11284
buffer->bufread=size;

mysql-test/main/mysql_client_test.result

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,3 +262,9 @@ SET @@global.collation_server= @save_collation_server;
262262
SET @@global.character_set_client= @save_character_set_client;
263263
SET @@global.collation_connection= @save_collation_connection;
264264
FOUND 1 /Aborted connection.*'u' host: '192.0.2.1' real ip: '(localhost|::1)'/ in mysqld.1.err
265+
#
266+
# MDEV-36269: Improve error handling for SOURCE command
267+
# Test that SOURCE on an existent directory returns a clear error
268+
#
269+
ERROR at line 1: Can't read from a directory '.'
270+
End of 10.11 tests

mysql-test/main/mysql_client_test.test

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,14 @@ SET @@global.collation_connection= @save_collation_connection;
6363
let SEARCH_FILE=$MYSQLTEST_VARDIR/log/mysqld.1.err;
6464
let SEARCH_PATTERN= Aborted connection.*'u' host: '192.0.2.1' real ip: '(localhost|::1)';
6565
source include/search_pattern_in_file.inc;
66+
67+
--echo #
68+
--echo # MDEV-36269: Improve error handling for SOURCE command
69+
--echo # Test that SOURCE on an existent directory returns a clear error
70+
--echo #
71+
72+
# --replace_regex /(ERROR at line 1: Failed to).*/\1 REPLACED/
73+
--error 1
74+
--exec $MYSQL -e "source ." 2>&1
75+
76+
--echo End of 10.11 tests

0 commit comments

Comments
 (0)