summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/field.cc22
-rw-r--r--sql/field.h9
-rw-r--r--sql/sql_lex.cc15
-rw-r--r--sql/sql_show.cc126
-rw-r--r--sql/sql_table.cc21
-rw-r--r--sql/sql_union.cc8
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(&quote_char, 1, system_charset_info);
+ packet->append(name, length, system_charset_info);
+ packet->append(&quote_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(&quote_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(&quote_char, 1, system_charset_info);
+ packet->append(name, length, packet->charset());
}
+ packet->append(&quote_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;
}