From 9186ff88dad674ba4c335a47e9657e5b54efbf69 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Wed, 3 Mar 2021 10:24:16 +0100 Subject: [PATCH] MDEV-9077 - sys schema preparation - increase MAX_BOOTSTRAP_QUERY_SIZE (sys.schema has SP over 50K large) don't allocate bootstrap query on heap anymore. - support DELIMITER in bootstrap --- scripts/CMakeLists.txt | 2 +- scripts/comp_sql.c | 7 +++--- sql/sql_bootstrap.cc | 53 ++++++++++++++++++++++++++++++++++++------ sql/sql_bootstrap.h | 14 ++++++++--- sql/sql_parse.cc | 6 +++-- 5 files changed, 66 insertions(+), 16 deletions(-) diff --git a/scripts/CMakeLists.txt b/scripts/CMakeLists.txt index 8d6a486a29d..44b899ef23b 100644 --- a/scripts/CMakeLists.txt +++ b/scripts/CMakeLists.txt @@ -30,7 +30,7 @@ ENDMACRO() IF(NOT CMAKE_CROSSCOMPILING) INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include) - ADD_EXECUTABLE(comp_sql comp_sql.c) + ADD_EXECUTABLE(comp_sql comp_sql.c ../sql/sql_bootstrap.cc) TARGET_LINK_LIBRARIES(comp_sql) ENDIF() diff --git a/scripts/comp_sql.c b/scripts/comp_sql.c index 5cd5642c9d0..1ce7889a90f 100644 --- a/scripts/comp_sql.c +++ b/scripts/comp_sql.c @@ -36,7 +36,7 @@ - do not duplicate the code either. so just add the sql_bootstrap.cc code as is. */ -#include "../sql/sql_bootstrap.cc" +#include "../sql/sql_bootstrap.h" FILE *in, *out; @@ -121,9 +121,10 @@ static void print_query(FILE *out, const char *query) fprintf(out, "\\n\",\n"); } +static char query[MAX_BOOTSTRAP_QUERY_SIZE]; + int main(int argc, char *argv[]) { - char query[MAX_BOOTSTRAP_QUERY_SIZE]; char* struct_name= argv[1]; char* infile_name= argv[2]; char* outfile_name= argv[3]; @@ -151,7 +152,7 @@ int main(int argc, char *argv[]) for ( ; ; ) { rc= read_bootstrap_query(query, &query_length, - (fgets_input_t) in, fgets_fn, &error); + (fgets_input_t) in, fgets_fn, 1, &error); if (rc == READ_BOOTSTRAP_EOF) break; diff --git a/sql/sql_bootstrap.cc b/sql/sql_bootstrap.cc index dbeb971cd5a..b39d7a57bc0 100644 --- a/sql/sql_bootstrap.cc +++ b/sql/sql_bootstrap.cc @@ -18,9 +18,20 @@ #include #include #include "sql_bootstrap.h" +#include -int read_bootstrap_query(char *query, int *query_length, - fgets_input_t input, fgets_fn_t fgets_fn, int *error) +static bool is_end_of_query(const char *line, size_t len, + const std::string& delimiter) +{ + if (delimiter.length() > len) + return false; + return !strcmp(line + len-delimiter.length(),delimiter.c_str()); +} + +static std::string delimiter= ";"; +extern "C" int read_bootstrap_query(char *query, int *query_length, + fgets_input_t input, fgets_fn_t fgets_fn, + int preserve_delimiter, int *error) { char line_buffer[MAX_BOOTSTRAP_LINE_SIZE]; const char *line; @@ -73,10 +84,33 @@ int read_bootstrap_query(char *query, int *query_length, if ((line[0] == '-') && (line[1] == '-')) continue; - /* Skip delimiter, ignored. */ - if (strncmp(line, "delimiter", 9) == 0) + size_t i=0; + while (line[i] == ' ') + i++; + + /* Skip -- comments */ + if (line[i] == '-' && line[i+1] == '-') continue; + if (strncmp(line, "DELIMITER", 9) == 0) + { + const char *p= strrchr(line,' '); + if (!p || !p[1]) + { + /* Invalid DELIMITER specifier */ + return READ_BOOTSTRAP_ERROR; + } + delimiter.assign(p+1); + if (preserve_delimiter) + { + memcpy(query,line,len); + query[len]=0; + *query_length = (int)len; + return READ_BOOTSTRAP_SUCCESS; + } + continue; + } + /* 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. @@ -105,13 +139,18 @@ int read_bootstrap_query(char *query, int *query_length, memcpy(query + query_len, line, len); query_len+= len; - if (line[len - 1] == ';') + if (is_end_of_query(line, len, delimiter)) { /* - The last line is terminated by ';'. + The last line is terminated by delimiter Return the query found. */ - query[query_len]= '\0'; + if (!preserve_delimiter) + { + query_len-= delimiter.length(); + query[query_len++]= ';'; + } + query[query_len]= 0; *query_length= (int)query_len; return READ_BOOTSTRAP_SUCCESS; } diff --git a/sql/sql_bootstrap.h b/sql/sql_bootstrap.h index f12d66a522e..e5b9b3a55c2 100644 --- a/sql/sql_bootstrap.h +++ b/sql/sql_bootstrap.h @@ -23,7 +23,7 @@ The longest query in use depends on the documentation content, see the file fill_help_tables.sql */ -#define MAX_BOOTSTRAP_QUERY_SIZE 20000 +#define MAX_BOOTSTRAP_QUERY_SIZE 60000 /** The maximum size of a bootstrap query, expressed in a single line. Do not increase this size, use the multiline syntax instead. @@ -39,8 +39,16 @@ typedef void *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, int *error); +#ifdef __cplusplus +extern "C" { +#endif +int read_bootstrap_query(char *query, int *query_length, fgets_input_t input, + fgets_fn_t fgets_fn, + int preserve_delimiter, + int *error); +#ifdef __cplusplus +} +#endif #endif diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 807bde840df..a574cb927eb 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -978,6 +978,7 @@ int bootstrap(MYSQL_FILE *file) DBUG_ENTER("handle_bootstrap"); THD *thd= new THD(next_thread_id()); + char *buffer= new char[MAX_BOOTSTRAP_QUERY_SIZE]; #ifdef WITH_WSREP thd->variables.wsrep_on= 0; #endif @@ -1011,12 +1012,12 @@ int bootstrap(MYSQL_FILE *file) for ( ; ; ) { - char buffer[MAX_BOOTSTRAP_QUERY_SIZE] = ""; + buffer[0]= 0; int rc, length; char *query; int error= 0; - rc= read_bootstrap_query(buffer, &length, file, fgets_fn, &error); + rc= read_bootstrap_query(buffer, &length, file, fgets_fn, 0, &error); if (rc == READ_BOOTSTRAP_EOF) break; @@ -1099,6 +1100,7 @@ int bootstrap(MYSQL_FILE *file) thd->lex->restore_set_statement_var(); } delete thd; + delete[] buffer; DBUG_RETURN(bootstrap_error); }