Commit fe7c2aae authored by Sergei Golubchik's avatar Sergei Golubchik

MDEV-3816 init-file stops getting executed if a long enough line is...

MDEV-3816 init-file stops getting executed if a long enough line is encountered; on a debug version, assertion `! is_set() || can_overwrite_status' fails
backport improved bootstrap error handling from 5.6

Was:
  revno: 3768.1.1
  committer: Christopher Powers <chris.powers@oracle.com>
  timestamp: Wed 2012-05-02 22:16:40 -0500
  message:
    Bug#11766342 INITIAL DB CREATION FAILS ON WINDOWS WITH AN ASSERT IN SQL_ERROR.CC
    Improved bootstrap error handling:
    - Detect and report file i/o errors
    - Report query size errors with nearest query text
parent 1679fe1c
select count(*) from t4;
count(*)
0
This diff is collapsed.
--init-file=$MYSQL_TEST_DIR/std_data/init_file_longline_3816.sql
#
# MDEV-3816 init-file stops getting executed if a long enough line is encountered; on a debug version, assertion `! is_set() || can_overwrite_status' fails
#
select count(*) from t4;
...@@ -65,9 +65,12 @@ static void die(const char *fmt, ...) ...@@ -65,9 +65,12 @@ static void die(const char *fmt, ...)
exit(1); exit(1);
} }
char *fgets_fn(char *buffer, size_t size, fgets_input_t input) char *fgets_fn(char *buffer, size_t size, fgets_input_t input, int *error)
{ {
return fgets(buffer, size, (FILE*) input); char *line= fgets(buffer, size, (FILE*) input);
if (error)
*error= (line == NULL) ? ferror((FILE*)input) : 0;
return line;
} }
static void print_query(FILE *out, const char *query) static void print_query(FILE *out, const char *query)
...@@ -116,6 +119,8 @@ int main(int argc, char *argv[]) ...@@ -116,6 +119,8 @@ int main(int argc, char *argv[])
char* outfile_name= argv[3]; char* outfile_name= argv[3];
int rc; int rc;
int query_length; int query_length;
int error= 0;
char *err_ptr;
if (argc != 4) if (argc != 4)
die("Usage: comp_sql <struct_name> <sql_filename> <c_filename>"); die("Usage: comp_sql <struct_name> <sql_filename> <c_filename>");
...@@ -136,14 +141,34 @@ int main(int argc, char *argv[]) ...@@ -136,14 +141,34 @@ int main(int argc, char *argv[])
for ( ; ; ) for ( ; ; )
{ {
rc= read_bootstrap_query(query, &query_length, rc= read_bootstrap_query(query, &query_length,
(fgets_input_t) in, fgets_fn); (fgets_input_t) in, fgets_fn, &error);
if (rc == READ_BOOTSTRAP_ERROR)
die("Failed to read the bootstrap input file.\n");
if (rc == READ_BOOTSTRAP_EOF) if (rc == READ_BOOTSTRAP_EOF)
break; break;
if (rc != READ_BOOTSTRAP_SUCCESS)
{
/* Get the most recent query text for reference. */
err_ptr= query + (query_length <= MAX_BOOTSTRAP_ERROR_LEN ?
0 : (query_length - MAX_BOOTSTRAP_ERROR_LEN));
switch (rc)
{
case READ_BOOTSTRAP_ERROR:
die("Failed to read the bootstrap input file. Return code (%d).\n"
"Last query: '%s'\n", error, err_ptr);
break;
case READ_BOOTSTRAP_QUERY_SIZE:
die("Failed to read the boostrap input file. Query size exceeded %d bytes.\n"
"Last query: '%s'.\n", MAX_BOOTSTRAP_LINE_SIZE, err_ptr);
break;
default:
die("Failed to read the boostrap input file. Unknown error.\n");
break;
}
}
print_query(out, query); print_query(out, query);
} }
......
...@@ -14,24 +14,34 @@ ...@@ -14,24 +14,34 @@
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
#include <stdlib.h>
#include <errno.h>
#include <ctype.h> #include <ctype.h>
#include <string.h> #include <string.h>
#include "sql_bootstrap.h" #include "sql_bootstrap.h"
int read_bootstrap_query(char *query, int *query_length, int read_bootstrap_query(char *query, int *query_length,
fgets_input_t input, fgets_fn_t fgets_fn) fgets_input_t input, fgets_fn_t fgets_fn, int *error)
{ {
char line_buffer[MAX_BOOTSTRAP_LINE_SIZE]; char line_buffer[MAX_BOOTSTRAP_LINE_SIZE];
const char *line; const char *line;
int len; int len;
int query_len= 0; int query_len= 0;
int fgets_error= 0;
*error= 0;
for ( ; ; ) for ( ; ; )
{ {
line= (*fgets_fn)(line_buffer, sizeof(line_buffer), input); line= (*fgets_fn)(line_buffer, sizeof(line_buffer), input, &fgets_error);
if (error)
*error= fgets_error;
if (fgets_error != 0)
return READ_BOOTSTRAP_ERROR;
if (line == NULL) if (line == NULL)
return (query_len ? READ_BOOTSTRAP_ERROR : READ_BOOTSTRAP_EOF); return (query_len == 0) ? READ_BOOTSTRAP_EOF : READ_BOOTSTRAP_ERROR;
len= strlen(line); len= strlen(line);
...@@ -67,10 +77,22 @@ int read_bootstrap_query(char *query, int *query_length, ...@@ -67,10 +77,22 @@ int read_bootstrap_query(char *query, int *query_length,
if (strncmp(line, "delimiter", 9) == 0) if (strncmp(line, "delimiter", 9) == 0)
continue; continue;
/* Append the current line to a multi line query. */ /* Append the current line to a multi line query. If the new line will make
the query too long, preserve the partial line to provide context for the
error message.
*/
if (query_len + len + 1 >= MAX_BOOTSTRAP_QUERY_SIZE) if (query_len + len + 1 >= MAX_BOOTSTRAP_QUERY_SIZE)
return READ_BOOTSTRAP_ERROR; {
int new_len= MAX_BOOTSTRAP_QUERY_SIZE - query_len - 1;
if ((new_len > 0) && (query_len < MAX_BOOTSTRAP_QUERY_SIZE))
{
memcpy(query + query_len, line, new_len);
query_len+= new_len;
}
query[query_len]= '\0';
*query_length= query_len;
return READ_BOOTSTRAP_QUERY_SIZE;
}
if (query_len != 0) if (query_len != 0)
{ {
...@@ -78,8 +100,7 @@ int read_bootstrap_query(char *query, int *query_length, ...@@ -78,8 +100,7 @@ int read_bootstrap_query(char *query, int *query_length,
Append a \n to the current line, if any, Append a \n to the current line, if any,
to preserve the intended presentation. to preserve the intended presentation.
*/ */
query[query_len]= '\n'; query[query_len++]= '\n';
query_len++;
} }
memcpy(query + query_len, line, len); memcpy(query + query_len, line, len);
query_len+= len; query_len+= len;
...@@ -92,7 +113,7 @@ int read_bootstrap_query(char *query, int *query_length, ...@@ -92,7 +113,7 @@ int read_bootstrap_query(char *query, int *query_length,
*/ */
query[query_len]= '\0'; query[query_len]= '\0';
*query_length= query_len; *query_length= query_len;
return 0; return READ_BOOTSTRAP_SUCCESS;
} }
} }
} }
......
...@@ -29,15 +29,18 @@ ...@@ -29,15 +29,18 @@
Do not increase this size, use the multiline syntax instead. Do not increase this size, use the multiline syntax instead.
*/ */
#define MAX_BOOTSTRAP_LINE_SIZE 20000 #define MAX_BOOTSTRAP_LINE_SIZE 20000
#define MAX_BOOTSTRAP_ERROR_LEN 256
#define READ_BOOTSTRAP_EOF 1 #define READ_BOOTSTRAP_SUCCESS 0
#define READ_BOOTSTRAP_ERROR 2 #define READ_BOOTSTRAP_EOF 1
#define READ_BOOTSTRAP_ERROR 2
#define READ_BOOTSTRAP_QUERY_SIZE 3
typedef void *fgets_input_t; typedef void *fgets_input_t;
typedef char * (*fgets_fn_t)(char *, size_t, fgets_input_t); typedef char * (*fgets_fn_t)(char *, size_t, fgets_input_t, int *error);
int read_bootstrap_query(char *query, int *query_length, int read_bootstrap_query(char *query, int *query_length,
fgets_input_t input, fgets_fn_t fgets_fn); fgets_input_t input, fgets_fn_t fgets_fn, int *error);
#endif #endif
......
...@@ -634,10 +634,13 @@ void execute_init_command(THD *thd, LEX_STRING *init_command, ...@@ -634,10 +634,13 @@ void execute_init_command(THD *thd, LEX_STRING *init_command,
} }
static char *fgets_fn(char *buffer, size_t size, fgets_input_t input) static char *fgets_fn(char *buffer, size_t size, fgets_input_t input, int *error)
{ {
MYSQL_FILE *in= static_cast<MYSQL_FILE*> (input); MYSQL_FILE *in= static_cast<MYSQL_FILE*> (input);
return mysql_file_fgets(buffer, size, in); char *line= mysql_file_fgets(buffer, size, in);
if (error)
*error= (line == NULL) ? ferror(in->m_file) : 0;
return line;
} }
...@@ -664,25 +667,53 @@ static void handle_bootstrap_impl(THD *thd) ...@@ -664,25 +667,53 @@ static void handle_bootstrap_impl(THD *thd)
for ( ; ; ) for ( ; ; )
{ {
char buffer[MAX_BOOTSTRAP_QUERY_SIZE]; char buffer[MAX_BOOTSTRAP_QUERY_SIZE] = "";
int rc, length; int rc, length;
char *query; char *query;
int error= 0;
rc= read_bootstrap_query(buffer, &length, file, fgets_fn); rc= read_bootstrap_query(buffer, &length, file, fgets_fn, &error);
if (rc == READ_BOOTSTRAP_ERROR) if (rc == READ_BOOTSTRAP_EOF)
break;
/*
Check for bootstrap file errors. SQL syntax errors will be
caught below.
*/
if (rc != READ_BOOTSTRAP_SUCCESS)
{ {
thd->raise_error(ER_SYNTAX_ERROR); /*
mysql_parse() may have set a successful error status for the previous
query. We must clear the error status to report the bootstrap error.
*/
thd->get_stmt_da()->reset_diagnostics_area();
/* Get the nearest query text for reference. */
char *err_ptr= buffer + (length <= MAX_BOOTSTRAP_ERROR_LEN ?
0 : (length - MAX_BOOTSTRAP_ERROR_LEN));
switch (rc)
{
case READ_BOOTSTRAP_ERROR:
my_printf_error(ER_UNKNOWN_ERROR, "Bootstrap file error, return code (%d). "
"Nearest query: '%s'", MYF(0), error, err_ptr);
break;
case READ_BOOTSTRAP_QUERY_SIZE:
my_printf_error(ER_UNKNOWN_ERROR, "Boostrap file error. Query size "
"exceeded %d bytes near '%s'.", MYF(0),
MAX_BOOTSTRAP_LINE_SIZE, err_ptr);
break;
default:
DBUG_ASSERT(false);
break;
}
thd->protocol->end_statement(); thd->protocol->end_statement();
bootstrap_error= 1; bootstrap_error= 1;
break; break;
} }
if (rc == READ_BOOTSTRAP_EOF)
break;
DBUG_ASSERT(rc == 0);
query= (char *) thd->memdup_w_gap(buffer, length + 1, query= (char *) thd->memdup_w_gap(buffer, length + 1,
thd->db_length + 1 + thd->db_length + 1 +
QUERY_CACHE_DB_LENGTH_SIZE + QUERY_CACHE_DB_LENGTH_SIZE +
......
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