This action will force synchronization from nwsuafzq/MySQLAdvisor, which will overwrite any changes that you have made since you forked the repository, and can not be recovered!!!
Synchronous operation will process in the background and will refresh the page when finishing processing. Please be patient.
/* Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.This program is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; version 2 of the License.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free Software Foundation,51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA *//**@file@briefText .frm files management routines*/#include "sql_priv.h"#include "parse_file.h"#include "unireg.h" // CREATE_MODE#include "sql_table.h" // build_table_filename#include <errno.h>#include <m_ctype.h>#include <my_sys.h>#include <my_dir.h>/* from sql_db.cc */extern long mysql_rm_arc_files(THD *thd, MY_DIR *dirp, const char *org_path);/**Write string with escaping.@param file IO_CACHE for record@param val_s string for writing@retvalFALSE OK@retvalTRUE error*/static my_boolwrite_escaped_string(IO_CACHE *file, LEX_STRING *val_s){char *eos= val_s->str + val_s->length;char *ptr= val_s->str;for (; ptr < eos; ptr++){/*Should be in sync with read_escaped_string() andparse_quoted_escaped_string()*/switch(*ptr) {case '\\': // escape characterif (my_b_append(file, (const uchar *)STRING_WITH_LEN("\\\\")))return TRUE;break;case '\n': // parameter value delimiterif (my_b_append(file, (const uchar *)STRING_WITH_LEN("\\n")))return TRUE;break;case '0円': // problem for some string processing utilitiesif (my_b_append(file, (const uchar *)STRING_WITH_LEN("\\0")))return TRUE;break;case 26: // problem for windows utilities (Ctrl-Z)if (my_b_append(file, (const uchar *)STRING_WITH_LEN("\\z")))return TRUE;break;case '\'': // list of string delimiterif (my_b_append(file, (const uchar *)STRING_WITH_LEN("\\\'")))return TRUE;break;default:if (my_b_append(file, (const uchar *)ptr, 1))return TRUE;}}return FALSE;}/**Write parameter value to IO_CACHE.@param file pointer to IO_CACHE structure for writing@param base pointer to data structure@param parameter pointer to parameter descriptor@retvalFALSE OK@retvalTRUE error*/static my_boolwrite_parameter(IO_CACHE *file, uchar* base, File_option *parameter){char num_buf[20]; // buffer for numeric operations// string for numeric operationsString num(num_buf, sizeof(num_buf), &my_charset_bin);DBUG_ENTER("write_parameter");switch (parameter->type) {case FILE_OPTIONS_STRING:{LEX_STRING *val_s= (LEX_STRING *)(base + parameter->offset);if (my_b_append(file, (const uchar *)val_s->str, val_s->length))DBUG_RETURN(TRUE);break;}case FILE_OPTIONS_ESTRING:{if (write_escaped_string(file, (LEX_STRING *)(base + parameter->offset)))DBUG_RETURN(TRUE);break;}case FILE_OPTIONS_ULONGLONG:{num.set(*((ulonglong *)(base + parameter->offset)), &my_charset_bin);if (my_b_append(file, (const uchar *)num.ptr(), num.length()))DBUG_RETURN(TRUE);break;}case FILE_OPTIONS_TIMESTAMP:{/* string have to be allocated already */LEX_STRING *val_s= (LEX_STRING *)(base + parameter->offset);time_t tm= my_time(0);get_date(val_s->str, GETDATE_DATE_TIME|GETDATE_GMT|GETDATE_FIXEDLENGTH,tm);val_s->length= PARSE_FILE_TIMESTAMPLENGTH;if (my_b_append(file, (const uchar *)val_s->str,PARSE_FILE_TIMESTAMPLENGTH))DBUG_RETURN(TRUE);break;}case FILE_OPTIONS_STRLIST:{List_iterator_fast<LEX_STRING> it(*((List<LEX_STRING>*)(base + parameter->offset)));bool first= 1;LEX_STRING *str;while ((str= it++)){// We need ' ' after string to detect list continuationif ((!first && my_b_append(file, (const uchar *)STRING_WITH_LEN(" "))) ||my_b_append(file, (const uchar *)STRING_WITH_LEN("\'")) ||write_escaped_string(file, str) ||my_b_append(file, (const uchar *)STRING_WITH_LEN("\'"))){DBUG_RETURN(TRUE);}first= 0;}break;}case FILE_OPTIONS_ULLLIST:{List_iterator_fast<ulonglong> it(*((List<ulonglong>*)(base + parameter->offset)));bool first= 1;ulonglong *val;while ((val= it++)){num.set(*val, &my_charset_bin);// We need ' ' after string to detect list continuationif ((!first && my_b_append(file, (const uchar *)STRING_WITH_LEN(" "))) ||my_b_append(file, (const uchar *)num.ptr(), num.length())){DBUG_RETURN(TRUE);}first= 0;}break;}default:DBUG_ASSERT(0); // never should happened}DBUG_RETURN(FALSE);}/**Renames a frm file (including backups) in same schema.@thd thread handler@param schema name of given schema@param old_name original file name@param new_db new schema@param new_name new file name@retval0 OK@retval1 Error (only if renaming of frm failed)*/my_bool rename_in_schema_file(THD *thd,const char *schema, const char *old_name,const char *new_db, const char *new_name){char old_path[FN_REFLEN + 1], new_path[FN_REFLEN + 1], arc_path[FN_REFLEN + 1];build_table_filename(old_path, sizeof(old_path) - 1,schema, old_name, reg_ext, 0);build_table_filename(new_path, sizeof(new_path) - 1,new_db, new_name, reg_ext, 0);if (mysql_file_rename(key_file_frm, old_path, new_path, MYF(MY_WME)))return 1;/* check if arc_dir exists: disabled unused feature (see bug #17823). */build_table_filename(arc_path, sizeof(arc_path) - 1, schema, "arc", "", 0);{ // remove obsolete 'arc' directory and files if anyMY_DIR *new_dirp;if ((new_dirp = my_dir(arc_path, MYF(MY_DONT_SORT)))){DBUG_PRINT("my",("Archive subdir found: %s", arc_path));(void) mysql_rm_arc_files(thd, new_dirp, arc_path);}}return 0;}/**Prepare frm to parse (read to memory).@param file_name path & filename to .frm file@param mem_root MEM_ROOT for buffer allocation@param bad_format_errors send errors on bad content@notereturned pointer + 1 will be type of .frm@return0 - error@returnparser object*/File_parser *sql_parse_prepare(const LEX_STRING *file_name, MEM_ROOT *mem_root,bool bad_format_errors){MY_STAT stat_info;size_t len;char *buff, *end, *sign;File_parser *parser;File file;DBUG_ENTER("sql_parse_prepare");if (!mysql_file_stat(key_file_fileparser,file_name->str, &stat_info, MYF(MY_WME))){DBUG_RETURN(0);}if (stat_info.st_size > INT_MAX-1){my_error(ER_FPARSER_TOO_BIG_FILE, MYF(0), file_name->str);DBUG_RETURN(0);}if (!(parser= new(mem_root) File_parser)){DBUG_RETURN(0);}if (!(buff= (char*) alloc_root(mem_root, stat_info.st_size+1))){DBUG_RETURN(0);}if ((file= mysql_file_open(key_file_fileparser, file_name->str,O_RDONLY | O_SHARE, MYF(MY_WME))) < 0){DBUG_RETURN(0);}if ((len= mysql_file_read(file, (uchar *)buff, stat_info.st_size,MYF(MY_WME))) == MY_FILE_ERROR){mysql_file_close(file, MYF(MY_WME));DBUG_RETURN(0);}if (mysql_file_close(file, MYF(MY_WME))){DBUG_RETURN(0);}end= buff + len;*end= '0円'; // barrier for more simple parsing// 7 = 5 (TYPE=) + 1 (letter at least of type name) + 1 ('\n')if (len < 7 ||buff[0] != 'T' ||buff[1] != 'Y' ||buff[2] != 'P' ||buff[3] != 'E' ||buff[4] != '=')goto frm_error;// skip signature;parser->file_type.str= sign= buff + 5;while (*sign >= 'A' && *sign <= 'Z' && sign < end)sign++;if (*sign != '\n')goto frm_error;parser->file_type.length= sign - parser->file_type.str;// EOS for file signature just for safety*sign= '0円';parser->end= end;parser->start= sign + 1;parser->content_ok= 1;DBUG_RETURN(parser);frm_error:if (bad_format_errors){my_error(ER_FPARSER_BAD_HEADER, MYF(0), file_name->str);DBUG_RETURN(0);}elseDBUG_RETURN(parser); // upper level have to check parser->ok()}/**parse LEX_STRING.@param ptr pointer on string beginning@param end pointer on symbol after parsed string end (still ownedby buffer and can be accessed@param mem_root MEM_ROOT for parameter allocation@param str pointer on string, where results should be stored@retval0 error@retval\# pointer on symbol after string*/static const char *parse_string(const char *ptr, const char *end, MEM_ROOT *mem_root,LEX_STRING *str){// get string lengthconst char *eol= strchr(ptr, '\n');if (eol >= end)return 0;str->length= eol - ptr;if (!(str->str= strmake_root(mem_root, ptr, str->length)))return 0;return eol+1;}/**read escaped string from ptr to eol in already allocated str.@param ptr pointer on string beginning@param eol pointer on character after end of string@param str target string@retvalFALSE OK@retvalTRUE error*/my_boolread_escaped_string(const char *ptr, const char *eol, LEX_STRING *str){char *write_pos= str->str;for (; ptr < eol; ptr++, write_pos++){char c= *ptr;if (c == '\\'){ptr++;if (ptr >= eol)return TRUE;/*Should be in sync with write_escaped_string() andparse_quoted_escaped_string()*/switch(*ptr) {case '\\':*write_pos= '\\';break;case 'n':*write_pos= '\n';break;case '0':*write_pos= '0円';break;case 'z':*write_pos= 26;break;case '\'':*write_pos= '\'';break;default:return TRUE;}}else*write_pos= c;}str->str[str->length= write_pos-str->str]= '0円'; // just for safetyreturn FALSE;}/**parse \\n delimited escaped string.@param ptr pointer on string beginning@param end pointer on symbol after parsed string end (still ownedby buffer and can be accessed@param mem_root MEM_ROOT for parameter allocation@param str pointer on string, where results should be stored@retval0 error@retval\# pointer on symbol after string*/const char *parse_escaped_string(const char *ptr, const char *end, MEM_ROOT *mem_root,LEX_STRING *str){const char *eol= strchr(ptr, '\n');if (eol == 0 || eol >= end ||!(str->str= (char*) alloc_root(mem_root, (eol - ptr) + 1)) ||read_escaped_string(ptr, eol, str))return 0;return eol+1;}/**parse '' delimited escaped string.@param ptr pointer on string beginning@param end pointer on symbol after parsed string end (still ownedby buffer and can be accessed@param mem_root MEM_ROOT for parameter allocation@param str pointer on string, where results should be stored@retval0 error@retval\# pointer on symbol after string*/static const char *parse_quoted_escaped_string(const char *ptr, const char *end,MEM_ROOT *mem_root, LEX_STRING *str){const char *eol;uint result_len= 0;bool escaped= 0;// starting 'if (*(ptr++) != '\'')return 0;// find ending 'for (eol= ptr; (*eol != '\'' || escaped) && eol < end; eol++){if (!(escaped= (*eol == '\\' && !escaped)))result_len++;}// process stringif (eol >= end ||!(str->str= (char*) alloc_root(mem_root, result_len + 1)) ||read_escaped_string(ptr, eol, str))return 0;return eol+1;}/**Parser for FILE_OPTIONS_ULLLIST type value.@param[in,out] ptr pointer to parameter@param[in] end end of the configuration@param[in] line pointer to the line begining@param[in] base base address for parameter writing (structurelike TABLE)@param[in] parameter description@param[in] mem_root MEM_ROOT for parameters allocation*/bool get_file_options_ulllist(const char *&ptr, const char *end, const char *line,uchar* base, File_option *parameter,MEM_ROOT *mem_root){List<ulonglong> *nlist= (List<ulonglong>*)(base + parameter->offset);ulonglong *num;nlist->empty();// list parsingwhile (ptr < end){int not_used;char *num_end= const_cast<char *>(end);if (!(num= (ulonglong*)alloc_root(mem_root, sizeof(ulonglong))) ||nlist->push_back(num, mem_root))goto nlist_err;*num= my_strtoll10(ptr, &num_end, ¬_used);ptr= num_end;switch (*ptr) {case '\n':goto end_of_nlist;case ' ':// we cant go over buffer bounds, because we have 0円 at the endptr++;break;default:goto nlist_err_w_message;}}end_of_nlist:if (*(ptr++) != '\n')goto nlist_err;return FALSE;nlist_err_w_message:my_error(ER_FPARSER_ERROR_IN_PARAMETER, MYF(0), parameter->name.str, line);nlist_err:return TRUE;}/**parse parameters.@param base base address for parameter writing (structure likeTABLE)@param mem_root MEM_ROOT for parameters allocation@param parameters parameters description@param required number of required parameters in above list. If the filecontains more parameters than "required", they willbe ignored. If the file contains less parametersthen "required", non-existing parameters willremain their values.@param hook hook called for unknown keys@param hook_data some data specific for the hook@retvalFALSE OK@retvalTRUE error*/my_boolFile_parser::parse(uchar* base, MEM_ROOT *mem_root,struct File_option *parameters, uint required,Unknown_key_hook *hook) const{uint first_param= 0, found= 0;const char *ptr= start;const char *eol;LEX_STRING *str;List<LEX_STRING> *list;DBUG_ENTER("File_parser::parse");while (ptr < end && found < required){const char *line= ptr;if (*ptr == '#'){// it is commentif (!(ptr= strchr(ptr, '\n'))){my_error(ER_FPARSER_EOF_IN_COMMENT, MYF(0), line);DBUG_RETURN(TRUE);}ptr++;}else{File_option *parameter= parameters+first_param,*parameters_end= parameters+required;int len= 0;for (; parameter < parameters_end; parameter++){len= parameter->name.length;// check lengthif (len < (end-ptr) && ptr[len] != '=')continue;// check keywordif (memcmp(parameter->name.str, ptr, len) == 0)break;}if (parameter < parameters_end){found++;/*if we found first parameter, start search from next parameternext time.(this small optimisation should work, because they should bewritten in same order)*/if (parameter == parameters+first_param)first_param++;// get valueptr+= (len+1);switch (parameter->type) {case FILE_OPTIONS_STRING:{if (!(ptr= parse_string(ptr, end, mem_root,(LEX_STRING *)(base +parameter->offset)))){my_error(ER_FPARSER_ERROR_IN_PARAMETER, MYF(0),parameter->name.str, line);DBUG_RETURN(TRUE);}break;}case FILE_OPTIONS_ESTRING:{if (!(ptr= parse_escaped_string(ptr, end, mem_root,(LEX_STRING *)(base + parameter->offset)))){my_error(ER_FPARSER_ERROR_IN_PARAMETER, MYF(0),parameter->name.str, line);DBUG_RETURN(TRUE);}break;}case FILE_OPTIONS_ULONGLONG:if (!(eol= strchr(ptr, '\n'))){my_error(ER_FPARSER_ERROR_IN_PARAMETER, MYF(0),parameter->name.str, line);DBUG_RETURN(TRUE);}{int not_used;*((ulonglong*)(base + parameter->offset))=my_strtoll10(ptr, 0, ¬_used);}ptr= eol+1;break;case FILE_OPTIONS_TIMESTAMP:{/* string have to be allocated already */LEX_STRING *val= (LEX_STRING *)(base + parameter->offset);/* yyyy-mm-dd HH:MM:SS = 19(PARSE_FILE_TIMESTAMPLENGTH) characters */if (ptr[PARSE_FILE_TIMESTAMPLENGTH] != '\n'){my_error(ER_FPARSER_ERROR_IN_PARAMETER, MYF(0),parameter->name.str, line);DBUG_RETURN(TRUE);}memcpy(val->str, ptr, PARSE_FILE_TIMESTAMPLENGTH);val->str[val->length= PARSE_FILE_TIMESTAMPLENGTH]= '0円';ptr+= (PARSE_FILE_TIMESTAMPLENGTH+1);break;}case FILE_OPTIONS_STRLIST:{list= (List<LEX_STRING>*)(base + parameter->offset);list->empty();// list parsingwhile (ptr < end){if (!(str= (LEX_STRING*)alloc_root(mem_root,sizeof(LEX_STRING))) ||list->push_back(str, mem_root))goto list_err;if (!(ptr= parse_quoted_escaped_string(ptr, end, mem_root, str)))goto list_err_w_message;switch (*ptr) {case '\n':goto end_of_list;case ' ':// we cant go over buffer bounds, because we have 0円 at the endptr++;break;default:goto list_err_w_message;}}end_of_list:if (*(ptr++) != '\n')goto list_err;break;list_err_w_message:my_error(ER_FPARSER_ERROR_IN_PARAMETER, MYF(0),parameter->name.str, line);list_err:DBUG_RETURN(TRUE);}case FILE_OPTIONS_ULLLIST:if (get_file_options_ulllist(ptr, end, line, base,parameter, mem_root))DBUG_RETURN(TRUE);break;default:DBUG_ASSERT(0); // never should happened}}else{ptr= line;if (hook->process_unknown_string(ptr, base, mem_root, end)){DBUG_RETURN(TRUE);}// skip unknown parameterif (!(ptr= strchr(ptr, '\n'))){my_error(ER_FPARSER_EOF_IN_UNKNOWN_PARAMETER, MYF(0), line);DBUG_RETURN(TRUE);}ptr++;}}}/*NOTE: if we read less than "required" parameters, it is still Ok.Probably, we've just read the file of the previous version, whichcontains less parameters.*/DBUG_RETURN(FALSE);}/**Dummy unknown key hook.@param[in,out] unknown_key reference on the line with unknownparameter and the parsing point@param[in] base base address for parameter writing(structure like TABLE)@param[in] mem_root MEM_ROOT for parameters allocation@param[in] end the end of the configuration@noteThis hook used to catch no longer supported keys and process them forbackward compatibility, but it will not slow down processing of modernformat files.This hook does nothing except debug output.@retvalFALSE OK@retvalTRUE Error*/boolFile_parser_dummy_hook::process_unknown_string(const char *&unknown_key,uchar* base, MEM_ROOT *mem_root,const char *end){DBUG_ENTER("file_parser_dummy_hook::process_unknown_string");DBUG_PRINT("info", ("Unknown key: '%60s'", unknown_key));DBUG_RETURN(FALSE);}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。