Skip to content

Commit 9fb13c8

Browse files
committed
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
1 parent 8d6b9f8 commit 9fb13c8

4 files changed

Lines changed: 112 additions & 29 deletions

File tree

scripts/comp_sql.c

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,12 @@ static void die(const char *fmt, ...)
6363
exit(1);
6464
}
6565

66-
char *fgets_fn(char *buffer, size_t size, fgets_input_t input)
66+
char *fgets_fn(char *buffer, size_t size, fgets_input_t input, int *error)
6767
{
68-
return fgets(buffer, size, (FILE*) input);
68+
char *line= fgets(buffer, size, (FILE*) input);
69+
if (error)
70+
*error= (line == NULL) ? ferror((FILE*)input) : 0;
71+
return line;
6972
}
7073

7174
static void print_query(FILE *out, const char *query)
@@ -117,6 +120,8 @@ int main(int argc, char *argv[])
117120
char* outfile_name= argv[3];
118121
int rc;
119122
int query_length;
123+
int error= 0;
124+
char *err_ptr;
120125

121126
if (argc != 4)
122127
die("Usage: comp_sql <struct_name> <sql_filename> <c_filename>");
@@ -136,14 +141,34 @@ int main(int argc, char *argv[])
136141
for ( ; ; )
137142
{
138143
rc= read_bootstrap_query(query, &query_length,
139-
(fgets_input_t) in, fgets_fn);
144+
(fgets_input_t) in, fgets_fn, &error);
140145

141-
if (rc == READ_BOOTSTRAP_ERROR)
142-
die("Failed to read the bootstrap input file.\n");
143-
144146
if (rc == READ_BOOTSTRAP_EOF)
145147
break;
146148

149+
if (rc != READ_BOOTSTRAP_SUCCESS)
150+
{
151+
/* Get the most recent query text for reference. */
152+
err_ptr= query + (query_length <= MAX_BOOTSTRAP_ERROR_LEN ?
153+
0 : (query_length - MAX_BOOTSTRAP_ERROR_LEN));
154+
switch (rc)
155+
{
156+
case READ_BOOTSTRAP_ERROR:
157+
die("Failed to read the bootstrap input file. Return code (%d).\n"
158+
"Last query: '%s'\n", error, err_ptr);
159+
break;
160+
161+
case READ_BOOTSTRAP_QUERY_SIZE:
162+
die("Failed to read the boostrap input file. Query size exceeded %d bytes.\n"
163+
"Last query: '%s'.\n", MAX_BOOTSTRAP_LINE_SIZE, err_ptr);
164+
break;
165+
166+
default:
167+
die("Failed to read the boostrap input file. Unknown error.\n");
168+
break;
169+
}
170+
}
171+
147172
print_query(out, query);
148173
}
149174

sql/sql_bootstrap.cc

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,24 +14,35 @@
1414
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
1515

1616

17+
#include <stdlib.h>
18+
#include <errno.h>
1719
#include <ctype.h>
1820
#include <string.h>
1921
#include "sql_bootstrap.h"
2022

2123
int read_bootstrap_query(char *query, int *query_length,
22-
fgets_input_t input, fgets_fn_t fgets_fn)
24+
fgets_input_t input, fgets_fn_t fgets_fn, int *error)
2325
{
2426
char line_buffer[MAX_BOOTSTRAP_LINE_SIZE];
2527
const char *line;
2628
int len;
2729
int query_len= 0;
30+
int fgets_error= 0;
31+
int bootstrap_error= 0;
32+
*error= 0;
2833

2934
for ( ; ; )
3035
{
31-
line= (*fgets_fn)(line_buffer, sizeof(line_buffer), input);
36+
line= (*fgets_fn)(line_buffer, sizeof(line_buffer), input, &fgets_error);
37+
38+
if (error)
39+
*error= fgets_error;
3240

41+
if (fgets_error != 0)
42+
return READ_BOOTSTRAP_ERROR;
43+
3344
if (line == NULL)
34-
return (query_len ? READ_BOOTSTRAP_ERROR : READ_BOOTSTRAP_EOF);
45+
return (query_len == 0) ? READ_BOOTSTRAP_EOF : READ_BOOTSTRAP_ERROR;
3546

3647
len= strlen(line);
3748

@@ -67,19 +78,30 @@ int read_bootstrap_query(char *query, int *query_length,
6778
if (strncmp(line, "delimiter", 9) == 0)
6879
continue;
6980

70-
/* Append the current line to a multi line query. */
71-
81+
/* Append the current line to a multi line query. If the new line will make
82+
the query too long, preserve the partial line to provide context for the
83+
error message.
84+
*/
7285
if (query_len + len + 1 >= MAX_BOOTSTRAP_QUERY_SIZE)
73-
return READ_BOOTSTRAP_ERROR;
86+
{
87+
int new_len= MAX_BOOTSTRAP_QUERY_SIZE - query_len - 1;
88+
if ((new_len > 0) && (query_len < MAX_BOOTSTRAP_QUERY_SIZE))
89+
{
90+
memcpy(query + query_len, line, new_len);
91+
query_len+= new_len;
92+
}
93+
query[query_len]= '\0';
94+
*query_length= query_len;
95+
return READ_BOOTSTRAP_QUERY_SIZE;
96+
}
7497

7598
if (query_len != 0)
7699
{
77100
/*
78101
Append a \n to the current line, if any,
79102
to preserve the intended presentation.
80103
*/
81-
query[query_len]= '\n';
82-
query_len++;
104+
query[query_len++]= '\n';
83105
}
84106
memcpy(query + query_len, line, len);
85107
query_len+= len;
@@ -92,7 +114,7 @@ int read_bootstrap_query(char *query, int *query_length,
92114
*/
93115
query[query_len]= '\0';
94116
*query_length= query_len;
95-
return 0;
117+
return READ_BOOTSTRAP_SUCCESS;
96118
}
97119
}
98120
}

sql/sql_bootstrap.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,18 @@
2929
Do not increase this size, use the multiline syntax instead.
3030
*/
3131
#define MAX_BOOTSTRAP_LINE_SIZE 20000
32+
#define MAX_BOOTSTRAP_ERROR_LEN 256
3233

33-
#define READ_BOOTSTRAP_EOF 1
34-
#define READ_BOOTSTRAP_ERROR 2
34+
#define READ_BOOTSTRAP_SUCCESS 0
35+
#define READ_BOOTSTRAP_EOF 1
36+
#define READ_BOOTSTRAP_ERROR 2
37+
#define READ_BOOTSTRAP_QUERY_SIZE 3
3538

3639
typedef void *fgets_input_t;
37-
typedef char * (*fgets_fn_t)(char *, size_t, fgets_input_t);
40+
typedef char * (*fgets_fn_t)(char *, size_t, fgets_input_t, int *error);
3841

3942
int read_bootstrap_query(char *query, int *query_length,
40-
fgets_input_t input, fgets_fn_t fgets_fn);
43+
fgets_input_t input, fgets_fn_t fgets_fn, int *error);
4144

4245
#endif
4346

sql/sql_parse.cc

Lines changed: 43 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -666,10 +666,13 @@ void execute_init_command(THD *thd, LEX_STRING *init_command,
666666
#endif
667667
}
668668

669-
static char *fgets_fn(char *buffer, size_t size, fgets_input_t input)
669+
static char *fgets_fn(char *buffer, size_t size, fgets_input_t input, int *error)
670670
{
671671
MYSQL_FILE *in= static_cast<MYSQL_FILE*> (input);
672-
return mysql_file_fgets(buffer, size, in);
672+
char *line= mysql_file_fgets(buffer, size, in);
673+
if (error)
674+
*error= (line == NULL) ? ferror(in->m_file) : 0;
675+
return line;
673676
}
674677

675678
static void handle_bootstrap_impl(THD *thd)
@@ -679,6 +682,7 @@ static void handle_bootstrap_impl(THD *thd)
679682
char *query;
680683
int length;
681684
int rc;
685+
int error= 0;
682686

683687
DBUG_ENTER("handle_bootstrap");
684688

@@ -698,23 +702,52 @@ static void handle_bootstrap_impl(THD *thd)
698702

699703
thd->init_for_queries();
700704

705+
buffer[0]= '\0';
706+
701707
for ( ; ; )
702708
{
703-
rc= read_bootstrap_query(buffer, &length, file, fgets_fn);
709+
rc= read_bootstrap_query(buffer, &length, file, fgets_fn, &error);
704710

705-
if (rc == READ_BOOTSTRAP_ERROR)
711+
if (rc == READ_BOOTSTRAP_EOF)
712+
break;
713+
/*
714+
Check for bootstrap file errors. SQL syntax errors will be
715+
caught below.
716+
*/
717+
if (rc != READ_BOOTSTRAP_SUCCESS)
706718
{
707-
thd->raise_error(ER_SYNTAX_ERROR);
719+
/*
720+
mysql_parse() may have set a successful error status for the previous
721+
query. We must clear the error status to report the bootstrap error.
722+
*/
723+
thd->get_stmt_da()->reset_diagnostics_area();
724+
725+
/* Get the nearest query text for reference. */
726+
char *err_ptr= buffer + (length <= MAX_BOOTSTRAP_ERROR_LEN ?
727+
0 : (length - MAX_BOOTSTRAP_ERROR_LEN));
728+
switch (rc)
729+
{
730+
case READ_BOOTSTRAP_ERROR:
731+
my_printf_error(ER_UNKNOWN_ERROR, "Bootstrap file error, return code (%d). "
732+
"Nearest query: '%s'", MYF(0), error, err_ptr);
733+
break;
734+
735+
case READ_BOOTSTRAP_QUERY_SIZE:
736+
my_printf_error(ER_UNKNOWN_ERROR, "Boostrap file error. Query size "
737+
"exceeded %d bytes near '%s'.", MYF(0),
738+
MAX_BOOTSTRAP_LINE_SIZE, err_ptr);
739+
break;
740+
741+
default:
742+
DBUG_ASSERT(false);
743+
break;
744+
}
745+
708746
thd->protocol->end_statement();
709747
bootstrap_error= 1;
710748
break;
711749
}
712750

713-
if (rc == READ_BOOTSTRAP_EOF)
714-
break;
715-
716-
DBUG_ASSERT(rc == 0);
717-
718751
query= (char *) thd->memdup_w_gap(buffer, length + 1,
719752
thd->db_length + 1 +
720753
QUERY_CACHE_FLAGS_SIZE);

0 commit comments

Comments
 (0)