Skip to content

Commit 82ed328

Browse files
committed
MDEV-36269: improve error handling for source command
- refactor 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 - handle windows check for block device - ensure file failing to open in windows because being a directory is different from any other reason for clear error message
1 parent 1893fb4 commit 82ed328

File tree

5 files changed

+98
-45
lines changed

5 files changed

+98
-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: 80 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1207,6 +1207,82 @@ 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+
#ifdef _WIN32
1222+
if (my_errno == EACCES && my_stat(path, &input_file_stat, MYF(0)) &&
1223+
MY_S_ISDIR(input_file_stat.st_mode))
1224+
goto errdir;
1225+
#endif
1226+
my_snprintf(buff, sizeof(buff), "Failed to open file '%.*s', error: %d",
1227+
FN_REFLEN, path, my_errno);
1228+
put_info(buff, INFO_ERROR, 0);
1229+
return 0;
1230+
}
1231+
}
1232+
else
1233+
{
1234+
file= my_fileno(stdin);
1235+
}
1236+
1237+
if (my_fstat(file, &input_file_stat, MYF(0)))
1238+
{
1239+
my_snprintf(buff, sizeof(buff), "Failed to stat file '%.*s', error: %d",
1240+
FN_REFLEN, path ? path : "stdin", my_errno);
1241+
goto err1;
1242+
}
1243+
1244+
if (MY_S_ISDIR(input_file_stat.st_mode))
1245+
{
1246+
#ifdef _WIN32
1247+
errdir:
1248+
#endif
1249+
my_snprintf(buff, sizeof(buff), "Can't read from a directory '%.*s'",
1250+
FN_REFLEN, path ? path : "stdin");
1251+
goto err1;
1252+
}
1253+
1254+
#ifndef _WIN32
1255+
if (MY_S_ISBLK(input_file_stat.st_mode))
1256+
{
1257+
my_snprintf(buff, sizeof(buff), "Can't read from a block device '%.*s'",
1258+
FN_REFLEN, path ? path : "stdin");
1259+
goto err1;
1260+
}
1261+
#endif
1262+
1263+
if (!(line_buff= (LINE_BUFFER*) my_malloc(PSI_NOT_INSTRUMENTED,
1264+
sizeof(*line_buff),
1265+
MYF(MY_WME | MY_ZEROFILL))))
1266+
{
1267+
goto err;
1268+
}
1269+
1270+
if (init_line_buffer(line_buff, file, IO_SIZE, max_size))
1271+
{
1272+
my_free(line_buff);
1273+
goto err;
1274+
}
1275+
1276+
return line_buff;
1277+
1278+
err1:
1279+
put_info(buff, INFO_ERROR, 0);
1280+
err:
1281+
if (path)
1282+
my_close(file, MYF(0));
1283+
return 0;
1284+
}
1285+
12101286
static int delimiter_index= -1;
12111287
static int charset_index= -1;
12121288
static int sandbox_index= -1;
@@ -1281,10 +1357,8 @@ int main(int argc,char *argv[])
12811357
}
12821358

12831359
if (status.batch && !status.line_buff &&
1284-
!(status.line_buff= batch_readline_init(MAX_BATCH_BUFFER_SIZE, stdin)))
1360+
!(status.line_buff= batch_readline_init(MAX_BATCH_BUFFER_SIZE, NULL)))
12851361
{
1286-
put_info("Can't initialize batch_readline - may be the input source is "
1287-
"a directory or a block device.", INFO_ERROR, 0);
12881362
free_defaults(defaults_argv);
12891363
my_end(0);
12901364
exit(1);
@@ -4682,7 +4756,6 @@ static int com_source(String *, char *line)
46824756
LINE_BUFFER *line_buff;
46834757
int error;
46844758
STATUS old_status;
4685-
FILE *sql_file;
46864759
my_bool save_ignore_errors;
46874760

46884761
if (status.sandbox)
@@ -4702,18 +4775,10 @@ static int com_source(String *, char *line)
47024775
end--;
47034776
end[0]=0;
47044777
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-
}
47124778

4713-
if (!(line_buff= batch_readline_init(MAX_BATCH_BUFFER_SIZE, sql_file)))
4779+
if (!(line_buff= batch_readline_init(MAX_BATCH_BUFFER_SIZE, source_name)))
47144780
{
4715-
my_fclose(sql_file,MYF(0));
4716-
return put_info("Can't initialize batch_readline", INFO_ERROR, 0);
4781+
return ignore_errors ? -1 : 1;
47174782
}
47184783

47194784
/* Save old status */
@@ -4732,7 +4797,7 @@ static int com_source(String *, char *line)
47324797
ignore_errors= save_ignore_errors;
47334798
status=old_status; // Continue as before
47344799
in_com_source= aborted= 0;
4735-
my_fclose(sql_file,MYF(0));
4800+
my_close(line_buff->file, MYF(0));
47364801
batch_readline_end(line_buff);
47374802
/*
47384803
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: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,13 @@ 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+
--error 1
73+
--exec $MYSQL -e "source ." 2>&1
74+
75+
--echo End of 10.11 tests

0 commit comments

Comments
 (0)