Commit fef32fd9 authored by Monty's avatar Monty

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 <serg@mariadb.com>
parent 4b4c371f
...@@ -158,7 +158,8 @@ static my_bool ignore_errors=0,wait_flag=0,quick=0, ...@@ -158,7 +158,8 @@ static my_bool ignore_errors=0,wait_flag=0,quick=0,
default_pager_set= 0, opt_sigint_ignore= 0, default_pager_set= 0, opt_sigint_ignore= 0,
auto_vertical_output= 0, auto_vertical_output= 0,
show_warnings= 0, executing_query= 0, show_warnings= 0, executing_query= 0,
ignore_spaces= 0, opt_binhex= 0, opt_progress_reports; ignore_spaces= 0, opt_binhex= 0, opt_progress_reports,
opt_print_query_on_error;
static my_bool debug_info_flag, debug_check_flag, batch_abort_on_error; static my_bool debug_info_flag, debug_check_flag, batch_abort_on_error;
static my_bool column_types_flag; static my_bool column_types_flag;
static my_bool preserve_comments= 0; static my_bool preserve_comments= 0;
...@@ -237,6 +238,7 @@ static int com_quit(String *str,char*), ...@@ -237,6 +238,7 @@ static int com_quit(String *str,char*),
com_prompt(String *str, char*), com_delimiter(String *str, char*), com_prompt(String *str, char*), com_delimiter(String *str, char*),
com_warnings(String *str, char*), com_nowarnings(String *str, char*), com_warnings(String *str, char*), com_nowarnings(String *str, char*),
com_sandbox(String *str, char*); com_sandbox(String *str, char*);
static void print_query_to_stderr(String *buffer);
#ifdef USE_POPEN #ifdef USE_POPEN
static int com_nopager(String *str, char*), com_pager(String *str, char*), static int com_nopager(String *str, char*), com_pager(String *str, char*),
...@@ -1659,6 +1661,10 @@ static struct my_option my_long_options[] = ...@@ -1659,6 +1661,10 @@ static struct my_option my_long_options[] =
#endif #endif
"built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").", &opt_mysql_port, "built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").", &opt_mysql_port,
&opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"print-query-on-error", 0,
"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)",
&opt_print_query_on_error, &opt_print_query_on_error, 0, GET_BOOL, NO_ARG,
1, 0, 0, 0, 0, 0},
{"progress-reports", 0, {"progress-reports", 0,
"Get progress reports for long running commands (like ALTER TABLE)", "Get progress reports for long running commands (like ALTER TABLE)",
&opt_progress_reports, &opt_progress_reports, 0, GET_BOOL, NO_ARG, 1, 0, &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) ...@@ -3086,6 +3092,11 @@ int mysql_real_query_for_lazy(const char *buf, size_t length)
int error; int error;
if (!mysql_real_query(&mysql,buf,(ulong)length)) if (!mysql_real_query(&mysql,buf,(ulong)length))
return 0; return 0;
if (opt_print_query_on_error)
{
String query(buf, length, charset_info);
(void) print_query_to_stderr(&query);
}
error= put_error(&mysql); error= put_error(&mysql);
if (mysql_errno(&mysql) != CR_SERVER_GONE_ERROR || retry > 1 || if (mysql_errno(&mysql) != CR_SERVER_GONE_ERROR || retry > 1 ||
!opt_reconnect) !opt_reconnect)
...@@ -3291,7 +3302,6 @@ static int com_charset(String *, char *line) ...@@ -3291,7 +3302,6 @@ static int com_charset(String *, char *line)
1 if fatal error 1 if fatal error
*/ */
static int com_go(String *buffer, char *) static int com_go(String *buffer, char *)
{ {
char buff[200]; /* about 110 chars used so far */ char buff[200]; /* about 110 chars used so far */
...@@ -3363,6 +3373,8 @@ static int com_go(String *buffer, char *) ...@@ -3363,6 +3373,8 @@ static int com_go(String *buffer, char *)
{ {
if (!(result=mysql_use_result(&mysql)) && mysql_field_count(&mysql)) if (!(result=mysql_use_result(&mysql)) && mysql_field_count(&mysql))
{ {
if (opt_print_query_on_error)
print_query_to_stderr(buffer);
error= put_error(&mysql); error= put_error(&mysql);
goto end; goto end;
} }
...@@ -3416,7 +3428,11 @@ static int com_go(String *buffer, char *) ...@@ -3416,7 +3428,11 @@ static int com_go(String *buffer, char *)
(long) mysql_num_rows(result) == 1 ? "row" : "rows"); (long) mysql_num_rows(result) == 1 ? "row" : "rows");
end_pager(); end_pager();
if (mysql_errno(&mysql)) if (mysql_errno(&mysql))
{
if (opt_print_query_on_error)
print_query_to_stderr(buffer);
error= put_error(&mysql); error= put_error(&mysql);
}
} }
} }
else if (mysql_affected_rows(&mysql) == ~(ulonglong) 0) else if (mysql_affected_rows(&mysql) == ~(ulonglong) 0)
...@@ -3443,13 +3459,21 @@ static int com_go(String *buffer, char *) ...@@ -3443,13 +3459,21 @@ static int com_go(String *buffer, char *)
put_info("",INFO_RESULT); // Empty row put_info("",INFO_RESULT); // Empty row
if (result && !mysql_eof(result)) /* Something wrong when using quick */ if (result && !mysql_eof(result)) /* Something wrong when using quick */
{
if (opt_print_query_on_error)
print_query_to_stderr(buffer);
error= put_error(&mysql); error= put_error(&mysql);
}
else if (unbuffered) else if (unbuffered)
fflush(stdout); fflush(stdout);
mysql_free_result(result); mysql_free_result(result);
} while (!(err= mysql_next_result(&mysql))); } while (!(err= mysql_next_result(&mysql)));
if (err >= 1) if (err >= 1)
{
if (opt_print_query_on_error)
print_query_to_stderr(buffer);
error= put_error(&mysql); error= put_error(&mysql);
}
end: end:
...@@ -4375,14 +4399,35 @@ static int com_shell(String *, char *line) ...@@ -4375,14 +4399,35 @@ static int com_shell(String *, char *line)
#endif #endif
static int com_print(String *buffer,char *) static void print_query(String *buffer, FILE *file)
{ {
tee_puts("--------------", stdout); tee_puts("--------------", file);
(void) tee_fputs(buffer->c_ptr(), stdout); (void) tee_fputs(buffer->c_ptr(), file);
if (!buffer->length() || (*buffer)[buffer->length()-1] != '\n') if (!buffer->length() || (*buffer)[buffer->length()-1] != '\n')
tee_putc('\n', stdout); tee_putc('\n', file);
tee_puts("--------------\n", stdout); tee_puts("--------------\n", file);
return 0; /* If empty buffer */ }
/*
Print query to stderr in batch mode if verbose is not set
*/
static void print_query_to_stderr(String *buffer)
{
if ((status.batch || in_com_source) && !verbose)
{
fflush(stdout);
print_query(buffer, stderr);
fflush(stderr);
}
}
static int com_print(String *buffer,char *)
{
print_query(buffer, stdout);
return 0;
} }
...@@ -5117,8 +5162,9 @@ put_info(const char *str,INFO_TYPE info_type, uint error, const char *sqlstate) ...@@ -5117,8 +5162,9 @@ put_info(const char *str,INFO_TYPE info_type, uint error, const char *sqlstate)
static int put_error(MYSQL *con) static int put_error(MYSQL *con)
{ {
return put_info(mysql_error(con), INFO_ERROR, mysql_errno(con), DBUG_ENTER("put_error");
mysql_sqlstate(con)); DBUG_RETURN(put_info(mysql_error(con), INFO_ERROR,
mysql_errno(con), mysql_sqlstate(con)));
} }
......
...@@ -628,7 +628,7 @@ static int run_query(const char *query, DYNAMIC_STRING *ds_res, ...@@ -628,7 +628,7 @@ static int run_query(const char *query, DYNAMIC_STRING *ds_res,
{ {
my_close(fd, MYF(MY_WME)); my_close(fd, MYF(MY_WME));
my_delete(query_file_path, MYF(0)); my_delete(query_file_path, MYF(0));
die("Failed to write to '%s'", query_file_path); die("Failed to write query to '%s'", query_file_path);
} }
} }
...@@ -637,7 +637,7 @@ static int run_query(const char *query, DYNAMIC_STRING *ds_res, ...@@ -637,7 +637,7 @@ static int run_query(const char *query, DYNAMIC_STRING *ds_res,
{ {
my_close(fd, MYF(MY_WME)); my_close(fd, MYF(MY_WME));
my_delete(query_file_path, MYF(0)); my_delete(query_file_path, MYF(0));
die("Failed to write to '%s'", query_file_path); die("Failed to write query to '%s'", query_file_path);
} }
ret= run_tool(mysql_path, ret= run_tool(mysql_path,
...@@ -647,6 +647,7 @@ static int run_query(const char *query, DYNAMIC_STRING *ds_res, ...@@ -647,6 +647,7 @@ static int run_query(const char *query, DYNAMIC_STRING *ds_res,
"--batch", /* Turns off pager etc. */ "--batch", /* Turns off pager etc. */
force ? "--force": "--skip-force", force ? "--force": "--skip-force",
opt_verbose >= 5 ? "--verbose" : "", opt_verbose >= 5 ? "--verbose" : "",
"--print-query-on-error",
ds_res || opt_silent ? "--silent": "", ds_res || opt_silent ? "--silent": "",
"<", "<",
query_file_path, query_file_path,
...@@ -1085,18 +1086,6 @@ static char* get_line(char* line) ...@@ -1085,18 +1086,6 @@ static char* get_line(char* line)
return line; return line;
} }
/* Print the current line to stderr */
static void print_line(char* line)
{
while (*line && *line != '\n')
{
fputc(*line, stderr);
line++;
}
fputc('\n', stderr);
}
static my_bool from_before_10_1() static my_bool from_before_10_1()
{ {
my_bool ret= TRUE; my_bool ret= TRUE;
...@@ -1308,16 +1297,21 @@ static int check_slave_repositories(void) ...@@ -1308,16 +1297,21 @@ static int check_slave_repositories(void)
static int run_sql_fix_privilege_tables(void) static int run_sql_fix_privilege_tables(void)
{ {
int found_real_errors= 0; int found_real_errors= 0, query_started= 0;
const char **query_ptr; const char **query_ptr;
const char *end;
DYNAMIC_STRING ds_script; DYNAMIC_STRING ds_script;
DYNAMIC_STRING ds_result; DYNAMIC_STRING ds_result;
DYNAMIC_STRING ds_query;
DBUG_ENTER("run_sql_fix_privilege_tables"); DBUG_ENTER("run_sql_fix_privilege_tables");
if (init_dynamic_string(&ds_script, "", 65536, 1024)) if (init_dynamic_string(&ds_script, "", 96*1024, 8196))
die("Out of memory"); die("Out of memory");
if (init_dynamic_string(&ds_result, "", 512, 512)) if (init_dynamic_string(&ds_result, "", 1024, 1024))
die("Out of memory");
if (init_dynamic_string(&ds_query, "", 1024, 1024))
die("Out of memory"); die("Out of memory");
verbose("Phase %d/%d: Running 'mysql_fix_privilege_tables'", verbose("Phase %d/%d: Running 'mysql_fix_privilege_tables'",
...@@ -1346,22 +1340,46 @@ static int run_sql_fix_privilege_tables(void) ...@@ -1346,22 +1340,46 @@ static int run_sql_fix_privilege_tables(void)
"Unknown column" and "Duplicate key name" since they just "Unknown column" and "Duplicate key name" since they just
indicate the system tables are already up to date indicate the system tables are already up to date
*/ */
char *line= ds_result.str; const char *line= ds_result.str;
do do
{ {
size_t length;
end= strchr(line, '\n');
if (!end)
end= strend(line);
else
end++; /* Include end \n */
length= (size_t) (end - line);
if (!is_expected_error(line)) if (!is_expected_error(line))
{ {
/* Something unexpected failed, dump error line to screen */ /* Something unexpected failed, dump error line to screen */
found_real_errors++; found_real_errors++;
print_line(line); if (ds_query.length)
fwrite(ds_query.str, sizeof(char), ds_query.length, stderr);
fwrite(line, sizeof(char), length, stderr);
query_started= 0;
} }
else if (strncmp(line, "WARNING", 7) == 0) else if (strncmp(line, "WARNING", 7) == 0)
{ {
print_line(line); fwrite(line, sizeof(char), length, stderr);
query_started= 0;
} }
} while ((line= get_line(line)) && *line); else if (!strncmp(line, "--------------\n", 16))
{
/* mariadb separates query from the error with a line of '-' */
if (!query_started++)
ds_query.length= 0; /* Truncate */
else
query_started= 0; /* End of query */
}
else if (query_started)
{
dynstr_append_mem(&ds_query, line, length);
}
} while (*(line= end));
} }
dynstr_free(&ds_query);
dynstr_free(&ds_result); dynstr_free(&ds_result);
dynstr_free(&ds_script); dynstr_free(&ds_script);
DBUG_RETURN(found_real_errors); DBUG_RETURN(found_real_errors);
......
...@@ -6413,9 +6413,13 @@ j integer ...@@ -6413,9 +6413,13 @@ j integer
INSERT INTO t VALUES (1,1),(2,2),(3,3),(4,4); INSERT INTO t VALUES (1,1),(2,2),(3,3),(4,4);
# Dump database 1 # Dump database 1
# Restore from database 1 to database 2 # Restore from database 1 to database 2
ERROR 1100 (HY000) at line 46: Table 'seq_t_i' was not locked with LOCK TABLES
SETVAL(`seq_t_i`, 1, 0) SETVAL(`seq_t_i`, 1, 0)
1 1
--------------
INSERT INTO `t` VALUES (1,1),(2,2),(3,3),(4,4)
--------------
ERROR 1100 (HY000) at line 46: Table 'seq_t_i' was not locked with LOCK TABLES
DROP DATABASE IF EXISTS test1; DROP DATABASE IF EXISTS test1;
DROP DATABASE IF EXISTS test2; DROP DATABASE IF EXISTS test2;
# #
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment