diff options
-rw-r--r-- | client/sql_string.cc | 649 | ||||
-rw-r--r-- | client/sql_string.h | 125 | ||||
-rw-r--r-- | mysql-test/r/federated.result | 6 | ||||
-rw-r--r-- | sql/field.cc | 38 | ||||
-rw-r--r-- | sql/field.h | 2 | ||||
-rw-r--r-- | sql/ha_federated.cc | 2 | ||||
-rw-r--r-- | sql/handler.cc | 2 | ||||
-rw-r--r-- | sql/item_func.cc | 8 | ||||
-rw-r--r-- | sql/item_sum.cc | 4 | ||||
-rw-r--r-- | sql/lock.cc | 2 | ||||
-rw-r--r-- | sql/log_event.cc | 2 | ||||
-rw-r--r-- | sql/mysql_priv.h | 33 | ||||
-rw-r--r-- | sql/opt_range.cc | 6 | ||||
-rw-r--r-- | sql/sql_base.cc | 6 | ||||
-rw-r--r-- | sql/sql_delete.cc | 2 | ||||
-rw-r--r-- | sql/sql_error.cc | 5 | ||||
-rw-r--r-- | sql/sql_help.cc | 2 | ||||
-rw-r--r-- | sql/sql_parse.cc | 17 | ||||
-rw-r--r-- | sql/sql_prepare.cc | 2 | ||||
-rw-r--r-- | sql/sql_rename.cc | 2 | ||||
-rw-r--r-- | sql/sql_select.cc | 9 | ||||
-rw-r--r-- | sql/sql_show.cc | 17 | ||||
-rw-r--r-- | sql/sql_string.cc | 12 | ||||
-rw-r--r-- | sql/sql_table.cc | 282 | ||||
-rw-r--r-- | sql/sql_update.cc | 2 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 16 |
26 files changed, 787 insertions, 466 deletions
diff --git a/client/sql_string.cc b/client/sql_string.cc index 9dcf19dad1d..0424723d97f 100644 --- a/client/sql_string.cc +++ b/client/sql_string.cc @@ -28,6 +28,11 @@ #include <floatingpoint.h> #endif +/* + The following extern declarations are ok as these are interface functions + required by the string function +*/ + extern gptr sql_alloc(unsigned size); extern void sql_element_free(void *ptr); @@ -97,14 +102,7 @@ bool String::set(longlong num, CHARSET_INFO *cs) if (alloc(l)) return TRUE; - if (cs->cset->snprintf == my_snprintf_8bit) - { - str_length=(uint32) (longlong10_to_str(num,Ptr,-10)-Ptr); - } - else - { - str_length=cs->cset->snprintf(cs,Ptr,l,"%d",num); - } + str_length=(uint32) (cs->cset->longlong10_to_str)(cs,Ptr,l,-10,num); str_charset=cs; return FALSE; } @@ -115,14 +113,7 @@ bool String::set(ulonglong num, CHARSET_INFO *cs) if (alloc(l)) return TRUE; - if (cs->cset->snprintf == my_snprintf_8bit) - { - str_length=(uint32) (longlong10_to_str(num,Ptr,10)-Ptr); - } - else - { - str_length=cs->cset->snprintf(cs,Ptr,l,"%d",num); - } + str_length=(uint32) (cs->cset->longlong10_to_str)(cs,Ptr,l,10,num); str_charset=cs; return FALSE; } @@ -130,12 +121,13 @@ bool String::set(ulonglong num, CHARSET_INFO *cs) bool String::set(double num,uint decimals, CHARSET_INFO *cs) { char buff[331]; + uint dummy_errors; str_charset=cs; if (decimals >= NOT_FIXED_DEC) { - sprintf(buff,"%.14g",num); // Enough for a DATETIME - return copy(buff, (uint32) strlen(buff), &my_charset_latin1, cs); + uint32 len= my_sprintf(buff,(buff, "%.14g",num));// Enough for a DATETIME + return copy(buff, len, &my_charset_latin1, cs, &dummy_errors); } #ifdef HAVE_FCONVERT int decpt,sign; @@ -150,7 +142,8 @@ bool String::set(double num,uint decimals, CHARSET_INFO *cs) buff[0]='-'; pos=buff; } - return copy(pos,(uint32) strlen(pos), &my_charset_latin1, cs); + uint dummy_errors; + return copy(pos,(uint32) strlen(pos), &my_charset_latin1, cs, &dummy_errors); } if (alloc((uint32) ((uint32) decpt+3+decimals))) return TRUE; @@ -200,7 +193,8 @@ end: #else sprintf(buff,"%.*f",(int) decimals,num); #endif - return copy(buff,(uint32) strlen(buff), &my_charset_latin1, cs); + return copy(buff,(uint32) strlen(buff), &my_charset_latin1, cs, + &dummy_errors); #endif } @@ -237,55 +231,163 @@ bool String::copy(const char *str,uint32 arg_length, CHARSET_INFO *cs) return FALSE; } -/* Copy with charset convertion */ -bool String::copy(const char *str,uint32 arg_length, CHARSET_INFO *from, CHARSET_INFO *to) + +/* + Checks that the source string can be just copied to the destination string + without conversion. + + SYNPOSIS + + needs_conversion() + arg_length Length of string to copy. + from_cs Character set to copy from + to_cs Character set to copy to + uint32 *offset Returns number of unaligned characters. + + RETURN + 0 No conversion needed + 1 Either character set conversion or adding leading zeros + (e.g. for UCS-2) must be done +*/ + +bool String::needs_conversion(uint32 arg_length, + CHARSET_INFO *from_cs, + CHARSET_INFO *to_cs, + uint32 *offset) +{ + *offset= 0; + if ((to_cs == &my_charset_bin) || + (to_cs == from_cs) || + my_charset_same(from_cs, to_cs) || + ((from_cs == &my_charset_bin) && + (!(*offset=(arg_length % to_cs->mbminlen))))) + return FALSE; + return TRUE; +} + + +/* + Copy a multi-byte character sets with adding leading zeros. + + SYNOPSIS + + copy_aligned() + str String to copy + arg_length Length of string. This should NOT be dividable with + cs->mbminlen. + offset arg_length % cs->mb_minlength + cs Character set for 'str' + + NOTES + For real multi-byte, ascii incompatible charactser sets, + like UCS-2, add leading zeros if we have an incomplete character. + Thus, + SELECT _ucs2 0xAA + will automatically be converted into + SELECT _ucs2 0x00AA + + RETURN + 0 ok + 1 error +*/ + +bool String::copy_aligned(const char *str,uint32 arg_length, uint32 offset, + CHARSET_INFO *cs) { - uint32 new_length=to->mbmaxlen*arg_length; - int cnvres; - my_wc_t wc; - const uchar *s=(const uchar *)str; - const uchar *se=s+arg_length; - uchar *d, *de; + /* How many bytes are in incomplete character */ + offset= cs->mbmaxlen - offset; /* How many zeros we should prepend */ + DBUG_ASSERT(offset && offset != cs->mbmaxlen); - if (alloc(new_length)) + uint32 aligned_length= arg_length + offset; + if (alloc(aligned_length)) return TRUE; + + /* + Note, this is only safe for little-endian UCS-2. + If we add big-endian UCS-2 sometimes, this code + will be more complicated. But it's OK for now. + */ + bzero((char*) Ptr, offset); + memcpy(Ptr + offset, str, arg_length); + Ptr[aligned_length]=0; + /* str_length is always >= 0 as arg_length is != 0 */ + str_length= aligned_length; + str_charset= cs; + return FALSE; +} + - d=(uchar *)Ptr; - de=d+new_length; +bool String::set_or_copy_aligned(const char *str,uint32 arg_length, + CHARSET_INFO *cs) +{ + /* How many bytes are in incomplete character */ + uint32 offset= (arg_length % cs->mbminlen); - for (str_length=new_length ; s < se && d < de ; ) + if (!offset) /* All characters are complete, just copy */ { - if ((cnvres=from->cset->mb_wc(from,&wc,s,se)) > 0 ) - { - s+=cnvres; - } - else if (cnvres==MY_CS_ILSEQ) - { - s++; - wc='?'; - } - else - break; + set(str, arg_length, cs); + return FALSE; + } + return copy_aligned(str, arg_length, offset, cs); +} -outp: - if((cnvres=to->cset->wc_mb(to,wc,d,de)) >0 ) - { - d+=cnvres; - } - else if (cnvres==MY_CS_ILUNI && wc!='?') - { - wc='?'; - goto outp; - } - else - break; + /* Copy with charset convertion */ + +bool String::copy(const char *str, uint32 arg_length, + CHARSET_INFO *from_cs, CHARSET_INFO *to_cs, uint *errors) +{ + uint32 offset; + if (!needs_conversion(arg_length, from_cs, to_cs, &offset)) + { + *errors= 0; + return copy(str, arg_length, to_cs); + } + if ((from_cs == &my_charset_bin) && offset) + { + *errors= 0; + return copy_aligned(str, arg_length, offset, to_cs); } - Ptr[new_length]=0; - length((uint32) (d-(uchar *)Ptr)); - str_charset=to; + uint32 new_length= to_cs->mbmaxlen*arg_length; + if (alloc(new_length)) + return TRUE; + str_length=copy_and_convert((char*) Ptr, new_length, to_cs, + str, arg_length, from_cs, errors); + str_charset=to_cs; return FALSE; } + +/* + Set a string to the value of a latin1-string, keeping the original charset + + SYNOPSIS + copy_or_set() + str String of a simple charset (latin1) + arg_length Length of string + + IMPLEMENTATION + If string object is of a simple character set, set it to point to the + given string. + If not, make a copy and convert it to the new character set. + + RETURN + 0 ok + 1 Could not allocate result buffer + +*/ + +bool String::set_ascii(const char *str, uint32 arg_length) +{ + if (str_charset->mbminlen == 1) + { + set(str, arg_length, str_charset); + return 0; + } + uint dummy_errors; + return copy(str, arg_length, &my_charset_latin1, str_charset, &dummy_errors); +} + + /* This is used by mysql.cc */ bool String::fill(uint32 max_length,char fill_char) @@ -320,11 +422,34 @@ bool String::append(const String &s) return FALSE; } + +/* + Append an ASCII string to the a string of the current character set +*/ + bool String::append(const char *s,uint32 arg_length) { - if (!arg_length) // Default argument - if (!(arg_length= (uint32) strlen(s))) - return FALSE; + if (!arg_length) + return FALSE; + + /* + For an ASCII incompatible string, e.g. UCS-2, we need to convert + */ + if (str_charset->mbminlen > 1) + { + uint32 add_length=arg_length * str_charset->mbmaxlen; + uint dummy_errors; + if (realloc(str_length+ add_length)) + return TRUE; + str_length+= copy_and_convert(Ptr+str_length, add_length, str_charset, + s, arg_length, &my_charset_latin1, + &dummy_errors); + return FALSE; + } + + /* + For an ASCII compatinble string we can just append. + */ if (realloc(str_length+arg_length)) return TRUE; memcpy(Ptr+str_length,s,arg_length); @@ -332,6 +457,46 @@ bool String::append(const char *s,uint32 arg_length) return FALSE; } + +/* + Append a 0-terminated ASCII string +*/ + +bool String::append(const char *s) +{ + return append(s, strlen(s)); +} + + +/* + Append a string in the given charset to the string + with character set recoding +*/ + +bool String::append(const char *s,uint32 arg_length, CHARSET_INFO *cs) +{ + uint32 dummy_offset; + + if (needs_conversion(arg_length, cs, str_charset, &dummy_offset)) + { + uint32 add_length= arg_length / cs->mbminlen * str_charset->mbmaxlen; + uint dummy_errors; + if (realloc(str_length + add_length)) + return TRUE; + str_length+= copy_and_convert(Ptr+str_length, add_length, str_charset, + s, arg_length, cs, &dummy_errors); + } + else + { + if (realloc(str_length + arg_length)) + return TRUE; + memcpy(Ptr + str_length, s, arg_length); + str_length+= arg_length; + } + return FALSE; +} + + #ifdef TO_BE_REMOVED bool String::append(FILE* file, uint32 arg_length, myf my_flags) { @@ -360,48 +525,33 @@ bool String::append(IO_CACHE* file, uint32 arg_length) return FALSE; } -uint32 String::numchars() +bool String::append_with_prefill(const char *s,uint32 arg_length, + uint32 full_length, char fill_char) { -#ifdef USE_MB - register uint32 n=0,mblen; - register const char *mbstr=Ptr; - register const char *end=mbstr+str_length; - if (use_mb(str_charset)) + int t_length= arg_length > full_length ? arg_length : full_length; + + if (realloc(str_length + t_length)) + return TRUE; + t_length= full_length - arg_length; + if (t_length > 0) { - while (mbstr < end) { - if ((mblen=my_ismbchar(str_charset, mbstr,end))) mbstr+=mblen; - else ++mbstr; - ++n; - } - return n; + bfill(Ptr+str_length, t_length, fill_char); + str_length=str_length + t_length; } - else -#endif - return str_length; + append(s, arg_length); + return FALSE; +} + +uint32 String::numchars() +{ + return str_charset->cset->numchars(str_charset, Ptr, Ptr+str_length); } int String::charpos(int i,uint32 offset) { -#ifdef USE_MB - register uint32 mblen; - register const char *mbstr=Ptr+offset; - register const char *end=Ptr+str_length; - if (use_mb(str_charset)) - { - if (i<=0) return i; - while (i && mbstr < end) { - if ((mblen=my_ismbchar(str_charset, mbstr,end))) mbstr+=mblen; - else ++mbstr; - --i; - } - if ( INT_MAX32-i <= (int) (mbstr-Ptr-offset)) - return INT_MAX32; - else - return (int) ((mbstr-Ptr-offset)+i); - } - else -#endif + if (i <= 0) return i; + return str_charset->cset->charpos(str_charset,Ptr+offset,Ptr+str_length,i); } int String::strstr(const String &s,uint32 offset) @@ -432,40 +582,6 @@ skip: } /* - Search after a string without regarding to case - This needs to be replaced when we have character sets per string -*/ - -int String::strstr_case(const String &s,uint32 offset) -{ - if (s.length()+offset <= str_length) - { - if (!s.length()) - return ((int) offset); // Empty string is always found - - register const char *str = Ptr+offset; - register const char *search=s.ptr(); - const char *end=Ptr+str_length-s.length()+1; - const char *search_end=s.ptr()+s.length(); -skip: - while (str != end) - { - if (str_charset->sort_order[*str++] == str_charset->sort_order[*search]) - { - register char *i,*j; - i=(char*) str; j=(char*) search+1; - while (j != search_end) - if (str_charset->sort_order[*i++] != - str_charset->sort_order[*j++]) - goto skip; - return (int) (str-Ptr) -1; - } - } - } - return -1; -} - -/* ** Search string from end. Offset is offset to the end of string */ @@ -504,14 +620,20 @@ skip: bool String::replace(uint32 offset,uint32 arg_length,const String &to) { - long diff = (long) to.length()-(long) arg_length; + return replace(offset,arg_length,to.ptr(),to.length()); +} + +bool String::replace(uint32 offset,uint32 arg_length, + const char *to,uint32 length) +{ + long diff = (long) length-(long) arg_length; if (offset+arg_length <= str_length) { if (diff < 0) { - if (to.length()) - memcpy(Ptr+offset,to.ptr(),to.length()); - bmove(Ptr+offset+to.length(),Ptr+offset+arg_length, + if (length) + memcpy(Ptr+offset,to,length); + bmove(Ptr+offset+length,Ptr+offset+arg_length, str_length-offset-arg_length); } else @@ -523,14 +645,15 @@ bool String::replace(uint32 offset,uint32 arg_length,const String &to) bmove_upp(Ptr+str_length+diff,Ptr+str_length, str_length-offset-arg_length); } - if (to.length()) - memcpy(Ptr+offset,to.ptr(),to.length()); + if (length) + memcpy(Ptr+offset,to,length); } str_length+=(uint32) diff; } return FALSE; } + // added by Holyfoot for "geometry" needs int String::reserve(uint32 space_needed, uint32 grow_by) { @@ -542,9 +665,8 @@ int String::reserve(uint32 space_needed, uint32 grow_by) return FALSE; } -void String::qs_append(const char *str) +void String::qs_append(const char *str, uint32 len) { - int len = (int)strlen(str); memcpy(Ptr + str_length, str, len + 1); str_length += len; } @@ -552,8 +674,7 @@ void String::qs_append(const char *str) void String::qs_append(double d) { char *buff = Ptr + str_length; - sprintf(buff,"%.14g", d); - str_length += (int)strlen(buff); + str_length+= my_sprintf(buff, (buff, "%.14g", d)); } void String::qs_append(double *d) @@ -563,90 +684,70 @@ void String::qs_append(double *d) qs_append(ld); } -void String::qs_append(const char &c) +void String::qs_append(int i) { - Ptr[str_length] = c; - str_length += sizeof(c); + char *buff= Ptr + str_length; + char *end= int10_to_str(i, buff, -10); + str_length+= (int) (end-buff); } - -int sortcmp(const String *x,const String *y) +void String::qs_append(uint i) { - const char *s= x->ptr(); - const char *t= y->ptr(); - uint32 x_len=x->length(),y_len=y->length(),len=min(x_len,y_len); - - if (use_strnxfrm(x->str_charset)) - { -#ifndef CMP_ENDSPACE - while (x_len && my_isspace(x->str_charset,s[x_len-1])) - x_len--; - while (y_len && my_isspace(x->str_charset,t[y_len-1])) - y_len--; -#endif - return my_strnncoll(x->str_charset, - (unsigned char *)s,x_len,(unsigned char *)t,y_len); - } - else - { - x_len-=len; // For easy end space test - y_len-=len; - if (x->str_charset->sort_order) - { - while (len--) - { - if (x->str_charset->sort_order[(uchar) *s++] != - x->str_charset->sort_order[(uchar) *t++]) - return ((int) x->str_charset->sort_order[(uchar) s[-1]] - - (int) x->str_charset->sort_order[(uchar) t[-1]]); - } - } - else - { - while (len--) - { - if (*s++ != *t++) - return ((int) s[-1] - (int) t[-1]); - } - } -#ifndef CMP_ENDSPACE - /* Don't compare end space in strings */ - { - if (y_len) - { - const char *end=t+y_len; - for (; t != end ; t++) - if (!my_isspace(x->str_charset,*t)) - return -1; - } - else - { - const char *end=s+x_len; - for (; s != end ; s++) - if (!my_isspace(x->str_charset,*s)) - return 1; - } - return 0; - } -#else - return (int) (x_len-y_len); -#endif /* CMP_ENDSPACE */ - } + char *buff= Ptr + str_length; + char *end= int10_to_str(i, buff, 10); + str_length+= (int) (end-buff); } +/* + Compare strings according to collation, without end space. + + SYNOPSIS + sortcmp() + s First string + t Second string + cs Collation + + NOTE: + Normally this is case sensitive comparison -int stringcmp(const String *x,const String *y) + RETURN + < 0 s < t + 0 s == t + > 0 s > t +*/ + + +int sortcmp(const String *s,const String *t, CHARSET_INFO *cs) { - const char *s= x->ptr(); - const char *t= y->ptr(); - uint32 x_len=x->length(),y_len=y->length(),len=min(x_len,y_len); + return cs->coll->strnncollsp(cs, + (unsigned char *) s->ptr(),s->length(), + (unsigned char *) t->ptr(),t->length(), 0); +} - while (len--) - { - if (*s++ != *t++) - return ((int) (uchar) s[-1] - (int) (uchar) t[-1]); - } - return (int) (x_len-y_len); + +/* + Compare strings byte by byte. End spaces are also compared. + + SYNOPSIS + stringcmp() + s First string + t Second string + + NOTE: + Strings are compared as a stream of unsigned chars + + RETURN + < 0 s < t + 0 s == t + > 0 s > t +*/ + + +int stringcmp(const String *s,const String *t) +{ + uint32 s_len=s->length(),t_len=t->length(),len=min(s_len,t_len); + int cmp= memcmp(s->ptr(), t->ptr(), len); + return (cmp) ? cmp : (int) (s_len - t_len); } @@ -668,4 +769,124 @@ String *copy_if_not_alloced(String *to,String *from,uint32 from_length) } +/**************************************************************************** + Help functions +****************************************************************************/ +/* + copy a string from one character set to another + + SYNOPSIS + copy_and_convert() + to Store result here + to_cs Character set of result string + from Copy from here + from_length Length of from string + from_cs From character set + + NOTES + 'to' must be big enough as form_length * to_cs->mbmaxlen + + RETURN + length of bytes copied to 'to' +*/ + + +uint32 +copy_and_convert(char *to, uint32 to_length, CHARSET_INFO *to_cs, + const char *from, uint32 from_length, CHARSET_INFO *from_cs, + uint *errors) +{ + int cnvres; + my_wc_t wc; + const uchar *from_end= (const uchar*) from+from_length; + char *to_start= to; + uchar *to_end= (uchar*) to+to_length; + int (*mb_wc)(struct charset_info_st *, my_wc_t *, const uchar *, + const uchar *) = from_cs->cset->mb_wc; + int (*wc_mb)(struct charset_info_st *, my_wc_t, uchar *s, uchar *e)= + to_cs->cset->wc_mb; + uint error_count= 0; + + while (1) + { + if ((cnvres= (*mb_wc)(from_cs, &wc, (uchar*) from, + from_end)) > 0) + from+= cnvres; + else if (cnvres == MY_CS_ILSEQ) + { + error_count++; + from++; + wc= '?'; + } + else + break; // Impossible char. + +outp: + if ((cnvres= (*wc_mb)(to_cs, wc, (uchar*) to, to_end)) > 0) + to+= cnvres; + else if (cnvres == MY_CS_ILUNI && wc != '?') + { + error_count++; + wc= '?'; + goto outp; + } + else + break; + } + *errors= error_count; + return (uint32) (to - to_start); +} + + +void String::print(String *str) +{ + char *st= (char*)Ptr, *end= st+str_length; + for (; st < end; st++) + { + uchar c= *st; + switch (c) + { + case '\\': + str->append("\\\\", 2); + break; + case '\0': + str->append("\\0", 2); + break; + case '\'': + str->append("\\'", 2); + break; + case '\n': + str->append("\\n", 2); + break; + case '\r': + str->append("\\r", 2); + break; + case 26: //Ctrl-Z + str->append("\\z", 2); + break; + default: + str->append(c); + } + } +} + + +/* + Exchange state of this object and argument. + + SYNOPSIS + String::swap() + + RETURN + Target string will contain state of this object and vice versa. +*/ + +void String::swap(String &s) +{ + swap_variables(char *, Ptr, s.Ptr); + swap_variables(uint32, str_length, s.str_length); + swap_variables(uint32, Alloced_length, s.Alloced_length); + swap_variables(bool, alloced, s.alloced); + swap_variables(CHARSET_INFO*, str_charset, s.str_charset); +} diff --git a/client/sql_string.h b/client/sql_string.h index aec40466d2b..2debeb61787 100644 --- a/client/sql_string.h +++ b/client/sql_string.h @@ -25,9 +25,11 @@ #endif class String; -int sortcmp(const String *a,const String *b); -int stringcmp(const String *a,const String *b); +int sortcmp(const String *a,const String *b, CHARSET_INFO *cs); String *copy_if_not_alloced(String *a,String *b,uint32 arg_length); +uint32 copy_and_convert(char *to, uint32 to_length, CHARSET_INFO *to_cs, + const char *from, uint32 from_length, + CHARSET_INFO *from_cs, uint *errors); class String { @@ -39,12 +41,12 @@ public: String() { Ptr=0; str_length=Alloced_length=0; alloced=0; - str_charset= &my_charset_latin1; + str_charset= &my_charset_bin; } String(uint32 length_arg) { alloced=0; Alloced_length=0; (void) real_alloc(length_arg); - str_charset= &my_charset_latin1; + str_charset= &my_charset_bin; } String(const char *str, CHARSET_INFO *cs) { @@ -67,12 +69,15 @@ public: Alloced_length=str.Alloced_length; alloced=0; str_charset=str.str_charset; } - static void *operator new(size_t size) { return (void*) sql_alloc((uint) size); } - static void operator delete(void *ptr_arg,size_t size) /*lint -e715 */ - { sql_element_free(ptr_arg); } + static void *operator new(size_t size, MEM_ROOT *mem_root) + { return (void*) alloc_root(mem_root, (uint) size); } + static void operator delete(void *ptr_arg,size_t size) + { TRASH(ptr_arg, size); } + static void operator delete(void *ptr_arg, MEM_ROOT *mem_root) + { /* never called */ } ~String() { free(); } - inline void set_charset(CHARSET_INFO *charset) { str_charset=charset; } + inline void set_charset(CHARSET_INFO *charset) { str_charset= charset; } inline CHARSET_INFO *charset() const { return str_charset; } inline uint32 length() const { return str_length;} inline uint32 alloced_length() const { return Alloced_length;} @@ -103,6 +108,7 @@ public: void set(String &str,uint32 offset,uint32 arg_length) { + DBUG_ASSERT(&str != this); free(); Ptr=(char*) str.ptr()+offset; str_length=arg_length; alloced=0; if (str.Alloced_length) @@ -123,6 +129,7 @@ public: Ptr=(char*) str; str_length=arg_length; Alloced_length=0 ; alloced=0; str_charset=cs; } + bool set_ascii(const char *str, uint32 arg_length); inline void set_quick(char *str,uint32 arg_length, CHARSET_INFO *cs) { if (!alloced) @@ -134,6 +141,34 @@ public: bool set(longlong num, CHARSET_INFO *cs); bool set(ulonglong num, CHARSET_INFO *cs); bool set(double num,uint decimals, CHARSET_INFO *cs); + + /* + PMG 2004.11.12 + This is a method that works the same as perl's "chop". It simply + drops the last character of a string. This is useful in the case + of the federated storage handler where I'm building a unknown + number, list of values and fields to be used in a sql insert + statement to be run on the remote server, and have a comma after each. + When the list is complete, I "chop" off the trailing comma + + ex. + String stringobj; + stringobj.append("VALUES ('foo', 'fi', 'fo',"); + stringobj.chop(); + stringobj.append(")"); + + In this case, the value of string was: + + VALUES ('foo', 'fi', 'fo', + VALUES ('foo', 'fi', 'fo' + VALUES ('foo', 'fi', 'fo') + + */ + inline void chop() + { + Ptr[str_length--]= '\0'; + } + inline void free() { if (alloced) @@ -175,6 +210,11 @@ public: { if (&s != this) { + /* + It is forbidden to do assignments like + some_string = substring_of_that_string + */ + DBUG_ASSERT(!s.uses_buffer_owned_by(this)); free(); Ptr=s.Ptr ; str_length=s.str_length ; Alloced_length=s.Alloced_length; alloced=0; @@ -185,13 +225,24 @@ public: bool copy(); // Alloc string if not alloced bool copy(const String &s); // Allocate new string bool copy(const char *s,uint32 arg_length, CHARSET_INFO *cs); // Allocate new string - bool copy(const char*s,uint32 arg_length, CHARSET_INFO *csfrom, CHARSET_INFO *csto); + static bool needs_conversion(uint32 arg_length, + CHARSET_INFO *cs_from, CHARSET_INFO *cs_to, + uint32 *offset); + bool copy_aligned(const char *s, uint32 arg_length, uint32 offset, + CHARSET_INFO *cs); + bool set_or_copy_aligned(const char *s, uint32 arg_length, CHARSET_INFO *cs); + bool copy(const char*s,uint32 arg_length, CHARSET_INFO *csfrom, + CHARSET_INFO *csto, uint *errors); bool append(const String &s); - bool append(const char *s,uint32 arg_length=0); + bool append(const char *s); + bool append(const char *s,uint32 arg_length); + bool append(const char *s,uint32 arg_length, CHARSET_INFO *cs); bool append(IO_CACHE* file, uint32 arg_length); + bool append_with_prefill(const char *s, uint32 arg_length, + uint32 full_length, char fill_char); int strstr(const String &search,uint32 offset=0); // Returns offset to substring or -1 - int strstr_case(const String &s,uint32 offset=0); int strrstr(const String &search,uint32 offset=0); // Returns offset to substring or -1 + bool replace(uint32 offset,uint32 arg_length,const char *to,uint32 length); bool replace(uint32 offset,uint32 arg_length,const String &to); inline bool append(char chr) { @@ -211,7 +262,7 @@ public: void strip_sp(); inline void caseup() { my_caseup(str_charset,Ptr,str_length); } inline void casedn() { my_casedn(str_charset,Ptr,str_length); } - friend int sortcmp(const String *a,const String *b); + friend int sortcmp(const String *a,const String *b, CHARSET_INFO *cs); friend int stringcmp(const String *a,const String *b); friend String *copy_if_not_alloced(String *a,String *b,uint32 arg_length); uint32 numchars(); @@ -228,11 +279,11 @@ public: q_*** methods writes values of parameters itself qs_*** methods writes string representation of value */ - void q_append(const char &c) + void q_append(const char c) { Ptr[str_length++] = c; } - void q_append(const uint32 &n) + void q_append(const uint32 n) { int4store(Ptr + str_length, n); str_length += 4; @@ -253,13 +304,53 @@ public: str_length += data_len; } - void WriteAtPosition(int position, uint32 value) + void write_at_position(int position, uint32 value) { int4store(Ptr + position,value); } - void qs_append(const char *str); + void qs_append(const char *str, uint32 len); void qs_append(double d); void qs_append(double *d); - void qs_append(const char &c); + inline void qs_append(const char c) + { + Ptr[str_length]= c; + str_length++; + } + void qs_append(int i); + void qs_append(uint i); + + /* Inline (general) functions used by the protocol functions */ + + inline char *prep_append(uint32 arg_length, uint32 step_alloc) + { + uint32 new_length= arg_length + str_length; + if (new_length > Alloced_length) + { + if (realloc(new_length + step_alloc)) + return 0; + } + uint32 old_length= str_length; + str_length+= arg_length; + return Ptr+ old_length; /* Area to use */ + } + + inline bool append(const char *s, uint32 arg_length, uint32 step_alloc) + { + uint32 new_length= arg_length + str_length; + if (new_length > Alloced_length && realloc(new_length + step_alloc)) + return TRUE; + memcpy(Ptr+str_length, s, arg_length); + str_length+= arg_length; + return FALSE; + } + void print(String *print); + + /* Swap two string objects. Efficient way to exchange data without memcpy. */ + void swap(String &s); + + inline bool uses_buffer_owned_by(const String *s) const + { + return (s->alloced && Ptr >= s->Ptr && Ptr < s->Ptr + s->str_length); + } }; diff --git a/mysql-test/r/federated.result b/mysql-test/r/federated.result index 9c524dd7264..1d24707034b 100644 --- a/mysql-test/r/federated.result +++ b/mysql-test/r/federated.result @@ -20,16 +20,14 @@ CREATE TABLE federated.t1 ( ) ENGINE="FEDERATED" DEFAULT CHARSET=latin1 COMMENT='mysql://root@127.0.0.1:@/too/many/items/federated/t1'; -ERROR HY000: Can't create table 'this connection string is not in the correct format! -' (errno: 0) +ERROR HY000: Can't create table 'connection string is not in the correct format' (errno: 0) CREATE TABLE federated.t1 ( `id` int(20) NOT NULL, `name` varchar(32) NOT NULL default '' ) ENGINE="FEDERATED" DEFAULT CHARSET=latin1 COMMENT='mysql://root@127.0.0.1'; -ERROR HY000: Can't create table 'this connection string is not in the correct format! -' (errno: 0) +ERROR HY000: Can't create table 'connection string is not in the correct format' (errno: 0) CREATE TABLE federated.t1 ( `id` int(20) NOT NULL, `name` varchar(32) NOT NULL default '' diff --git a/sql/field.cc b/sql/field.cc index 26575d97f69..b6dd00d62a7 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -5328,11 +5328,11 @@ Field *Field_string::new_field(MEM_ROOT *root, struct st_table *new_table) int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs) { - int error= 0; uint32 not_used, copy_length; char buff[STRING_BUFFER_USUAL_SIZE]; String tmpstr(buff,sizeof(buff), &my_charset_bin); - bool lost_only_spaces= FALSE; + int error_code= 0; + enum MYSQL_ERROR::enum_warning_level level= MYSQL_ERROR::WARN_LEVEL_WARN; /* Convert character set if necessary */ if (String::needs_conversion(length, cs, field_charset, ¬_used)) @@ -5342,7 +5342,7 @@ int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs) from= tmpstr.ptr(); length= tmpstr.length(); if (conv_errors) - error= 1; + error_code= WARN_DATA_TRUNCATED; } /* Make sure we don't break a multibyte sequence @@ -5359,30 +5359,26 @@ int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs) int2store(ptr, copy_length); // Check if we lost something other than just trailing spaces - if ((copy_length < length) && table->in_use->count_cuted_fields) + if ((copy_length < length) && table->in_use->count_cuted_fields && + !error_code) { const char *end= from + length; from+= copy_length; from+= field_charset->cset->scan(field_charset, from, end, MY_SEQ_SPACES); - /* - If we lost only spaces then produce a NOTE, not a WARNING. - But if we have already had errors (e.g with charset conversion), - then don't reset level to NOTE. - */ - if (from == end && !error) - lost_only_spaces= TRUE; - error= 1; + /* If we lost only spaces then produce a NOTE, not a WARNING */ + if (from == end) + level= MYSQL_ERROR::WARN_LEVEL_NOTE; + error_code= WARN_DATA_TRUNCATED; } - if (error) + if (error_code) { - if (lost_only_spaces) - set_warning(MYSQL_ERROR::WARN_LEVEL_NOTE, WARN_DATA_TRUNCATED, 1); - else if (table->in_use->abort_on_warning) - set_warning(MYSQL_ERROR::WARN_LEVEL_ERROR, ER_DATA_TOO_LONG, 1); - else - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1); + if (level == MYSQL_ERROR::WARN_LEVEL_WARN && + table->in_use->abort_on_warning) + error_code= ER_DATA_TOO_LONG; + set_warning(level, error_code, 1); + return 1; } - return error; + return 0; } @@ -7562,7 +7558,7 @@ create_field::create_field(Field *old_field,Field *orig_field) false - otherwise */ bool -Field::set_warning(const uint level, const uint code, int cuted_increment) +Field::set_warning(uint level, uint code, int cuted_increment) { THD *thd= table->in_use; if (thd->count_cuted_fields) diff --git a/sql/field.h b/sql/field.h index 083af27d6d9..5b13ba1042a 100644 --- a/sql/field.h +++ b/sql/field.h @@ -279,7 +279,7 @@ public: virtual CHARSET_INFO *sort_charset(void) const { return charset(); } virtual bool has_charset(void) const { return FALSE; } virtual void set_charset(CHARSET_INFO *charset) { } - bool set_warning(const unsigned int level, const unsigned int code, + bool set_warning(unsigned int level, unsigned int code, int cuted_increment); bool check_int(const char *str, int length, const char *int_end, CHARSET_INFO *cs); diff --git a/sql/ha_federated.cc b/sql/ha_federated.cc index 215a8daf200..25f6e62a9ae 100644 --- a/sql/ha_federated.cc +++ b/sql/ha_federated.cc @@ -662,7 +662,7 @@ static int parse_url(FEDERATED_SHARE *share, TABLE *table, error: my_error(error_num, MYF(0), - "this connection string is not in the correct format!\n"); + "connection string is not in the correct format",0); DBUG_RETURN(1); } diff --git a/sql/handler.cc b/sql/handler.cc index f33f987ef77..20c96849c0f 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -834,7 +834,7 @@ int ha_recover(HASH *commit_list) for now, only InnoDB supports 2pc. It means we can always safely rollback all pending transactions, without risking inconsistent data */ - DBUG_ASSERT(total_ha_2pc == opt_bin_log+1); // only InnoDB and binlog + DBUG_ASSERT(total_ha_2pc == (ulong) opt_bin_log+1); // only InnoDB and binlog tc_heuristic_recover= TC_HEURISTIC_RECOVER_ROLLBACK; // forcing ROLLBACK dry_run=FALSE; #endif diff --git a/sql/item_func.cc b/sql/item_func.cc index 680f3608d0d..bec91f7e90a 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -4370,19 +4370,19 @@ Item_func_sp::Item_func_sp(sp_name *name) { maybe_null= 1; m_name->init_qname(current_thd); - dummy_table= (TABLE *)sql_alloc(sizeof(TABLE)); - bzero(dummy_table, sizeof(TABLE)); + dummy_table= (TABLE*) sql_calloc(sizeof(TABLE)); } + Item_func_sp::Item_func_sp(sp_name *name, List<Item> &list) :Item_func(list), m_name(name), m_sp(NULL) { maybe_null= 1; m_name->init_qname(current_thd); - dummy_table= (TABLE *)sql_alloc(sizeof(TABLE)); - bzero(dummy_table, sizeof(TABLE)); + dummy_table= (TABLE*) sql_calloc(sizeof(TABLE)); } + const char * Item_func_sp::func_name() const { diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 174e2ba4b85..b18653ed5a4 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -727,7 +727,7 @@ Item_sum_avg_distinct::fix_length_and_dec() AVG() will divide val by count. We need to reserve digits after decimal point as the result can be fractional. */ - decimals+= 4; + decimals= min(decimals + 4, NOT_FIXED_DEC); } @@ -927,7 +927,7 @@ void Item_sum_variance::fix_length_and_dec() { DBUG_ENTER("Item_sum_variance::fix_length_and_dec"); maybe_null= null_value= 1; - decimals= args[0]->decimals + 4; + decimals= min(args[0]->decimals + 4, NOT_FIXED_DEC); switch (args[0]->result_type()) { case REAL_RESULT: case STRING_RESULT: diff --git a/sql/lock.cc b/sql/lock.cc index 35b93c79fee..507e802d2e8 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -562,7 +562,7 @@ int lock_table_name(THD *thd, TABLE_LIST *table_list) my_free((gptr) table,MYF(0)); DBUG_RETURN(-1); } - if (remove_table_from_cache(thd, db, table_list->table_name)) + if (remove_table_from_cache(thd, db, table_list->table_name, 0)) DBUG_RETURN(1); // Table is in use DBUG_RETURN(0); } diff --git a/sql/log_event.cc b/sql/log_event.cc index ff7445029d0..e37fb865003 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -2575,7 +2575,7 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli, "data truncated" warning but which is absorbed and never gets to the error log); still we init it to avoid a Valgrind message. */ - mysql_reset_errors(thd); + mysql_reset_errors(thd, 0); TABLE_LIST tables; bzero((char*) &tables,sizeof(tables)); diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 86fc04b3622..229b15adbfc 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -632,10 +632,11 @@ int mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *t); int mysql_derived_filling(THD *thd, LEX *lex, TABLE_LIST *t); Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, Item ***copy_func, Field **from_field, - bool group, bool modify_item, uint convert_blob_length); + bool group, bool modify_item, + uint convert_blob_length); int prepare_create_field(create_field *sql_field, - uint &blob_columns, - int ×tamps, int ×tamps_with_niladic, + uint *blob_columns, + int *timestamps, int *timestamps_with_niladic, uint table_flags); int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, List<create_field> &fields, @@ -661,7 +662,7 @@ bool mysql_alter_table(THD *thd, char *new_db, char *new_name, uint order_num, ORDER *order, enum enum_duplicates handle_duplicates, bool ignore, - ALTER_INFO *alter_info, bool do_send_ok=1); + ALTER_INFO *alter_info, bool do_send_ok); bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list, bool do_send_ok); bool mysql_create_like_table(THD *thd, TABLE_LIST *table, HA_CREATE_INFO *create_info, @@ -705,7 +706,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT* mem, bool *refresh); TABLE *reopen_name_locked_table(THD* thd, TABLE_LIST* table); TABLE *find_locked_table(THD *thd, const char *db,const char *table_name); -bool reopen_table(TABLE *table,bool locked=0); +bool reopen_table(TABLE *table,bool locked); bool reopen_tables(THD *thd,bool get_locks,bool in_refresh); void close_old_data_files(THD *thd, TABLE *table, bool abort_locks, bool send_refresh); @@ -769,7 +770,7 @@ void append_identifier(THD *thd, String *packet, const char *name, uint length); int get_quote_char_for_identifier(THD *thd, const char *name, uint length); void mysqld_list_fields(THD *thd,TABLE_LIST *table, const char *wild); -int mysqld_dump_create_info(THD *thd, TABLE_LIST *table_list, int fd = -1); +int mysqld_dump_create_info(THD *thd, TABLE_LIST *table_list, int fd); bool mysqld_show_create(THD *thd, TABLE_LIST *table_list); bool mysqld_show_create_db(THD *thd, char *dbname, HA_CREATE_INFO *create); @@ -790,7 +791,7 @@ void calc_sum_of_all_status(STATUS_VAR *to); extern LEX_STRING information_schema_name; LEX_STRING *make_lex_string(THD *thd, LEX_STRING *lex_str, const char* str, uint length, - bool allocate_lex_string= 0); + bool allocate_lex_string); ST_SCHEMA_TABLE *find_schema_table(THD *thd, const char* table_name); ST_SCHEMA_TABLE *get_schema_table(enum enum_schema_tables schema_table_idx); int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident, @@ -806,7 +807,7 @@ bool get_schema_tables_result(JOIN *join); /* sql_prepare.cc */ bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length, - LEX_STRING *name=NULL); + LEX_STRING *name); void mysql_stmt_execute(THD *thd, char *packet, uint packet_length); void mysql_sql_stmt_execute(THD *thd, LEX_STRING *stmt_name); void mysql_stmt_fetch(THD *thd, char *packet, uint packet_length); @@ -821,11 +822,11 @@ MYSQL_ERROR *push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level, uint const char *msg); void push_warning_printf(THD *thd, MYSQL_ERROR::enum_warning_level level, uint code, const char *format, ...); -void mysql_reset_errors(THD *thd, bool force= false); +void mysql_reset_errors(THD *thd, bool force); bool mysqld_show_warnings(THD *thd, ulong levels_to_show); /* sql_handler.cc */ -bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen= 0); +bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen); bool mysql_ha_close(THD *thd, TABLE_LIST *tables); bool mysql_ha_read(THD *, TABLE_LIST *,enum enum_ha_read_modes,char *, List<Item> *,enum ha_rkey_function,Item *,ha_rows,ha_rows); @@ -854,15 +855,15 @@ create_field * new_create_field(THD *thd, char *field_name, enum_field_types typ List<String> *interval_list, CHARSET_INFO *cs, uint uint_geom_type); void store_position_for_column(const char *name); -bool add_to_list(THD *thd, SQL_LIST &list,Item *group,bool asc=0); +bool add_to_list(THD *thd, SQL_LIST &list,Item *group,bool asc); void add_join_on(TABLE_LIST *b,Item *expr); void add_join_natural(TABLE_LIST *a,TABLE_LIST *b); bool add_proc_to_list(THD *thd, Item *item); TABLE *unlink_open_table(THD *thd,TABLE *list,TABLE *find); SQL_SELECT *make_select(TABLE *head, table_map const_tables, - table_map read_tables, COND *conds, int *error, - bool allow_null_cond= false); + table_map read_tables, COND *conds, + bool allow_null_cond, int *error); extern Item **not_found_item; Item ** find_item_in_list(Item *item, List<Item> &items, uint *counter, find_item_error_report_type report_error, @@ -905,13 +906,13 @@ TABLE_LIST *find_table_in_list(TABLE_LIST *table, TABLE_LIST *unique_table(TABLE_LIST *table, TABLE_LIST *table_list); TABLE **find_temporary_table(THD *thd, const char *db, const char *table_name); bool close_temporary_table(THD *thd, const char *db, const char *table_name); -void close_temporary(TABLE *table, bool delete_table=1); +void close_temporary(TABLE *table, bool delete_table); bool rename_temporary_table(THD* thd, TABLE *table, const char *new_db, const char *table_name); void remove_db_from_cache(const char *db); void flush_tables(); bool remove_table_from_cache(THD *thd, const char *db, const char *table, - bool return_if_owned_by_thd=0); + bool return_if_owned_by_thd); bool close_cached_tables(THD *thd, bool wait_for_refresh, TABLE_LIST *tables); void copy_field_from_tmp_record(Field *field,int offset); bool fill_record(THD *thd, List<Item> &fields, List<Item> &values, @@ -1170,7 +1171,7 @@ void unlock_table_name(THD *thd, TABLE_LIST *table_list); bool wait_for_locked_table_names(THD *thd, TABLE_LIST *table_list); bool lock_table_names(THD *thd, TABLE_LIST *table_list); void unlock_table_names(THD *thd, TABLE_LIST *table_list, - TABLE_LIST *last_table= 0); + TABLE_LIST *last_table); /* old unireg functions */ diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 812d5a41cbc..fe1780b92a7 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -650,8 +650,10 @@ int imerge_list_or_tree(PARAM *param, */ SQL_SELECT *make_select(TABLE *head, table_map const_tables, - table_map read_tables, COND *conds, int *error, - bool allow_null_cond) + table_map read_tables, COND *conds, + bool allow_null_cond, + int *error) + { SQL_SELECT *select; DBUG_ENTER("make_select"); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 09640eb3f57..4750fe1386f 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -633,7 +633,7 @@ void close_temporary_tables(THD *thd) table->s->table_name,"`,", NullS); } next=table->next; - close_temporary(table); + close_temporary(table, 1); } if (query && found_user_tables && mysql_bin_log.is_open()) { @@ -798,7 +798,7 @@ bool close_temporary_table(THD *thd, const char *db, const char *table_name) return 1; table= *prev; *prev= table->next; - close_temporary(table); + close_temporary(table, 1); if (thd->slave_thread) --slave_open_temp_tables; return 0; @@ -1606,7 +1606,7 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db, if (ha_create_table_from_engine(thd, db, name, TRUE) != 0) goto err; - mysql_reset_errors(thd, true); // Clear warnings + mysql_reset_errors(thd, 1); // Clear warnings thd->clear_error(); // Clear error message continue; } diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index d49d654cb87..642564f5d7a 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -96,7 +96,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, table->used_keys.clear_all(); table->quick_keys.clear_all(); // Can't use 'only index' - select=make_select(table,0,0,conds,&error); + select=make_select(table, 0, 0, conds, 0, &error); if (error) DBUG_RETURN(TRUE); if ((select && select->check_quick(thd, safe_update, limit)) || !limit) diff --git a/sql/sql_error.cc b/sql/sql_error.cc index 4420f2d16ad..281ac7169c0 100644 --- a/sql/sql_error.cc +++ b/sql/sql_error.cc @@ -80,7 +80,8 @@ void mysql_reset_errors(THD *thd, bool force) thd->warn_id= thd->query_id; free_root(&thd->warn_root,MYF(0)); bzero((char*) thd->warn_count, sizeof(thd->warn_count)); - if (force) thd->total_warn_count= 0; + if (force) + thd->total_warn_count= 0; thd->warn_list.empty(); thd->row_count= 1; // by default point to row 1 } @@ -113,7 +114,7 @@ MYSQL_ERROR *push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level, DBUG_RETURN(0); if (thd->query_id != thd->warn_id) - mysql_reset_errors(thd); + mysql_reset_errors(thd, 0); thd->got_warning= 1; if (thd->spcont && thd->spcont->find_handler(code, diff --git a/sql/sql_help.cc b/sql/sql_help.cc index f5490da7e85..fa3e2070a28 100644 --- a/sql/sql_help.cc +++ b/sql/sql_help.cc @@ -562,7 +562,7 @@ SQL_SELECT *prepare_simple_select(THD *thd, Item *cond, TABLE_LIST *tables, /* Assume that no indexes cover all required fields */ table->used_keys.clear_all(); - SQL_SELECT *res= make_select(table,0,0,cond,error); + SQL_SELECT *res= make_select(table, 0, 0, cond, 0, error); if (*error || (res && res->check_quick(thd, 0, HA_POS_ERROR)) || (res->quick && res->quick->reset())) { diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index c1793f0b026..547dc9fd0f8 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1623,7 +1623,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, } case COM_PREPARE: { - mysql_stmt_prepare(thd, packet, packet_length); + mysql_stmt_prepare(thd, packet, packet_length, 0); break; } case COM_CLOSE_STMT: @@ -2261,7 +2261,7 @@ mysql_execute_command(THD *thd) */ if (all_tables || &lex->select_lex != lex->all_selects_list || lex->spfuns.records || lex->spprocs.records) - mysql_reset_errors(thd); + mysql_reset_errors(thd, 0); #ifdef HAVE_REPLICATION if (thd->slave_thread) @@ -2935,7 +2935,8 @@ unsent_create_error: lex->key_list, select_lex->order_list.elements, (ORDER *) select_lex->order_list.first, - lex->duplicates, lex->ignore, &lex->alter_info); + lex->duplicates, lex->ignore, &lex->alter_info, + 1); } break; } @@ -3764,7 +3765,7 @@ unsent_create_error: if (check_db_used(thd, all_tables) || check_table_access(thd, SELECT_ACL, all_tables, 0)) goto error; - res= mysql_ha_open(thd, first_table); + res= mysql_ha_open(thd, first_table, 0); break; case SQLCOM_HA_CLOSE: DBUG_ASSERT(first_table == all_tables && first_table != 0); @@ -4109,7 +4110,7 @@ unsent_create_error: sp= sp_find_procedure(thd, lex->spname); else sp= sp_find_function(thd, lex->spname); - mysql_reset_errors(thd); + mysql_reset_errors(thd, 0); if (! sp) result= SP_KEY_NOT_FOUND; else @@ -4150,7 +4151,7 @@ unsent_create_error: sp= sp_find_procedure(thd, lex->spname); else sp= sp_find_function(thd, lex->spname); - mysql_reset_errors(thd); + mysql_reset_errors(thd, 0); if (sp) { db= thd->strdup(sp->m_db.str); @@ -6491,7 +6492,7 @@ bool mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys) DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->table_name, &create_info, table_list, fields, keys, 0, (ORDER*)0, - DUP_ERROR, 0, &alter_info)); + DUP_ERROR, 0, &alter_info, 1)); } @@ -6509,7 +6510,7 @@ bool mysql_drop_index(THD *thd, TABLE_LIST *table_list, ALTER_INFO *alter_info) DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->table_name, &create_info, table_list, fields, keys, 0, (ORDER*)0, - DUP_ERROR, 0, alter_info)); + DUP_ERROR, 0, alter_info, 1)); } diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 5cd4753c229..7862717bb18 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -1782,7 +1782,7 @@ bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length, thd->current_arena= stmt; mysql_init_query(thd, (uchar *) thd->query, thd->query_length); /* Reset warnings from previous command */ - mysql_reset_errors(thd); + mysql_reset_errors(thd, 0); lex= thd->lex; lex->safe_to_cache_query= 0; diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc index 8bc1891ef1b..8fe17198cf0 100644 --- a/sql/sql_rename.cc +++ b/sql/sql_rename.cc @@ -90,7 +90,7 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list) send_ok(thd); } - unlock_table_names(thd, table_list); + unlock_table_names(thd, table_list, (TABLE_LIST*) 0); err: pthread_mutex_unlock(&LOCK_open); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 162e5b887ab..b970c184489 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -675,8 +675,8 @@ JOIN::optimize() /* Handle the case where we have an OUTER JOIN without a WHERE */ conds=new Item_int((longlong) 1,1); // Always true } - select=make_select(*table, const_table_map, - const_table_map, conds, &error, true); + select= make_select(*table, const_table_map, + const_table_map, conds, 1, &error); if (error) { /* purecov: inspected */ error= -1; /* purecov: inspected */ @@ -2398,7 +2398,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds, select= make_select(s->table, found_const_table_map, found_const_table_map, *s->on_expr_ref ? *s->on_expr_ref : conds, - &error, true); + 1, &error); if (!select) DBUG_RETURN(1); records= get_quick_record_count(join->thd, select, s->table, @@ -12495,7 +12495,8 @@ static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab) error=(int) cond->add(join_tab->select->cond); join_tab->select_cond=join_tab->select->cond=cond; } - else if ((join_tab->select=make_select(join_tab->table, 0, 0, cond,&error))) + else if ((join_tab->select= make_select(join_tab->table, 0, 0, cond, 0, + &error))) join_tab->select_cond=cond; DBUG_RETURN(error ? TRUE : FALSE); diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 293c5f5d275..124ce1805db 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -704,14 +704,17 @@ static void append_directory(THD *thd, String *packet, const char *dir_type, packet->append(dir_type); packet->append(" DIRECTORY='", 12); #ifdef __WIN__ - char *winfilename = thd->memdup(filename, length); - for (uint i=0; i < length; i++) - if (winfilename[i] == '\\') - winfilename[i] = '/'; - packet->append(winfilename, length); -#else - packet->append(filename, length); + /* Convert \ to / to be able to create table on unix */ + char *winfilename= (char*) thd->memdup(filename, length); + char *pos, *end; + for (pos= winfilename, end= pos+length ; pos < end ; pos++) + { + if (*pos == '\\') + *pos = '/'; + } + filename= winfilename; #endif + packet->append(filename, length); packet->append('\''); } } diff --git a/sql/sql_string.cc b/sql/sql_string.cc index 226a80201a1..0424723d97f 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -686,16 +686,16 @@ void String::qs_append(double *d) void String::qs_append(int i) { - char *buff = Ptr + str_length; - sprintf(buff,"%d", i); - str_length += strlen(buff); + char *buff= Ptr + str_length; + char *end= int10_to_str(i, buff, -10); + str_length+= (int) (end-buff); } void String::qs_append(uint i) { - char *buff = Ptr + str_length; - sprintf(buff,"%u", i); - str_length += strlen(buff); + char *buff= Ptr + str_length; + char *end= int10_to_str(i, buff, 10); + str_length+= (int) (end-buff); } /* diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 2f872b2ad05..48e3cb14261 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -208,7 +208,8 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, if (!drop_temporary) { abort_locked_tables(thd,db,table->table_name); - while (remove_table_from_cache(thd,db,table->table_name) && !thd->killed) + while (remove_table_from_cache(thd, db, table->table_name, 0) && + !thd->killed) { dropping_tables++; (void) pthread_cond_wait(&COND_refresh,&LOCK_open); @@ -291,7 +292,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, } } - unlock_table_names(thd, tables); + unlock_table_names(thd, tables, (TABLE_LIST*) 0); thd->no_warnings_for_error= 0; DBUG_RETURN(error); } @@ -451,150 +452,151 @@ void calculate_interval_lengths(CHARSET_INFO *cs, TYPELIB *interval, */ int prepare_create_field(create_field *sql_field, - uint &blob_columns, - int ×tamps, int ×tamps_with_niladic, + uint *blob_columns, + int *timestamps, int *timestamps_with_niladic, uint table_flags) { DBUG_ENTER("prepare_field"); - { - /* This code came from mysql_prepare_table. - Indent preserved to make patching easier */ - DBUG_ASSERT(sql_field->charset); - - switch (sql_field->sql_type) { - case FIELD_TYPE_BLOB: - case FIELD_TYPE_MEDIUM_BLOB: - case FIELD_TYPE_TINY_BLOB: - case FIELD_TYPE_LONG_BLOB: - sql_field->pack_flag=FIELDFLAG_BLOB | - pack_length_to_packflag(sql_field->pack_length - - portable_sizeof_char_ptr); - if (sql_field->charset->state & MY_CS_BINSORT) - sql_field->pack_flag|=FIELDFLAG_BINARY; - sql_field->length=8; // Unireg field length - sql_field->unireg_check=Field::BLOB_FIELD; - blob_columns++; - break; - case FIELD_TYPE_GEOMETRY: + + /* + This code came from mysql_prepare_table. + Indent preserved to make patching easier + */ + DBUG_ASSERT(sql_field->charset); + + switch (sql_field->sql_type) { + case FIELD_TYPE_BLOB: + case FIELD_TYPE_MEDIUM_BLOB: + case FIELD_TYPE_TINY_BLOB: + case FIELD_TYPE_LONG_BLOB: + sql_field->pack_flag=FIELDFLAG_BLOB | + pack_length_to_packflag(sql_field->pack_length - + portable_sizeof_char_ptr); + if (sql_field->charset->state & MY_CS_BINSORT) + sql_field->pack_flag|=FIELDFLAG_BINARY; + sql_field->length=8; // Unireg field length + sql_field->unireg_check=Field::BLOB_FIELD; + blob_columns++; + break; + case FIELD_TYPE_GEOMETRY: #ifdef HAVE_SPATIAL - if (!(table_flags & HA_CAN_GEOMETRY)) - { - my_printf_error(ER_CHECK_NOT_IMPLEMENTED, ER(ER_CHECK_NOT_IMPLEMENTED), - MYF(0), "GEOMETRY"); - DBUG_RETURN(1); - } - sql_field->pack_flag=FIELDFLAG_GEOM | - pack_length_to_packflag(sql_field->pack_length - - portable_sizeof_char_ptr); - if (sql_field->charset->state & MY_CS_BINSORT) - sql_field->pack_flag|=FIELDFLAG_BINARY; - sql_field->length=8; // Unireg field length - sql_field->unireg_check=Field::BLOB_FIELD; - blob_columns++; - break; -#else - my_printf_error(ER_FEATURE_DISABLED,ER(ER_FEATURE_DISABLED), MYF(0), - sym_group_geom.name, sym_group_geom.needed_define); + if (!(table_flags & HA_CAN_GEOMETRY)) + { + my_printf_error(ER_CHECK_NOT_IMPLEMENTED, ER(ER_CHECK_NOT_IMPLEMENTED), + MYF(0), "GEOMETRY"); DBUG_RETURN(1); + } + sql_field->pack_flag=FIELDFLAG_GEOM | + pack_length_to_packflag(sql_field->pack_length - + portable_sizeof_char_ptr); + if (sql_field->charset->state & MY_CS_BINSORT) + sql_field->pack_flag|=FIELDFLAG_BINARY; + sql_field->length=8; // Unireg field length + sql_field->unireg_check=Field::BLOB_FIELD; + blob_columns++; + break; +#else + my_printf_error(ER_FEATURE_DISABLED,ER(ER_FEATURE_DISABLED), MYF(0), + sym_group_geom.name, sym_group_geom.needed_define); + DBUG_RETURN(1); #endif /*HAVE_SPATIAL*/ - case MYSQL_TYPE_VARCHAR: + case MYSQL_TYPE_VARCHAR: #ifndef QQ_ALL_HANDLERS_SUPPORT_VARCHAR - if (table_flags & HA_NO_VARCHAR) - { - /* convert VARCHAR to CHAR because handler is not yet up to date */ - sql_field->sql_type= MYSQL_TYPE_VAR_STRING; - sql_field->pack_length= calc_pack_length(sql_field->sql_type, - (uint) sql_field->length); - if ((sql_field->length / sql_field->charset->mbmaxlen) > - MAX_FIELD_CHARLENGTH) - { - my_printf_error(ER_TOO_BIG_FIELDLENGTH, ER(ER_TOO_BIG_FIELDLENGTH), - MYF(0), sql_field->field_name, MAX_FIELD_CHARLENGTH); - DBUG_RETURN(1); - } - } -#endif - /* fall through */ - case FIELD_TYPE_STRING: - sql_field->pack_flag=0; - if (sql_field->charset->state & MY_CS_BINSORT) - sql_field->pack_flag|=FIELDFLAG_BINARY; - break; - case FIELD_TYPE_ENUM: - sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) | - FIELDFLAG_INTERVAL; - if (sql_field->charset->state & MY_CS_BINSORT) - sql_field->pack_flag|=FIELDFLAG_BINARY; - sql_field->unireg_check=Field::INTERVAL_FIELD; - check_duplicates_in_interval("ENUM",sql_field->field_name, - sql_field->interval, - sql_field->charset); - break; - case FIELD_TYPE_SET: - sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) | - FIELDFLAG_BITFIELD; - if (sql_field->charset->state & MY_CS_BINSORT) - sql_field->pack_flag|=FIELDFLAG_BINARY; - sql_field->unireg_check=Field::BIT_FIELD; - check_duplicates_in_interval("SET",sql_field->field_name, - sql_field->interval, - sql_field->charset); - break; - case FIELD_TYPE_DATE: // Rest of string types - case FIELD_TYPE_NEWDATE: - case FIELD_TYPE_TIME: - case FIELD_TYPE_DATETIME: - case FIELD_TYPE_NULL: - sql_field->pack_flag=f_settype((uint) sql_field->sql_type); - break; - case FIELD_TYPE_BIT: - if (!(table_flags & HA_CAN_BIT_FIELD)) + if (table_flags & HA_NO_VARCHAR) + { + /* convert VARCHAR to CHAR because handler is not yet up to date */ + sql_field->sql_type= MYSQL_TYPE_VAR_STRING; + sql_field->pack_length= calc_pack_length(sql_field->sql_type, + (uint) sql_field->length); + if ((sql_field->length / sql_field->charset->mbmaxlen) > + MAX_FIELD_CHARLENGTH) { - my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "BIT FIELD"); + my_printf_error(ER_TOO_BIG_FIELDLENGTH, ER(ER_TOO_BIG_FIELDLENGTH), + MYF(0), sql_field->field_name, MAX_FIELD_CHARLENGTH); DBUG_RETURN(1); } - sql_field->pack_flag= FIELDFLAG_NUMBER; - break; - case FIELD_TYPE_NEWDECIMAL: - sql_field->pack_flag=(FIELDFLAG_NUMBER | - (sql_field->flags & UNSIGNED_FLAG ? 0 : - FIELDFLAG_DECIMAL) | - (sql_field->flags & ZEROFILL_FLAG ? - FIELDFLAG_ZEROFILL : 0) | - (sql_field->decimals << FIELDFLAG_DEC_SHIFT)); - break; - case FIELD_TYPE_TIMESTAMP: - /* We should replace old TIMESTAMP fields with their newer analogs */ - if (sql_field->unireg_check == Field::TIMESTAMP_OLD_FIELD) + } +#endif + /* fall through */ + case FIELD_TYPE_STRING: + sql_field->pack_flag=0; + if (sql_field->charset->state & MY_CS_BINSORT) + sql_field->pack_flag|=FIELDFLAG_BINARY; + break; + case FIELD_TYPE_ENUM: + sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) | + FIELDFLAG_INTERVAL; + if (sql_field->charset->state & MY_CS_BINSORT) + sql_field->pack_flag|=FIELDFLAG_BINARY; + sql_field->unireg_check=Field::INTERVAL_FIELD; + check_duplicates_in_interval("ENUM",sql_field->field_name, + sql_field->interval, + sql_field->charset); + break; + case FIELD_TYPE_SET: + sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) | + FIELDFLAG_BITFIELD; + if (sql_field->charset->state & MY_CS_BINSORT) + sql_field->pack_flag|=FIELDFLAG_BINARY; + sql_field->unireg_check=Field::BIT_FIELD; + check_duplicates_in_interval("SET",sql_field->field_name, + sql_field->interval, + sql_field->charset); + break; + case FIELD_TYPE_DATE: // Rest of string types + case FIELD_TYPE_NEWDATE: + case FIELD_TYPE_TIME: + case FIELD_TYPE_DATETIME: + case FIELD_TYPE_NULL: + sql_field->pack_flag=f_settype((uint) sql_field->sql_type); + break; + case FIELD_TYPE_BIT: + if (!(table_flags & HA_CAN_BIT_FIELD)) + { + my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "BIT FIELD"); + DBUG_RETURN(1); + } + sql_field->pack_flag= FIELDFLAG_NUMBER; + break; + case FIELD_TYPE_NEWDECIMAL: + sql_field->pack_flag=(FIELDFLAG_NUMBER | + (sql_field->flags & UNSIGNED_FLAG ? 0 : + FIELDFLAG_DECIMAL) | + (sql_field->flags & ZEROFILL_FLAG ? + FIELDFLAG_ZEROFILL : 0) | + (sql_field->decimals << FIELDFLAG_DEC_SHIFT)); + break; + case FIELD_TYPE_TIMESTAMP: + /* We should replace old TIMESTAMP fields with their newer analogs */ + if (sql_field->unireg_check == Field::TIMESTAMP_OLD_FIELD) + { + if (!timestamps) { - if (!timestamps) - { - sql_field->unireg_check= Field::TIMESTAMP_DNUN_FIELD; - timestamps_with_niladic++; - } - else - sql_field->unireg_check= Field::NONE; + sql_field->unireg_check= Field::TIMESTAMP_DNUN_FIELD; + timestamps_with_niladic++; } - else if (sql_field->unireg_check != Field::NONE) - timestamps_with_niladic++; - - timestamps++; - /* fall-through */ - default: - sql_field->pack_flag=(FIELDFLAG_NUMBER | - (sql_field->flags & UNSIGNED_FLAG ? 0 : - FIELDFLAG_DECIMAL) | - (sql_field->flags & ZEROFILL_FLAG ? - FIELDFLAG_ZEROFILL : 0) | - f_settype((uint) sql_field->sql_type) | - (sql_field->decimals << FIELDFLAG_DEC_SHIFT)); - break; - } - if (!(sql_field->flags & NOT_NULL_FLAG)) - sql_field->pack_flag|= FIELDFLAG_MAYBE_NULL; - if (sql_field->flags & NO_DEFAULT_VALUE_FLAG) - sql_field->pack_flag|= FIELDFLAG_NO_DEFAULT; - } + else + sql_field->unireg_check= Field::NONE; + } + else if (sql_field->unireg_check != Field::NONE) + timestamps_with_niladic++; + + timestamps++; + /* fall-through */ + default: + sql_field->pack_flag=(FIELDFLAG_NUMBER | + (sql_field->flags & UNSIGNED_FLAG ? 0 : + FIELDFLAG_DECIMAL) | + (sql_field->flags & ZEROFILL_FLAG ? + FIELDFLAG_ZEROFILL : 0) | + f_settype((uint) sql_field->sql_type) | + (sql_field->decimals << FIELDFLAG_DEC_SHIFT)); + break; + } + if (!(sql_field->flags & NOT_NULL_FLAG)) + sql_field->pack_flag|= FIELDFLAG_MAYBE_NULL; + if (sql_field->flags & NO_DEFAULT_VALUE_FLAG) + sql_field->pack_flag|= FIELDFLAG_NO_DEFAULT; DBUG_RETURN(0); } @@ -857,8 +859,8 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, { DBUG_ASSERT(sql_field->charset != 0); - if (prepare_create_field(sql_field, blob_columns, - timestamps, timestamps_with_niladic, + if (prepare_create_field(sql_field, &blob_columns, + ×tamps, ×tamps_with_niladic, file->table_flags())) DBUG_RETURN(-1); if (sql_field->sql_type == FIELD_TYPE_BLOB || @@ -1765,7 +1767,7 @@ static void wait_while_table_is_used(THD *thd,TABLE *table, mysql_lock_abort(thd, table); // end threads waiting on lock /* Wait until all there are no other threads that has this table open */ - while (remove_table_from_cache(thd, table->s->db, table->s->table_name)) + while (remove_table_from_cache(thd, table->s->db, table->s->table_name, 0)) { dropping_tables++; (void) pthread_cond_wait(&COND_refresh,&LOCK_open); @@ -2134,7 +2136,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, "Waiting to get writelock"); mysql_lock_abort(thd,table->table); while (remove_table_from_cache(thd, table->table->s->db, - table->table->s->table_name) && + table->table->s->table_name, 0) && ! thd->killed) { dropping_tables++; @@ -2249,7 +2251,7 @@ send_result_message: { pthread_mutex_lock(&LOCK_open); remove_table_from_cache(thd, table->table->s->db, - table->table->s->table_name); + table->table->s->table_name, 0); pthread_mutex_unlock(&LOCK_open); /* May be something modified consequently we have to invalidate cache */ query_cache_invalidate3(thd, table->table, 0); @@ -3558,7 +3560,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, if (table) { VOID(table->file->extra(HA_EXTRA_FORCE_REOPEN)); // Use new file - remove_table_from_cache(thd,db,table_name); // Mark all in-use copies old + remove_table_from_cache(thd,db,table_name, 0); // Mark in-use copies old mysql_lock_abort(thd,table); // end threads waiting on lock } VOID(quick_rm_table(old_db_type,db,old_name)); diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 477a283448a..e215141ff0a 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -229,7 +229,7 @@ int mysql_update(THD *thd, // Don't count on usage of 'only index' when calculating which key to use table->used_keys.clear_all(); - select=make_select(table,0,0,conds,&error); + select= make_select(table, 0, 0, conds, 0, &error); if (error || (select && select->check_quick(thd, safe_update, limit)) || !limit) { diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 56dd6409eba..cb247f900d8 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1386,14 +1386,18 @@ create_function_tail: uint unused1= 0; int unused2= 0; - if (!(new_field= new_create_field(YYTHD, "", (enum enum_field_types)$8, - lex->length, lex->dec, lex->type, - (Item *)0, (Item *) 0, &cmt, 0, &lex->interval_list, - (lex->charset ? lex->charset : default_charset_info), - lex->uint_geom_type))) + if (!(new_field= new_create_field(YYTHD, "", + (enum enum_field_types)$8, + lex->length, lex->dec, lex->type, + (Item *)0, (Item *) 0, &cmt, 0, + &lex->interval_list, + (lex->charset ? lex->charset : + default_charset_info), + lex->uint_geom_type))) YYABORT; - if (prepare_create_field(new_field, unused1, unused2, unused2, 0)) + if (prepare_create_field(new_field, &unused1, &unused2, &unused2, + 0)) YYABORT; sp->m_returns= new_field->sql_type; |