diff options
-rw-r--r-- | include/mysql_com.h | 2 | ||||
-rw-r--r-- | sql/discover.cc | 10 | ||||
-rw-r--r-- | sql/discover.h | 2 | ||||
-rw-r--r-- | sql/share/errmsg-utf8.txt | 6 | ||||
-rw-r--r-- | sql/sql_table.cc | 8 | ||||
-rw-r--r-- | sql/table.cc | 41 | ||||
-rw-r--r-- | sql/table.h | 6 | ||||
-rw-r--r-- | sql/unireg.cc | 55 | ||||
-rw-r--r-- | sql/unireg.h | 6 | ||||
-rw-r--r-- | storage/federatedx/ha_federatedx.cc | 7 |
10 files changed, 75 insertions, 68 deletions
diff --git a/include/mysql_com.h b/include/mysql_com.h index 5697fc952ce..9ba17b416c4 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -41,7 +41,7 @@ /* Maximum length of comments */ -#define TABLE_COMMENT_INLINE_MAXLEN 180 /* pre 6.0: 60 characters */ +#define TABLE_COMMENT_INLINE_MAXLEN 180 /* pre 5.5: 60 characters */ #define TABLE_COMMENT_MAXLEN 2048 #define COLUMN_COMMENT_MAXLEN 1024 #define INDEX_COMMENT_MAXLEN 1024 diff --git a/sql/discover.cc b/sql/discover.cc index 5add741fc0c..b5bccf7dcb0 100644 --- a/sql/discover.cc +++ b/sql/discover.cc @@ -111,17 +111,21 @@ int readfrm(const char *name, const uchar **frmdata, size_t *len) */ int writefrm(const char *path, const char *db, const char *table, - bool need_sync, const uchar *frmdata, size_t len) + bool tmp_table, const uchar *frmdata, size_t len) { char file_name[FN_REFLEN+1]; int error; + int create_flags= O_RDWR | O_TRUNC; DBUG_ENTER("writefrm"); DBUG_PRINT("enter",("name: '%s' len: %lu ",path, (ulong) len)); + if (tmp_table) + create_flags|= O_EXCL | O_NOFOLLOW; + strxnmov(file_name, sizeof(file_name)-1, path, reg_ext, NullS); File file= mysql_file_create(key_file_frm, file_name, - CREATE_MODE, O_RDWR | O_TRUNC, MYF(0)); + CREATE_MODE, create_flags, MYF(0)); if ((error= file < 0)) { @@ -134,7 +138,7 @@ int writefrm(const char *path, const char *db, const char *table, { error= mysql_file_write(file, frmdata, len, MYF(MY_WME | MY_NABP)); - if (!error && need_sync && opt_sync_frm) + if (!error && !tmp_table && opt_sync_frm) error= mysql_file_sync(file, MYF(MY_WME)) || my_sync_dir_by_file(file_name, MYF(MY_WME)); diff --git a/sql/discover.h b/sql/discover.h index aad8bb734ec..fbf94891c74 100644 --- a/sql/discover.h +++ b/sql/discover.h @@ -24,7 +24,7 @@ int extension_based_table_discovery(MY_DIR *dirp, const char *ext, #ifdef MYSQL_SERVER int readfrm(const char *name, const uchar **data, size_t *length); int writefrm(const char *path, const char *db, const char *table, - bool need_sync, const uchar *frmdata, size_t len); + bool tmp_table, const uchar *frmdata, size_t len); int ext_table_discovery_simple(MY_DIR *dirp, handlerton::discovered_list *result); diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index 036d4a0258c..6a7eafc5fc4 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -6192,9 +6192,9 @@ ER_TOO_LONG_TABLE_COMMENT por "Comentário para a tabela '%-.64s' é longo demais (max = %u)" ger "Kommentar für Tabelle '%-.64s' ist zu lang (max = %u)" ER_TOO_LONG_FIELD_COMMENT - eng "Comment for field '%-.64s' is too long (max = %lu)" - por "Comentário para o campo '%-.64s' é longo demais (max = %lu)" - ger "Kommentar für Feld '%-.64s' ist zu lang (max = %lu)" + eng "Comment for field '%-.64s' is too long (max = %u)" + por "Comentário para o campo '%-.64s' é longo demais (max = %u)" + ger "Kommentar für Feld '%-.64s' ist zu lang (max = %u)" ER_FUNC_INEXISTENT_NAME_COLLISION 42000 eng "FUNCTION %s does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual" ger "FUNCTION %s existiert nicht. Erläuterungen im Abschnitt 'Function Name Parsing and Resolution' im Referenzhandbuch" diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 8862fcc7d0e..eb02e9f2baf 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1709,7 +1709,7 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags) } int error= writefrm(shadow_path, lpt->db, lpt->table_name, - !lpt->create_info->tmp_table(), frm.str, frm.length); + lpt->create_info->tmp_table(), frm.str, frm.length); my_free(const_cast<uchar*>(frm.str)); if (error || lpt->table->file->ha_create_partitioning_metadata(shadow_path, @@ -1751,7 +1751,7 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags) */ build_table_filename(path, sizeof(path) - 1, lpt->db, lpt->table_name, "", 0); - strxmov(frm_name, path, reg_ext, NullS); + strxnmov(frm_name, sizeof(frm_name), path, reg_ext, NullS); /* When we are changing to use new frm file we need to ensure that we don't collide with another thread in process to open the frm file. @@ -4467,7 +4467,7 @@ bool mysql_create_table_no_lock(THD *thd, create_info, file)) { char frm_name[FN_REFLEN]; - strxmov(frm_name, path, reg_ext, NullS); + strxnmov(frm_name, sizeof(frm_name), path, reg_ext, NullS); (void) mysql_file_delete(key_file_frm, frm_name, MYF(0)); goto err; } @@ -6661,7 +6661,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, if (need_copy_table == ALTER_TABLE_METADATA_ONLY) { char frm_name[FN_REFLEN+1]; - strxmov(frm_name, path, reg_ext, NullS); + strxnmov(frm_name, sizeof(frm_name), path, reg_ext, NullS); /* C_ALTER_TABLE_FRM_ONLY can only be used if old frm exists. discovering frm-less engines cannot enjoy this optimization. diff --git a/sql/table.cc b/sql/table.cc index ccb763847d6..faa087cbaa4 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -592,11 +592,10 @@ enum open_frm_error open_table_def(THD *thd, TABLE_SHARE *share, uint flags) { bool error_given= false; File file; - MY_STAT stats; uchar *buf; uchar head[FRM_HEADER_SIZE]; char path[FN_REFLEN]; - size_t frmlen; + size_t frmlen, read_length; DBUG_ENTER("open_table_def"); DBUG_PRINT("enter", ("table: '%s'.'%s' path: '%s'", share->db.str, share->table_name.str, share->normalized_path.str)); @@ -640,26 +639,26 @@ enum open_frm_error open_table_def(THD *thd, TABLE_SHARE *share, uint flags) goto err; } - if (my_fstat(file, &stats, MYF(0))) - goto err; - - frmlen= min(FRM_MAX_SIZE, stats.st_size); // safety + frmlen= uint4korr(head+10); + set_if_smaller(frmlen, FRM_MAX_SIZE); // safety if (!(buf= (uchar*)my_malloc(frmlen, MYF(MY_THREAD_SPECIFIC|MY_WME)))) goto err; memcpy(buf, head, sizeof(head)); - if (mysql_file_read(file, buf + sizeof(head), - frmlen - sizeof(head), MYF(MY_NABP))) + read_length= mysql_file_read(file, buf + sizeof(head), + frmlen - sizeof(head), MYF(MY_WME)); + if (read_length == 0 || read_length == (size_t)-1) { - share->error = my_errno == HA_ERR_FILE_TOO_SHORT - ? OPEN_FRM_CORRUPTED : OPEN_FRM_READ_ERROR; + share->error = OPEN_FRM_READ_ERROR; my_free(buf); goto err; } mysql_file_close(file, MYF(MY_WME)); + frmlen= read_length + sizeof(head); + share->init_from_binary_frm_image(thd, false, buf, frmlen); error_given= true; // init_from_binary_frm_image has already called my_error() my_free(buf); @@ -759,17 +758,21 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, if (*extra2 != '/') // old frm had '/' there { const uchar *e2end= extra2 + len; - while (extra2 < e2end) + while (extra2 + 3 < e2end) { uchar type= *extra2++; size_t length= *extra2++; if (!length) { + if (extra2 + 258 >= e2end) + goto err; length= uint2korr(extra2); extra2+=2; if (length < 256) goto err; } + if (extra2 + length > e2end) + goto err; switch (type) { case EXTRA2_TABLEDEF_VERSION: if (tabledef_version.str) // see init_from_sql_statement_string() @@ -780,12 +783,10 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, } else { - uchar *buf= (uchar*) alloc_root(&mem_root, length); - if (!buf) - goto err; - memcpy(buf, extra2, length); - tabledef_version.str= buf; tabledef_version.length= length; + tabledef_version.str= (uchar*)memdup_root(&mem_root, extra2, length); + if (!tabledef_version.str) + goto err; } break; case EXTRA2_ENGINE_TABLEOPTS: @@ -797,12 +798,12 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, break; default: /* abort frm parsing if it's an unknown but important extra2 value */ - if (type >= 128) + if (type >= EXTRA2_ENGINE_IMPORTANT) goto err; } extra2+= length; } - if (extra2 > e2end) + if (extra2 != e2end) goto err; } @@ -2116,7 +2117,7 @@ ret: bool TABLE_SHARE::write_frm_image(const uchar *frm, size_t len) { - return writefrm(normalized_path.str, db.str, table_name.str, 1, frm, len); + return writefrm(normalized_path.str, db.str, table_name.str, false, frm, len); } @@ -3242,7 +3243,7 @@ rename_file_ext(const char * from,const char * to,const char * ext) char from_b[FN_REFLEN],to_b[FN_REFLEN]; (void) strxmov(from_b,from,ext,NullS); (void) strxmov(to_b,to,ext,NullS); - return (mysql_file_rename(key_file_frm, from_b, to_b, MYF(0))); + return mysql_file_rename(key_file_frm, from_b, to_b, MYF(0)); } diff --git a/sql/table.h b/sql/table.h index 2d929bfc41b..fa5bd83371a 100644 --- a/sql/table.h +++ b/sql/table.h @@ -2539,12 +2539,6 @@ static inline int set_zone(int nr,int min_zone,int max_zone) return nr; } -/* Adjust number to next larger disk buffer */ -static inline ulong next_io_size(ulong pos) -{ - return MY_ALIGN(pos, IO_SIZE); -} - /* performance schema */ extern LEX_STRING PERFORMANCE_SCHEMA_DB_NAME; diff --git a/sql/unireg.cc b/sql/unireg.cc index bb34c6e800b..0940b34308f 100644 --- a/sql/unireg.cc +++ b/sql/unireg.cc @@ -67,7 +67,7 @@ LEX_CUSTRING build_frm_image(THD *thd, const char *table, uint keys, KEY *key_info, handler *db_file) { LEX_STRING str_db_type; - uint reclength, key_info_length, maxlength, tmp_len, i; + uint reclength, key_info_length, tmp_len, i; ulong key_buff_length; ulong filepos, data_offset; uint options_len; @@ -173,7 +173,7 @@ LEX_CUSTRING build_frm_image(THD *thd, const char *table, /* If table comment is longer than TABLE_COMMENT_INLINE_MAXLEN bytes, store the comment in an extra segment (up to TABLE_COMMENT_MAXLEN bytes). - Pre 6.0, the limit was 60 characters, with no extra segment-handling. + Pre 5.5, the limit was 60 characters, with no extra segment-handling. */ if (create_info->comment.length > TABLE_COMMENT_INLINE_MAXLEN) { @@ -212,7 +212,7 @@ LEX_CUSTRING build_frm_image(THD *thd, const char *table, frm.length+= extra2_size + 4; // mariadb extra2 frm segment int2store(fileinfo+4, extra2_size); - int2store(fileinfo+6, frm.length); + int2store(fileinfo+6, frm.length); // Position to key information frm.length+= key_buff_length; frm.length+= reclength; // row with default values frm.length+= create_info->extra_size; @@ -228,7 +228,8 @@ LEX_CUSTRING build_frm_image(THD *thd, const char *table, /* write the extra2 segment */ pos = frm_ptr + 64; - *pos++ = EXTRA2_TABLEDEF_VERSION; + compile_time_assert(EXTRA2_TABLEDEF_VERSION != '/'); + *pos++ = EXTRA2_TABLEDEF_VERSION; // old servers write '/' here *pos++ = create_info->tabledef_version.length; memcpy(pos, create_info->tabledef_version.str, create_info->tabledef_version.length); @@ -241,7 +242,11 @@ LEX_CUSTRING build_frm_image(THD *thd, const char *table, *pos++= options_len; else { - DBUG_ASSERT(options_len <= 65535); // FIXME if necessary + /* + At the moment we support options_len up to 64K. + We can easily extend it in the future, if the need arises. + */ + DBUG_ASSERT(options_len <= 65535); int2store(pos + 1, options_len); pos+= 3; } @@ -255,9 +260,8 @@ LEX_CUSTRING build_frm_image(THD *thd, const char *table, DBUG_ASSERT(pos == frm_ptr + uint2korr(fileinfo+6)); key_info_length= pack_keys(pos, keys, key_info, data_offset); - maxlength=(uint) next_io_size((ulong) (uint2korr(forminfo)+1000)); - int2store(forminfo+2,maxlength); - int4store(fileinfo+10,(ulong) (filepos+maxlength)); + int2store(forminfo+2, frm.length - filepos); + int4store(fileinfo+10, frm.length); fileinfo[26]= (uchar) test((create_info->max_rows == 1) && (create_info->min_rows == 1) && (keys == 0)); int2store(fileinfo+28,key_info_length); @@ -312,7 +316,7 @@ LEX_CUSTRING build_frm_image(THD *thd, const char *table, pos+= key_info[i].parser_name->length + 1; } } - if (forminfo[46] == (uchar)255) + if (forminfo[46] == (uchar)255) // New style MySQL 5.5 table comment { int2store(pos, create_info->comment.length); pos+=2; @@ -378,7 +382,7 @@ int rea_create_table(THD *thd, LEX_CUSTRING *frm, { // TODO don't write frm for temp tables if (create_info->tmp_table() && - writefrm(path, db, table_name, 0, frm->str, frm->length)) + writefrm(path, db, table_name, true, frm->str, frm->length)) goto err_handler; if (thd->variables.keep_files_on_create) @@ -393,7 +397,7 @@ int rea_create_table(THD *thd, LEX_CUSTRING *frm, } else { - if (writefrm(path, db, table_name, 1, frm->str, frm->length)) + if (writefrm(path, db, table_name, false, frm->str, frm->length)) goto err_handler; } @@ -524,19 +528,18 @@ static bool pack_header(uchar *forminfo, List<Create_field> &create_fields, COLUMN_COMMENT_MAXLEN); if (tmp_len < field->comment.length) { - if ((current_thd->variables.sql_mode & - (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES))) - { - my_error(ER_TOO_LONG_FIELD_COMMENT, MYF(0), field->field_name, - static_cast<ulong>(COLUMN_COMMENT_MAXLEN)); + myf myf_warning= ME_JUST_WARNING; + ulonglong sql_mode= current_thd->variables.sql_mode; + + if (sql_mode & (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES)) + myf_warning= 0; + + my_error(ER_TOO_LONG_FIELD_COMMENT, myf_warning, field->field_name, + COLUMN_COMMENT_MAXLEN); + + if (!myf_warning) DBUG_RETURN(1); - } - char warn_buff[MYSQL_ERRMSG_SIZE]; - my_snprintf(warn_buff, sizeof(warn_buff), ER(ER_TOO_LONG_FIELD_COMMENT), - field->field_name, - static_cast<ulong>(COLUMN_COMMENT_MAXLEN)); - push_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, - ER_TOO_LONG_FIELD_COMMENT, warn_buff); + field->comment.length= tmp_len; } if (field->vcol_info) @@ -562,7 +565,7 @@ static bool pack_header(uchar *forminfo, List<Create_field> &create_fields, expressions saved in the frm file for virtual columns. */ vcol_info_length+= field->vcol_info->expr_str.length+ - FRM_VCOL_HEADER_SIZE(field->interval!=NULL); + FRM_VCOL_HEADER_SIZE(field->interval); } totlength+= field->length; @@ -890,10 +893,10 @@ static bool pack_fields(uchar *buff, List<Create_field> &create_fields, */ if (field->vcol_info && field->vcol_info->expr_str.length) { - *buff++= (uchar)(1 + test(field->interval_id)); + *buff++= (uchar)(1 + test(field->interval)); *buff++= (uchar) field->sql_type; *buff++= (uchar) field->stored_in_db; - if (field->interval_id) + if (field->interval) *buff++= (uchar) field->interval_id; memcpy(buff, field->vcol_info->expr_str.str, field->vcol_info->expr_str.length); buff+= field->vcol_info->expr_str.length; diff --git a/sql/unireg.h b/sql/unireg.h index 0ef69beb08a..5e232becbb2 100644 --- a/sql/unireg.h +++ b/sql/unireg.h @@ -175,11 +175,15 @@ binary value of the 'length' bytes. Older MariaDB servers can ignore values of unknown types if - the type code is less than 128. Otherwise older servers are required + the type code is less than 128 (EXTRA2_ENGINE_IMPORTANT). + Otherwise older (but newer than 10.0.1) servers are required to report an error. */ enum extra2_frm_value_type { EXTRA2_TABLEDEF_VERSION=0, + +#define EXTRA2_ENGINE_IMPORTANT 128 + EXTRA2_ENGINE_TABLEOPTS=128, }; diff --git a/storage/federatedx/ha_federatedx.cc b/storage/federatedx/ha_federatedx.cc index 81b57034e66..2f84cdf5c45 100644 --- a/storage/federatedx/ha_federatedx.cc +++ b/storage/federatedx/ha_federatedx.cc @@ -3622,9 +3622,10 @@ int ha_federatedx::discover_assisted(handlerton *hton, THD* thd, goto err2; query.copy(rdata[1], rlen[1], cs); - query.append(STRING_WITH_LEN(" CONNECTION=\""), cs); - query.append(table_s->connect_string.str, table_s->connect_string.length, cs); - query.append('"'); + query.append(STRING_WITH_LEN(" CONNECTION='"), cs); + query.append_for_single_quote(table_s->connect_string.str, + table_s->connect_string.length); + query.append('\''); error= table_s->init_from_sql_statement_string(thd, true, query.ptr(), query.length()); |