diff options
Diffstat (limited to 'sql')
-rw-r--r-- | sql/field.cc | 22 | ||||
-rw-r--r-- | sql/field.h | 9 | ||||
-rw-r--r-- | sql/sql_lex.cc | 15 | ||||
-rw-r--r-- | sql/sql_show.cc | 126 | ||||
-rw-r--r-- | sql/sql_table.cc | 21 | ||||
-rw-r--r-- | sql/sql_union.cc | 8 |
6 files changed, 94 insertions, 107 deletions
diff --git a/sql/field.cc b/sql/field.cc index 1e926c0926e..4632fbc5c69 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -4075,10 +4075,10 @@ int Field_string::store(const char *from,uint length,CHARSET_INFO *cs) Make sure we don't break a multibyte sequence as well as don't copy a malformed data. */ - copy_length= field_charset->cset->wellformedlen(field_charset, - from,from+length, - field_length/ - field_charset->mbmaxlen); + copy_length= field_charset->cset->well_formed_len(field_charset, + from,from+length, + field_length/ + field_charset->mbmaxlen); memcpy(ptr,from,copy_length); if (copy_length < field_length) // Append spaces if shorter field_charset->cset->fill(field_charset,ptr+copy_length, @@ -4571,11 +4571,15 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs) } copy_length= max_data_length(); - if (copy_length > length) - copy_length= length; - copy_length= field_charset->cset->wellformedlen(field_charset, - from,from+copy_length, - field_length); + /* + copy_length is ok as last argument to well_formed_len as this is never + used to limit the length of the data. The cut of long data is done with + the 'min()' call below. + */ + copy_length= field_charset->cset->well_formed_len(field_charset, + from,from + + min(length, copy_length), + copy_length); if (copy_length < length) set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED); diff --git a/sql/field.h b/sql/field.h index 90e78c5421a..f815324c698 100644 --- a/sql/field.h +++ b/sql/field.h @@ -953,14 +953,9 @@ public: void sort_string(char *buff,uint length); uint32 pack_length() const { return (uint32) (packlength+table->blob_ptr_size); } - uint32 max_data_length() const + inline uint32 max_data_length() const { - switch (packlength) { - case 1: return 255; - case 2: return (uint32) 0xFFFFL; - case 3: return (uint32) 0xFFFFFF; - default: return (uint32) 0xFFFFFFFF; - } + return (uint32) (((ulonglong) 1 << (packlength*8)) -1); } void reset(void) { bzero(ptr, packlength+sizeof(char*)); } void reset_fields() { bzero((char*) &value,sizeof(value)); } diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 5ffe8c1c365..7982bd35f30 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -688,15 +688,15 @@ int yylex(void *arg, void *yythd) yylval->lex_str= get_token(lex,yyLength()); return(result_state); - case MY_LEX_USER_VARIABLE_DELIMITER: + case MY_LEX_USER_VARIABLE_DELIMITER: // Found quote char { uint double_quotes= 0; char quote_char= c; // Used char lex->tok_start=lex->ptr; // Skip first ` while ((c=yyGet())) { - int l; - if ((l= my_mbcharlen(cs, c)) == 1) + int length; + if ((length= my_mbcharlen(cs, c)) == 1) { if (c == (uchar) NAMES_SEP_CHAR) break; /* Old .frm format can't handle this char */ @@ -710,12 +710,9 @@ int yylex(void *arg, void *yythd) } } #ifdef USE_MB - else if (l > 1) - { - lex->ptr += l-1; - } - else - break; + else if (length < 1) + break; // Error + lex->ptr+= length-1; #endif } if (double_quotes) diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 8ed44d618fb..c169ea8952f 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1089,100 +1089,86 @@ mysqld_dump_create_info(THD *thd, TABLE *table, int fd) DBUG_RETURN(0); } -static inline const char *require_quotes(const char *name, uint length) -{ - uint i, d, c; - for (i=0; i<length; i+=d) - { - c=((uchar *)name)[i]; - d=my_mbcharlen(system_charset_info, c); - if (d==1 && !system_charset_info->ident_map[c]) - return name+i; - } - return 0; -} - /* - Looking for char in multibyte string + Go through all character combinations and ensure that sql_lex.cc can + parse it as an identifer. SYNOPSIS - look_for_char() - name string for looking at - length length of name - q '\'' or '\"' for looking for - - RETURN VALUES - # pointer to found char in string - 0 string doesn't contain required char + require_quotes() + name attribute name + name_length length of name + + RETURN + # Pointer to conflicting character + 0 No conflicting character */ -static inline const char *look_for_char(const char *name, - uint length, char q) +static const char *require_quotes(const char *name, uint name_length) { - const char *cur= name; - const char *end= cur+length; - uint symbol_length; - for (; cur<end; cur+= symbol_length) + uint length; + const char *end= name + name_length; + + for ( ; name < end ; name++) { - char c= *cur; - symbol_length= my_mbcharlen(system_charset_info, c); - if (symbol_length==1 && c==q) - return cur; + uchar chr= (uchar) *name; + length= my_mbcharlen(system_charset_info, chr); + if (length == 1 && !system_charset_info->ident_map[chr]) + return name; } return 0; } + +static void append_quoted_simple_identifier(String *packet, char quote_char, + const char *name, uint length) +{ + packet->append("e_char, 1, system_charset_info); + packet->append(name, length, system_charset_info); + packet->append("e_char, 1, system_charset_info); +} + + void append_identifier(THD *thd, String *packet, const char *name, uint length) { - char qtype; + const char *name_end; + char quote_char; uint part_len; - const char *qplace; + if (thd->variables.sql_mode & MODE_ANSI_QUOTES) - qtype= '\"'; + quote_char= '\"'; else - qtype= '`'; + quote_char= '`'; if (is_keyword(name,length)) { - packet->append(&qtype, 1, system_charset_info); - packet->append(name, length, system_charset_info); - packet->append(&qtype, 1, system_charset_info); + append_quoted_simple_identifier(packet, quote_char, name, length); + return; } - else + + if (!require_quotes(name, length)) { - if (!(qplace= require_quotes(name, length))) - { - if (!(thd->options & OPTION_QUOTE_SHOW_CREATE)) - packet->append(name, length, system_charset_info); - else - { - packet->append(&qtype, 1, system_charset_info); - packet->append(name, length, system_charset_info); - packet->append(&qtype, 1, system_charset_info); - } - } - else - { - packet->shrink(packet->length()+length+2); - packet->append(&qtype, 1, system_charset_info); - if (*qplace != qtype) - qplace= look_for_char(qplace+1,length-(qplace-name)-1,qtype); - while (qplace) - { - if ((part_len= qplace-name)) - { - packet->append(name, part_len, system_charset_info); - length-= part_len; - } - packet->append(qplace, 1, system_charset_info); - name= qplace; - qplace= look_for_char(name+1,length-1,qtype); - } + if (!(thd->options & OPTION_QUOTE_SHOW_CREATE)) packet->append(name, length, system_charset_info); - packet->append(&qtype, 1, system_charset_info); - } + else + append_quoted_simple_identifier(packet, quote_char, name, length); + return; + } + + /* The identifier must be quoted as it includes a quote character */ + + packet->reserve(length*2 + 2); + packet->append("e_char, 1, system_charset_info); + + for (name_end= name+length ; name < name_end ; name+= length) + { + char chr= *name; + length= my_mbcharlen(system_charset_info, chr); + if (length == 1 && chr == quote_char) + packet->append("e_char, 1, system_charset_info); + packet->append(name, length, packet->charset()); } + packet->append("e_char, 1, system_charset_info); } diff --git a/sql/sql_table.cc b/sql/sql_table.cc index fb86e446fb7..8d1d64e9491 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1868,20 +1868,17 @@ int mysql_create_like_table(THD* thd, TABLE_LIST* table, table_name); /* purecov: inspected */ DBUG_RETURN(-1); /* purecov: inspected */ } - else + + // Must be written before unlock + mysql_update_log.write(thd,thd->query, thd->query_length); + if (mysql_bin_log.is_open()) { - // Must be written before unlock - mysql_update_log.write(thd,thd->query, thd->query_length); - if (mysql_bin_log.is_open()) - { - thd->clear_error(); - Query_log_event qinfo(thd, thd->query, thd->query_length, - test(create_info->options & - HA_LEX_CREATE_TMP_TABLE)); - mysql_bin_log.write(&qinfo); - } + thd->clear_error(); + Query_log_event qinfo(thd, thd->query, thd->query_length, + test(create_info->options & + HA_LEX_CREATE_TMP_TABLE)); + mysql_bin_log.write(&qinfo); } - DBUG_RETURN(0); table_exists: diff --git a/sql/sql_union.cc b/sql/sql_union.cc index f2e9016aec3..dc372bcd0b5 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -331,6 +331,14 @@ int st_select_lex_unit::exec() */ setup_table_map(table_list->table, table_list, tablenr); } + /* + Mark that we are using all fields in the table. This is needed + for InnoDB when using the same table but different fields in + an UNION + QQ: Replace query_id with a bit map of used fields and + change this for each union part. After this change, + this code can be removed. + */ for (unsigned int i=0; i < table_list->table->fields; i++) table_list->table->field[i]->query_id= query_id; } |