Skip to content

Commit fef32fd

Browse files
committed
MDEV-34406 Enhance mariadb_upgrade to print failing query in case of error
To make this possible, it was also necessary to enhance the mariadb client with the option --print-query-on-error. This option can also be very useful when running a batch of queries through the mariadb client and one wants to find out where things goes wrong. TODO: It would be good to enhance mariadb_upgrade to not call the mariadb client for executing queries but instead do this internally. This would have made this patch much easier! Reviewed by: Sergei Golubchik <[email protected]>
1 parent 4b4c371 commit fef32fd

File tree

3 files changed

+101
-33
lines changed

3 files changed

+101
-33
lines changed

client/mysql.cc

Lines changed: 56 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,8 @@ static my_bool ignore_errors=0,wait_flag=0,quick=0,
158158
default_pager_set= 0, opt_sigint_ignore= 0,
159159
auto_vertical_output= 0,
160160
show_warnings= 0, executing_query= 0,
161-
ignore_spaces= 0, opt_binhex= 0, opt_progress_reports;
161+
ignore_spaces= 0, opt_binhex= 0, opt_progress_reports,
162+
opt_print_query_on_error;
162163
static my_bool debug_info_flag, debug_check_flag, batch_abort_on_error;
163164
static my_bool column_types_flag;
164165
static my_bool preserve_comments= 0;
@@ -237,6 +238,7 @@ static int com_quit(String *str,char*),
237238
com_prompt(String *str, char*), com_delimiter(String *str, char*),
238239
com_warnings(String *str, char*), com_nowarnings(String *str, char*),
239240
com_sandbox(String *str, char*);
241+
static void print_query_to_stderr(String *buffer);
240242

241243
#ifdef USE_POPEN
242244
static int com_nopager(String *str, char*), com_pager(String *str, char*),
@@ -1659,6 +1661,10 @@ static struct my_option my_long_options[] =
16591661
#endif
16601662
"built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").", &opt_mysql_port,
16611663
&opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1664+
{"print-query-on-error", 0,
1665+
"Print the query if there was an error. Is only enabled in --batch mode if verbose is not set (as then the query would be printed anyway)",
1666+
&opt_print_query_on_error, &opt_print_query_on_error, 0, GET_BOOL, NO_ARG,
1667+
1, 0, 0, 0, 0, 0},
16621668
{"progress-reports", 0,
16631669
"Get progress reports for long running commands (like ALTER TABLE)",
16641670
&opt_progress_reports, &opt_progress_reports, 0, GET_BOOL, NO_ARG, 1, 0,
@@ -3086,6 +3092,11 @@ int mysql_real_query_for_lazy(const char *buf, size_t length)
30863092
int error;
30873093
if (!mysql_real_query(&mysql,buf,(ulong)length))
30883094
return 0;
3095+
if (opt_print_query_on_error)
3096+
{
3097+
String query(buf, length, charset_info);
3098+
(void) print_query_to_stderr(&query);
3099+
}
30893100
error= put_error(&mysql);
30903101
if (mysql_errno(&mysql) != CR_SERVER_GONE_ERROR || retry > 1 ||
30913102
!opt_reconnect)
@@ -3291,7 +3302,6 @@ static int com_charset(String *, char *line)
32913302
1 if fatal error
32923303
*/
32933304

3294-
32953305
static int com_go(String *buffer, char *)
32963306
{
32973307
char buff[200]; /* about 110 chars used so far */
@@ -3363,6 +3373,8 @@ static int com_go(String *buffer, char *)
33633373
{
33643374
if (!(result=mysql_use_result(&mysql)) && mysql_field_count(&mysql))
33653375
{
3376+
if (opt_print_query_on_error)
3377+
print_query_to_stderr(buffer);
33663378
error= put_error(&mysql);
33673379
goto end;
33683380
}
@@ -3416,7 +3428,11 @@ static int com_go(String *buffer, char *)
34163428
(long) mysql_num_rows(result) == 1 ? "row" : "rows");
34173429
end_pager();
34183430
if (mysql_errno(&mysql))
3431+
{
3432+
if (opt_print_query_on_error)
3433+
print_query_to_stderr(buffer);
34193434
error= put_error(&mysql);
3435+
}
34203436
}
34213437
}
34223438
else if (mysql_affected_rows(&mysql) == ~(ulonglong) 0)
@@ -3443,13 +3459,21 @@ static int com_go(String *buffer, char *)
34433459
put_info("",INFO_RESULT); // Empty row
34443460

34453461
if (result && !mysql_eof(result)) /* Something wrong when using quick */
3462+
{
3463+
if (opt_print_query_on_error)
3464+
print_query_to_stderr(buffer);
34463465
error= put_error(&mysql);
3466+
}
34473467
else if (unbuffered)
34483468
fflush(stdout);
34493469
mysql_free_result(result);
34503470
} while (!(err= mysql_next_result(&mysql)));
34513471
if (err >= 1)
3472+
{
3473+
if (opt_print_query_on_error)
3474+
print_query_to_stderr(buffer);
34523475
error= put_error(&mysql);
3476+
}
34533477

34543478
end:
34553479

@@ -4375,14 +4399,35 @@ static int com_shell(String *, char *line)
43754399
#endif
43764400

43774401

4378-
static int com_print(String *buffer,char *)
4402+
static void print_query(String *buffer, FILE *file)
43794403
{
4380-
tee_puts("--------------", stdout);
4381-
(void) tee_fputs(buffer->c_ptr(), stdout);
4404+
tee_puts("--------------", file);
4405+
(void) tee_fputs(buffer->c_ptr(), file);
43824406
if (!buffer->length() || (*buffer)[buffer->length()-1] != '\n')
4383-
tee_putc('\n', stdout);
4384-
tee_puts("--------------\n", stdout);
4385-
return 0; /* If empty buffer */
4407+
tee_putc('\n', file);
4408+
tee_puts("--------------\n", file);
4409+
}
4410+
4411+
4412+
/*
4413+
Print query to stderr in batch mode if verbose is not set
4414+
*/
4415+
4416+
static void print_query_to_stderr(String *buffer)
4417+
{
4418+
if ((status.batch || in_com_source) && !verbose)
4419+
{
4420+
fflush(stdout);
4421+
print_query(buffer, stderr);
4422+
fflush(stderr);
4423+
}
4424+
}
4425+
4426+
4427+
static int com_print(String *buffer,char *)
4428+
{
4429+
print_query(buffer, stdout);
4430+
return 0;
43864431
}
43874432

43884433

@@ -5117,8 +5162,9 @@ put_info(const char *str,INFO_TYPE info_type, uint error, const char *sqlstate)
51175162

51185163
static int put_error(MYSQL *con)
51195164
{
5120-
return put_info(mysql_error(con), INFO_ERROR, mysql_errno(con),
5121-
mysql_sqlstate(con));
5165+
DBUG_ENTER("put_error");
5166+
DBUG_RETURN(put_info(mysql_error(con), INFO_ERROR,
5167+
mysql_errno(con), mysql_sqlstate(con)));
51225168
}
51235169

51245170

client/mysql_upgrade.c

Lines changed: 40 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -628,7 +628,7 @@ static int run_query(const char *query, DYNAMIC_STRING *ds_res,
628628
{
629629
my_close(fd, MYF(MY_WME));
630630
my_delete(query_file_path, MYF(0));
631-
die("Failed to write to '%s'", query_file_path);
631+
die("Failed to write query to '%s'", query_file_path);
632632
}
633633
}
634634

@@ -637,7 +637,7 @@ static int run_query(const char *query, DYNAMIC_STRING *ds_res,
637637
{
638638
my_close(fd, MYF(MY_WME));
639639
my_delete(query_file_path, MYF(0));
640-
die("Failed to write to '%s'", query_file_path);
640+
die("Failed to write query to '%s'", query_file_path);
641641
}
642642

643643
ret= run_tool(mysql_path,
@@ -647,6 +647,7 @@ static int run_query(const char *query, DYNAMIC_STRING *ds_res,
647647
"--batch", /* Turns off pager etc. */
648648
force ? "--force": "--skip-force",
649649
opt_verbose >= 5 ? "--verbose" : "",
650+
"--print-query-on-error",
650651
ds_res || opt_silent ? "--silent": "",
651652
"<",
652653
query_file_path,
@@ -1085,18 +1086,6 @@ static char* get_line(char* line)
10851086
return line;
10861087
}
10871088

1088-
1089-
/* Print the current line to stderr */
1090-
static void print_line(char* line)
1091-
{
1092-
while (*line && *line != '\n')
1093-
{
1094-
fputc(*line, stderr);
1095-
line++;
1096-
}
1097-
fputc('\n', stderr);
1098-
}
1099-
11001089
static my_bool from_before_10_1()
11011090
{
11021091
my_bool ret= TRUE;
@@ -1308,16 +1297,21 @@ static int check_slave_repositories(void)
13081297

13091298
static int run_sql_fix_privilege_tables(void)
13101299
{
1311-
int found_real_errors= 0;
1300+
int found_real_errors= 0, query_started= 0;
13121301
const char **query_ptr;
1302+
const char *end;
13131303
DYNAMIC_STRING ds_script;
13141304
DYNAMIC_STRING ds_result;
1305+
DYNAMIC_STRING ds_query;
13151306
DBUG_ENTER("run_sql_fix_privilege_tables");
13161307

1317-
if (init_dynamic_string(&ds_script, "", 65536, 1024))
1308+
if (init_dynamic_string(&ds_script, "", 96*1024, 8196))
13181309
die("Out of memory");
13191310

1320-
if (init_dynamic_string(&ds_result, "", 512, 512))
1311+
if (init_dynamic_string(&ds_result, "", 1024, 1024))
1312+
die("Out of memory");
1313+
1314+
if (init_dynamic_string(&ds_query, "", 1024, 1024))
13211315
die("Out of memory");
13221316

13231317
verbose("Phase %d/%d: Running 'mysql_fix_privilege_tables'",
@@ -1346,22 +1340,46 @@ static int run_sql_fix_privilege_tables(void)
13461340
"Unknown column" and "Duplicate key name" since they just
13471341
indicate the system tables are already up to date
13481342
*/
1349-
char *line= ds_result.str;
1343+
const char *line= ds_result.str;
13501344
do
13511345
{
1346+
size_t length;
1347+
end= strchr(line, '\n');
1348+
if (!end)
1349+
end= strend(line);
1350+
else
1351+
end++; /* Include end \n */
1352+
length= (size_t) (end - line);
1353+
13521354
if (!is_expected_error(line))
13531355
{
13541356
/* Something unexpected failed, dump error line to screen */
13551357
found_real_errors++;
1356-
print_line(line);
1358+
if (ds_query.length)
1359+
fwrite(ds_query.str, sizeof(char), ds_query.length, stderr);
1360+
fwrite(line, sizeof(char), length, stderr);
1361+
query_started= 0;
13571362
}
13581363
else if (strncmp(line, "WARNING", 7) == 0)
13591364
{
1360-
print_line(line);
1365+
fwrite(line, sizeof(char), length, stderr);
1366+
query_started= 0;
13611367
}
1362-
} while ((line= get_line(line)) && *line);
1368+
else if (!strncmp(line, "--------------\n", 16))
1369+
{
1370+
/* mariadb separates query from the error with a line of '-' */
1371+
if (!query_started++)
1372+
ds_query.length= 0; /* Truncate */
1373+
else
1374+
query_started= 0; /* End of query */
1375+
}
1376+
else if (query_started)
1377+
{
1378+
dynstr_append_mem(&ds_query, line, length);
1379+
}
1380+
} while (*(line= end));
13631381
}
1364-
1382+
dynstr_free(&ds_query);
13651383
dynstr_free(&ds_result);
13661384
dynstr_free(&ds_script);
13671385
DBUG_RETURN(found_real_errors);

mysql-test/main/mysqldump.result

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6413,9 +6413,13 @@ j integer
64136413
INSERT INTO t VALUES (1,1),(2,2),(3,3),(4,4);
64146414
# Dump database 1
64156415
# Restore from database 1 to database 2
6416-
ERROR 1100 (HY000) at line 46: Table 'seq_t_i' was not locked with LOCK TABLES
64176416
SETVAL(`seq_t_i`, 1, 0)
64186417
1
6418+
--------------
6419+
INSERT INTO `t` VALUES (1,1),(2,2),(3,3),(4,4)
6420+
--------------
6421+
6422+
ERROR 1100 (HY000) at line 46: Table 'seq_t_i' was not locked with LOCK TABLES
64196423
DROP DATABASE IF EXISTS test1;
64206424
DROP DATABASE IF EXISTS test2;
64216425
#

0 commit comments

Comments
 (0)