From: Christopher Powers Date: May 24 2012 1:39am Subject: bzr push into mysql-trunk branch (chris.powers:3774) List-Archive: http://lists.mysql.com/commits/143928 Message-Id: <201205240143.q4O1ht4p016635@acsmt358.oracle.com> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit 3774 Christopher Powers 2012-05-23 [merge] local merge from mysql-trunk modified: storage/innobase/handler/ha_innodb.cc === modified file 'scripts/comp_sql.c' --- a/scripts/comp_sql.c 2011-06-27 12:14:33 +0000 +++ b/scripts/comp_sql.c 2012-05-03 03:16:40 +0000 @@ -63,9 +63,12 @@ static void die(const char *fmt, ...) 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) @@ -117,6 +120,8 @@ int main(int argc, char *argv[]) char* outfile_name= argv[3]; int rc; int query_length; + int error= 0; + char *err_ptr; if (argc != 4) die("Usage: comp_sql "); @@ -136,14 +141,34 @@ int main(int argc, char *argv[]) for ( ; ; ) { 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) 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); } === modified file 'sql/sql_bootstrap.cc' --- a/sql/sql_bootstrap.cc 2010-06-30 14:05:18 +0000 +++ b/sql/sql_bootstrap.cc 2012-05-03 03:16:40 +0000 @@ -14,24 +14,35 @@ 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ +#include +#include #include #include #include "sql_bootstrap.h" 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]; const char *line; int len; int query_len= 0; + int fgets_error= 0; + int bootstrap_error= 0; + *error= 0; 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) - return (query_len ? READ_BOOTSTRAP_ERROR : READ_BOOTSTRAP_EOF); + return (query_len == 0) ? READ_BOOTSTRAP_EOF : READ_BOOTSTRAP_ERROR; len= strlen(line); @@ -67,10 +78,22 @@ int read_bootstrap_query(char *query, in if (strncmp(line, "delimiter", 9) == 0) 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) - 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) { @@ -78,8 +101,7 @@ int read_bootstrap_query(char *query, in Append a \n to the current line, if any, to preserve the intended presentation. */ - query[query_len]= '\n'; - query_len++; + query[query_len++]= '\n'; } memcpy(query + query_len, line, len); query_len+= len; @@ -92,7 +114,7 @@ int read_bootstrap_query(char *query, in */ query[query_len]= '\0'; *query_length= query_len; - return 0; + return READ_BOOTSTRAP_SUCCESS; } } } === modified file 'sql/sql_bootstrap.h' --- a/sql/sql_bootstrap.h 2010-08-23 22:29:36 +0000 +++ b/sql/sql_bootstrap.h 2012-05-03 03:16:40 +0000 @@ -29,15 +29,18 @@ Do not increase this size, use the multiline syntax instead. */ #define MAX_BOOTSTRAP_LINE_SIZE 20000 +#define MAX_BOOTSTRAP_ERROR_LEN 256 -#define READ_BOOTSTRAP_EOF 1 -#define READ_BOOTSTRAP_ERROR 2 +#define READ_BOOTSTRAP_SUCCESS 0 +#define READ_BOOTSTRAP_EOF 1 +#define READ_BOOTSTRAP_ERROR 2 +#define READ_BOOTSTRAP_QUERY_SIZE 3 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, - fgets_input_t input, fgets_fn_t fgets_fn); + fgets_input_t input, fgets_fn_t fgets_fn, int *error); #endif === modified file 'sql/sql_parse.cc' --- a/sql/sql_parse.cc 2012-05-24 16:01:28 +0000 +++ b/sql/sql_parse.cc 2012-05-23 20:18:54 +0000 @@ -667,10 +667,13 @@ void execute_init_command(THD *thd, LEX_ #endif } -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 (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; } static void handle_bootstrap_impl(THD *thd) @@ -680,6 +683,7 @@ static void handle_bootstrap_impl(THD *t char *query; int length; int rc; + int error= 0; DBUG_ENTER("handle_bootstrap"); @@ -699,23 +703,52 @@ static void handle_bootstrap_impl(THD *t thd->init_for_queries(); + buffer[0]= '\0'; + for ( ; ; ) { - 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(); bootstrap_error= 1; break; } - if (rc == READ_BOOTSTRAP_EOF) - break; - - DBUG_ASSERT(rc == 0); - query= (char *) thd->memdup_w_gap(buffer, length + 1, thd->db_length + 1 + QUERY_CACHE_FLAGS_SIZE); No bundle (reason: useless for push emails).