Skip to content

Commit 7cd2cea

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 c331d53 commit 7cd2cea

File tree

5 files changed

+98
-45
lines changed

5 files changed

+98
-45
lines changed

client/my_readline.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,10 @@ 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,
41+
ulong max_size);
4142

4243
#endif /* CLIENT_MY_READLINE_INCLUDED */

client/mysql.cc

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

12831358
if (status.batch && !status.line_buff &&
1284-
!(status.line_buff= batch_readline_init(MAX_BATCH_BUFFER_SIZE, stdin)))
1359+
!(status.line_buff= batch_readline_init(MAX_BATCH_BUFFER_SIZE, NULL)))
12851360
{
1286-
put_info("Can't initialize batch_readline - may be the input source is "
1287-
"a directory or a block device.", INFO_ERROR, 0);
12881361
free_defaults(defaults_argv);
12891362
my_end(0);
12901363
exit(1);
@@ -4682,7 +4755,6 @@ static int com_source(String *, char *line)
46824755
LINE_BUFFER *line_buff;
46834756
int error;
46844757
STATUS old_status;
4685-
FILE *sql_file;
46864758
my_bool save_ignore_errors;
46874759

46884760
if (status.sandbox)
@@ -4702,18 +4774,10 @@ static int com_source(String *, char *line)
47024774
end--;
47034775
end[0]=0;
47044776
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-
}
47124777

4713-
if (!(line_buff= batch_readline_init(MAX_BATCH_BUFFER_SIZE, sql_file)))
4778+
if (!(line_buff= batch_readline_init(MAX_BATCH_BUFFER_SIZE, source_name)))
47144779
{
4715-
my_fclose(sql_file,MYF(0));
4716-
return put_info("Can't initialize batch_readline", INFO_ERROR, 0);
4780+
return ignore_errors ? -1 : 1;
47174781
}
47184782

47194783
/* Save old status */
@@ -4732,7 +4796,7 @@ static int com_source(String *, char *line)
47324796
ignore_errors= save_ignore_errors;
47334797
status=old_status; // Continue as before
47344798
in_com_source= aborted= 0;
4735-
my_fclose(sql_file,MYF(0));
4799+
my_close(line_buff->file, MYF(0));
47364800
batch_readline_end(line_buff);
47374801
/*
47384802
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)