summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/Makefile.am2
-rw-r--r--sql/field.cc261
-rw-r--r--sql/field.h45
-rw-r--r--sql/gen_lex_hash.cc58
-rw-r--r--sql/ha_berkeley.cc39
-rw-r--r--sql/ha_berkeley.h2
-rw-r--r--sql/ha_innodb.cc21
-rw-r--r--sql/ha_myisam.cc23
-rw-r--r--sql/item.cc229
-rw-r--r--sql/item.h178
-rw-r--r--sql/item_cmpfunc.cc302
-rw-r--r--sql/item_cmpfunc.h234
-rw-r--r--sql/item_func.cc3
-rw-r--r--sql/item_func.h10
-rw-r--r--sql/item_row.cc42
-rw-r--r--sql/item_row.h21
-rw-r--r--sql/item_subselect.cc132
-rw-r--r--sql/item_subselect.h30
-rw-r--r--sql/item_sum.cc71
-rw-r--r--sql/item_sum.h67
-rw-r--r--sql/item_timefunc.cc58
-rw-r--r--sql/item_timefunc.h64
-rw-r--r--sql/lex.h2
-rw-r--r--sql/log_event.cc76
-rw-r--r--sql/log_event.h26
-rw-r--r--sql/mysql_priv.h29
-rw-r--r--sql/mysqld.cc3
-rw-r--r--sql/net_pkg.cc525
-rw-r--r--sql/opt_range.cc45
-rw-r--r--sql/procedure.h6
-rw-r--r--sql/protocol.cc1038
-rw-r--r--sql/protocol.h131
-rw-r--r--sql/repl_failsafe.cc48
-rw-r--r--sql/set_var.cc4
-rw-r--r--sql/share/german/errmsg.txt203
-rw-r--r--sql/slave.cc122
-rw-r--r--sql/sql_acl.cc27
-rw-r--r--sql/sql_analyse.cc50
-rw-r--r--sql/sql_base.cc247
-rw-r--r--sql/sql_class.cc48
-rw-r--r--sql/sql_class.h3
-rw-r--r--sql/sql_db.cc17
-rw-r--r--sql/sql_derived.cc77
-rw-r--r--sql/sql_error.cc18
-rw-r--r--sql/sql_handler.cc33
-rw-r--r--sql/sql_help.cc72
-rw-r--r--sql/sql_lex.cc9
-rw-r--r--sql/sql_lex.h2
-rw-r--r--sql/sql_list.h10
-rw-r--r--sql/sql_parse.cc8
-rw-r--r--sql/sql_prepare.cc5
-rw-r--r--sql/sql_repl.cc46
-rw-r--r--sql/sql_select.cc41
-rw-r--r--sql/sql_show.cc660
-rw-r--r--sql/sql_string.h25
-rw-r--r--sql/sql_table.cc91
-rw-r--r--sql/sql_union.cc6
-rw-r--r--sql/sql_yacc.yy10
-rw-r--r--sql/structs.h3
-rw-r--r--sql/time.cc17
60 files changed, 3518 insertions, 2157 deletions
diff --git a/sql/Makefile.am b/sql/Makefile.am
index c5af51e8397..245e4c5d258 100644
--- a/sql/Makefile.am
+++ b/sql/Makefile.am
@@ -64,7 +64,7 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc \
thr_malloc.cc item_create.cc item_subselect.cc \
item_row.cc \
field.cc key.cc sql_class.cc sql_list.cc \
- net_serv.cc net_pkg.cc lock.cc my_lock.c \
+ net_serv.cc protocol.cc lock.cc my_lock.c \
sql_string.cc sql_manager.cc sql_map.cc \
mysqld.cc password.c hash_filo.cc hostname.cc \
convert.cc set_var.cc sql_parse.cc sql_yacc.yy \
diff --git a/sql/field.cc b/sql/field.cc
index 59033dd2d7f..e6a4c30d7f5 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -196,17 +196,12 @@ void Field::copy_from_tmp(int row_offset)
}
-bool Field::send(THD *thd, String *packet)
+bool Field::send_binary(Protocol *protocol)
{
- if (is_null())
- return net_store_null(packet);
char buff[MAX_FIELD_WIDTH];
String tmp(buff,sizeof(buff),default_charset_info);
val_str(&tmp,&tmp);
- CONVERT *convert;
- if ((convert=thd->variables.convert_set))
- return convert->store(packet,tmp.ptr(),tmp.length());
- return net_store_data(packet,tmp.ptr(),tmp.length());
+ return protocol->store(tmp.ptr(), tmp.length());
}
@@ -1074,6 +1069,10 @@ String *Field_tiny::val_str(String *val_buffer,
return val_buffer;
}
+bool Field_tiny::send_binary(Protocol *protocol)
+{
+ return protocol->store_tiny((longlong) (int8) ptr[0]);
+}
int Field_tiny::cmp(const char *a_ptr, const char *b_ptr)
{
@@ -1285,6 +1284,7 @@ longlong Field_short::val_int(void)
return unsigned_flag ? (longlong) (unsigned short) j : (longlong) j;
}
+
String *Field_short::val_str(String *val_buffer,
String *val_ptr __attribute__((unused)))
{
@@ -1312,6 +1312,12 @@ String *Field_short::val_str(String *val_buffer,
}
+bool Field_short::send_binary(Protocol *protocol)
+{
+ return protocol->store_short(Field_short::val_int());
+}
+
+
int Field_short::cmp(const char *a_ptr, const char *b_ptr)
{
short a,b;
@@ -1538,6 +1544,12 @@ String *Field_medium::val_str(String *val_buffer,
}
+bool Field_medium::send_binary(Protocol *protocol)
+{
+ return protocol->store_long(Field_medium::val_int());
+}
+
+
int Field_medium::cmp(const char *a_ptr, const char *b_ptr)
{
long a,b;
@@ -1774,6 +1786,11 @@ String *Field_long::val_str(String *val_buffer,
}
+bool Field_long::send_binary(Protocol *protocol)
+{
+ return protocol->store_long(Field_long::val_int());
+}
+
int Field_long::cmp(const char *a_ptr, const char *b_ptr)
{
int32 a,b;
@@ -1988,6 +2005,12 @@ String *Field_longlong::val_str(String *val_buffer,
}
+bool Field_longlong::send_binary(Protocol *protocol)
+{
+ return protocol->store_longlong(Field_longlong::val_int(), unsigned_flag);
+}
+
+
int Field_longlong::cmp(const char *a_ptr, const char *b_ptr)
{
longlong a,b;
@@ -2302,6 +2325,12 @@ void Field_float::sort_string(char *to,uint length __attribute__((unused)))
}
+bool Field_float::send_binary(Protocol *protocol)
+{
+ return protocol->store((float) Field_float::val_real(), dec, (String*) 0);
+}
+
+
void Field_float::sql_type(String &res) const
{
if (dec == NOT_FIXED_DEC)
@@ -2499,6 +2528,11 @@ String *Field_double::val_str(String *val_buffer,
return val_buffer;
}
+bool Field_double::send_binary(Protocol *protocol)
+{
+ return protocol->store((float) Field_double::val_real(), dec, (String*) 0);
+}
+
int Field_double::cmp(const char *a_ptr, const char *b_ptr)
{
@@ -2568,10 +2602,10 @@ void Field_double::sql_type(String &res) const
Field_timestamp::Field_timestamp(char *ptr_arg, uint32 len_arg,
enum utype unireg_check_arg,
const char *field_name_arg,
- struct st_table *table_arg)
- :Field_num(ptr_arg, len_arg, (uchar*) 0,0,
- unireg_check_arg, field_name_arg, table_arg,
- 0, 1, 1)
+ struct st_table *table_arg,
+ CHARSET_INFO *cs)
+ :Field_str(ptr_arg, 19, (uchar*) 0,0,
+ unireg_check_arg, field_name_arg, table_arg, cs)
{
if (table && !table->timestamp_field)
{
@@ -2596,35 +2630,6 @@ int Field_timestamp::store(const char *from,uint len,CHARSET_INFO *cs)
return 0;
}
-void Field_timestamp::fill_and_store(char *from,uint len)
-{
- uint res_length;
- if (len <= field_length)
- res_length=field_length;
- else if (len <= 12)
- res_length=12; /* purecov: inspected */
- else if (len <= 14)
- res_length=14; /* purecov: inspected */
- else
- res_length=(len+1)/2*2; // must be even
- if (res_length != len)
- {
- bmove_upp(from+res_length,from+len,len);
- bfill(from,res_length-len,'0');
- len=res_length;
- }
- long tmp=(long) str_to_timestamp(from,len);
-#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
- {
- int4store(ptr,tmp);
- }
- else
-#endif
- longstore(ptr,tmp);
-}
-
-
int Field_timestamp::store(double nr)
{
int error= 0;
@@ -2735,44 +2740,34 @@ longlong Field_timestamp::val_int(void)
time_arg=(time_t) temp;
localtime_r(&time_arg,&tm_tmp);
l_time=&tm_tmp;
- res=(longlong) 0;
- for (pos=len=0; len+1 < (uint) field_length ; len+=2,pos++)
- {
- bool year_flag=0;
- switch (dayord.pos[pos]) {
- case 0: part_time=l_time->tm_year % 100; year_flag=1 ; break;
- case 1: part_time=l_time->tm_mon+1; break;
- case 2: part_time=l_time->tm_mday; break;
- case 3: part_time=l_time->tm_hour; break;
- case 4: part_time=l_time->tm_min; break;
- case 5: part_time=l_time->tm_sec; break;
- default: part_time=0; break; /* purecov: deadcode */
- }
- if (year_flag && (field_length == 8 || field_length == 14))
- {
- res=res*(longlong) 10000+(part_time+
- ((part_time < YY_PART_YEAR) ? 2000 : 1900));
- len+=2;
- }
- else
- res=res*(longlong) 100+part_time;
- }
- return (longlong) res;
+
+ part_time= l_time->tm_year % 100;
+ res= ((longlong) (part_time+ ((part_time < YY_PART_YEAR) ? 2000 : 1900))*
+ LL(10000000000));
+ part_time= l_time->tm_mon+1;
+ res+= (longlong) part_time * LL(100000000);
+ part_time=l_time->tm_mday;
+ res+= (longlong) ((long) part_time * 1000000L);
+ part_time=l_time->tm_hour;
+ res+= (longlong) (part_time * 10000L);
+ part_time=l_time->tm_min;
+ res+= (longlong) (part_time * 100);
+ part_time=l_time->tm_sec;
+ return res+part_time;
}
String *Field_timestamp::val_str(String *val_buffer,
String *val_ptr __attribute__((unused)))
{
- uint pos;
- int part_time;
- uint32 temp;
+ uint32 temp, temp2;
time_t time_arg;
struct tm *l_time;
struct tm tm_tmp;
val_buffer->alloc(field_length+1);
char *to=(char*) val_buffer->ptr(),*end=to+field_length;
+ val_buffer->length(field_length);
#ifdef WORDS_BIGENDIAN
if (table->db_low_byte_first)
@@ -2783,44 +2778,57 @@ String *Field_timestamp::val_str(String *val_buffer,
if (temp == 0L)
{ /* Zero time is "000000" */
- VOID(strfill(to,field_length,'0'));
- val_buffer->length(field_length);
+ strmov(to, "0000-00-00 00:00:00");
return val_buffer;
}
time_arg=(time_t) temp;
localtime_r(&time_arg,&tm_tmp);
l_time=&tm_tmp;
- for (pos=0; to < end ; pos++)
- {
- bool year_flag=0;
- switch (dayord.pos[pos]) {
- case 0: part_time=l_time->tm_year % 100; year_flag=1; break;
- case 1: part_time=l_time->tm_mon+1; break;
- case 2: part_time=l_time->tm_mday; break;
- case 3: part_time=l_time->tm_hour; break;
- case 4: part_time=l_time->tm_min; break;
- case 5: part_time=l_time->tm_sec; break;
- default: part_time=0; break; /* purecov: deadcode */
- }
- if (year_flag && (field_length == 8 || field_length == 14))
- {
- if (part_time < YY_PART_YEAR)
- {
- *to++='2'; *to++='0'; /* purecov: inspected */
- }
- else
- {
- *to++='1'; *to++='9';
- }
- }
- *to++=(char) ('0'+((uint) part_time/10));
- *to++=(char) ('0'+((uint) part_time % 10));
- }
- *to=0; // Safeguard
- val_buffer->length((uint) (to-val_buffer->ptr()));
+
+ temp= l_time->tm_year % 100;
+ if (temp < YY_PART_YEAR)
+ {
+ *to++= '2';
+ *to++= '0';
+ }
+ else
+ {
+ *to++= '1';
+ *to++= '9';
+ }
+ temp2=temp/10; temp=temp-temp2*10;
+ *to++= (char) ('0'+(char) (temp2));
+ *to++= (char) ('0'+(char) (temp));
+ *to++= '-';
+ temp=l_time->tm_mon+1;
+ temp2=temp/10; temp=temp-temp2*10;
+ *to++= (char) ('0'+(char) (temp2));
+ *to++= (char) ('0'+(char) (temp));
+ *to++= '-';
+ temp=l_time->tm_mday;
+ temp2=temp/10; temp=temp-temp2*10;
+ *to++= (char) ('0'+(char) (temp2));
+ *to++= (char) ('0'+(char) (temp));
+ *to++= ' ';
+ temp=l_time->tm_hour;
+ temp2=temp/10; temp=temp-temp2*10;
+ *to++= (char) ('0'+(char) (temp2));
+ *to++= (char) ('0'+(char) (temp));
+ *to++= ':';
+ temp=l_time->tm_min;
+ temp2=temp/10; temp=temp-temp2*10;
+ *to++= (char) ('0'+(char) (temp2));
+ *to++= (char) ('0'+(char) (temp));
+ *to++= ':';
+ temp=l_time->tm_sec;
+ temp2=temp/10; temp=temp-temp2*10;
+ *to++= (char) ('0'+(char) (temp2));
+ *to++= (char) ('0'+(char) (temp));
+ *to= 0;
return val_buffer;
}
+
bool Field_timestamp::get_date(TIME *ltime, bool fuzzydate)
{
long temp;
@@ -2860,6 +2868,15 @@ bool Field_timestamp::get_time(TIME *ltime)
return Field_timestamp::get_date(ltime,0);
}
+
+bool Field_timestamp::send_binary(Protocol *protocol)
+{
+ TIME tm;
+ Field_timestamp::get_date(&tm, 1);
+ return protocol->store(&tm);
+}
+
+
int Field_timestamp::cmp(const char *a_ptr, const char *b_ptr)
{
int32 a,b;
@@ -2878,6 +2895,7 @@ int Field_timestamp::cmp(const char *a_ptr, const char *b_ptr)
return ((uint32) a < (uint32) b) ? -1 : ((uint32) a > (uint32) b) ? 1 : 0;
}
+
void Field_timestamp::sort_string(char *to,uint length __attribute__((unused)))
{
#ifdef WORDS_BIGENDIAN
@@ -2901,10 +2919,7 @@ void Field_timestamp::sort_string(char *to,uint length __attribute__((unused)))
void Field_timestamp::sql_type(String &res) const
{
- ulong length= my_sprintf((char*) res.ptr(),
- ((char*) res.ptr(),"timestamp(%d)",
- (int) field_length));
- res.length(length);
+ res.set("timestamp", 9, default_charset_info);
}
@@ -3068,6 +3083,17 @@ bool Field_time::get_time(TIME *ltime)
return 0;
}
+
+bool Field_time::send_binary(Protocol *protocol)
+{
+ TIME tm;
+ Field_time::get_time(&tm);
+ tm.day= tm.hour/3600; // Move hours to days
+ tm.hour-= tm.day*3600;
+ return protocol->store(&tm);
+}
+
+
int Field_time::cmp(const char *a_ptr, const char *b_ptr)
{
int32 a,b;
@@ -3965,19 +3991,15 @@ int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs)
ThNormalize((uchar *) ptr+2, field_length, (uchar *) from, length);
}
#else
- if (length <= field_length)
- {
- memcpy(ptr+2,from,length);
- }
- else
+ if (length > field_length)
{
length=field_length;
- memcpy(ptr+2,from,field_length);
current_thd->cuted_fields++;
error= 1;
}
+ memcpy(ptr+2,from,length);
#endif /* USE_TIS620 */
- int2store(ptr,length);
+ int2store(ptr, length);
return error;
}
@@ -4176,6 +4198,28 @@ uint Field_varstring::max_packed_col_length(uint max_length)
return (max_length > 255 ? 2 : 1)+max_length;
}
+void Field_varstring::get_key_image(char *buff, uint length, imagetype type)
+{
+ length-= HA_KEY_BLOB_LENGTH;
+ uint f_length=uint2korr(ptr);
+ if (f_length > length)
+ f_length= length;
+ int2store(buff,length);
+ memcpy(buff+2,ptr+2,length);
+#ifdef HAVE_purify
+ if (f_length < length)
+ bzero(buff+2+f_length, (length-f_length));
+#endif
+}
+
+void Field_varstring::set_key_image(char *buff,uint length)
+{
+ length=uint2korr(buff); // Real length is here
+ (void) Field_varstring::store(buff+2, length, default_charset_info);
+}
+
+
+
/****************************************************************************
** blob type
** A blob is saved as a length and a pointer. The length is stored in the
@@ -4443,7 +4487,6 @@ void Field_blob::get_key_image(char *buff,uint length, imagetype type)
return;
}
- length-=HA_KEY_BLOB_LENGTH;
if ((uint32) length > blob_length)
{
#ifdef HAVE_purify
@@ -5265,7 +5308,7 @@ Field *make_field(char *ptr, uint32 field_length,
f_is_dec(pack_flag) == 0);
case FIELD_TYPE_TIMESTAMP:
return new Field_timestamp(ptr,field_length,
- unireg_check, field_name, table);
+ unireg_check, field_name, table, field_charset);
case FIELD_TYPE_YEAR:
return new Field_year(ptr,field_length,null_pos,null_bit,
unireg_check, field_name, table);
diff --git a/sql/field.h b/sql/field.h
index 7a1a191ab43..9258e15ed04 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -27,10 +27,12 @@
#define NOT_FIXED_DEC 31
class Send_field;
+class Protocol;
struct st_cache_field;
void field_conv(Field *to,Field *from);
-class Field {
+class Field
+{
Field(const Item &); /* Prevent use of these */
void operator=(Field &);
public:
@@ -164,7 +166,7 @@ public:
ptr-=row_offset;
return tmp;
}
- bool send(THD *thd, String *packet);
+ bool send_binary(Protocol *protocol);
virtual char *pack(char* to, const char *from, uint max_length=~(uint) 0)
{
uint32 length=pack_length();
@@ -268,11 +270,11 @@ public:
void set_charset(CHARSET_INFO *charset) { field_charset=charset; }
bool binary() const { return field_charset->state & MY_CS_BINSORT ? 1 : 0; }
inline int cmp_image(char *buff,uint length)
- {
- if (binary())
- return memcmp(ptr,buff,length);
- else
- return my_strncasecmp(field_charset,ptr,buff,length);
+ {
+ if (binary())
+ return memcmp(ptr,buff,length);
+ else
+ return my_strncasecmp(field_charset,ptr,buff,length);
}
friend class create_field;
};
@@ -291,7 +293,7 @@ public:
{}
enum_field_types type() const { return FIELD_TYPE_DECIMAL;}
enum ha_base_keytype key_type() const
- { return zerofill ? HA_KEYTYPE_BINARY : HA_KEYTYPE_NUM; }
+ { return zerofill ? HA_KEYTYPE_BINARY : HA_KEYTYPE_NUM; }
void reset(void);
int store(const char *to,uint length,CHARSET_INFO *charset);
int store(double nr);
@@ -329,6 +331,7 @@ public:
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
+ bool send_binary(Protocol *protocol);
int cmp(const char *,const char*);
void sort_string(char *buff,uint length);
uint32 pack_length() const { return 1; }
@@ -358,6 +361,7 @@ public:
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
+ bool send_binary(Protocol *protocol);
int cmp(const char *,const char*);
void sort_string(char *buff,uint length);
uint32 pack_length() const { return 2; }
@@ -387,6 +391,7 @@ public:
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
+ bool send_binary(Protocol *protocol);
int cmp(const char *,const char*);
void sort_string(char *buff,uint length);
uint32 pack_length() const { return 3; }
@@ -420,6 +425,7 @@ public:
void reset(void) { ptr[0]=ptr[1]=ptr[2]=ptr[3]=0; }
double val_real(void);
longlong val_int(void);
+ bool send_binary(Protocol *protocol);
String *val_str(String*,String *);
int cmp(const char *,const char*);
void sort_string(char *buff,uint length);
@@ -457,6 +463,7 @@ public:
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
+ bool send_binary(Protocol *protocol);
int cmp(const char *,const char*);
void sort_string(char *buff,uint length);
uint32 pack_length() const { return 8; }
@@ -485,6 +492,7 @@ public:
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
+ bool send_binary(Protocol *protocol);
int cmp(const char *,const char*);
void sort_string(char *buff,uint length);
uint32 pack_length() const { return sizeof(float); }
@@ -517,6 +525,7 @@ public:
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
+ bool send_binary(Protocol *protocol);
int cmp(const char *,const char*);
void sort_string(char *buff,uint length);
uint32 pack_length() const { return sizeof(double); }
@@ -552,14 +561,15 @@ public:
};
-class Field_timestamp :public Field_num {
+class Field_timestamp :public Field_str {
public:
Field_timestamp(char *ptr_arg, uint32 len_arg,
enum utype unireg_check_arg, const char *field_name_arg,
- struct st_table *table_arg);
- enum Item_result result_type () const { return field_length == 8 || field_length == 14 ? INT_RESULT : STRING_RESULT; }
+ struct st_table *table_arg,
+ CHARSET_INFO *cs);
enum_field_types type() const { return FIELD_TYPE_TIMESTAMP;}
enum ha_base_keytype key_type() const { return HA_KEYTYPE_ULONG_INT; }
+ enum Item_result cmp_type () const { return INT_RESULT; }
int store(const char *to,uint length,CHARSET_INFO *charset);
int store(double nr);
int store(longlong nr);
@@ -567,6 +577,7 @@ public:
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
+ bool send_binary(Protocol *protocol);
int cmp(const char *,const char*);
void sort_string(char *buff,uint length);
uint32 pack_length() const { return 4; }
@@ -588,7 +599,6 @@ public:
longget(tmp,ptr);
return tmp;
}
- void fill_and_store(char *from,uint len);
bool get_date(TIME *ltime,bool fuzzydate);
bool get_time(TIME *ltime);
};
@@ -610,6 +620,7 @@ public:
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
+ bool send_binary(Protocol *protocol);
void sql_type(String &str) const;
};
@@ -636,6 +647,7 @@ public:
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
+ bool send_binary(Protocol *protocol);
int cmp(const char *,const char*);
void sort_string(char *buff,uint length);
uint32 pack_length() const { return 4; }
@@ -664,6 +676,7 @@ public:
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
+ bool send_binary(Protocol *protocol);
int cmp(const char *,const char*);
void sort_string(char *buff,uint length);
uint32 pack_length() const { return 3; }
@@ -697,6 +710,7 @@ public:
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
+ bool send_binary(Protocol *protocol);
bool get_time(TIME *ltime);
int cmp(const char *,const char*);
void sort_string(char *buff,uint length);
@@ -732,6 +746,7 @@ public:
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
+ bool send_binary(Protocol *protocol);
int cmp(const char *,const char*);
void sort_string(char *buff,uint length);
uint32 pack_length() const { return 8; }
@@ -772,6 +787,7 @@ public:
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
+ bool send_binary(Protocol *protocol);
int cmp(const char *,const char*);
void sort_string(char *buff,uint length);
void sql_type(String &str) const;
@@ -812,8 +828,11 @@ public:
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
+ bool send_binary(Protocol *protocol);
int cmp(const char *,const char*);
void sort_string(char *buff,uint length);
+ void get_key_image(char *buff,uint length, imagetype type);
+ void set_key_image(char *buff,uint length);
void sql_type(String &str) const;
char *pack(char *to, const char *from, uint max_length=~(uint) 0);
const char *unpack(char* to, const char *from);
@@ -852,6 +871,7 @@ public:
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
+ bool send_binary(Protocol *protocol);
int cmp(const char *,const char*);
int cmp(const char *a, uint32 a_length, const char *b, uint32 b_length);
int cmp_offset(uint offset);
@@ -959,6 +979,7 @@ public:
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
+ bool send_binary(Protocol *protocol);
int cmp(const char *,const char*);
void sort_string(char *buff,uint length);
uint32 pack_length() const { return (uint32) packlength; }
diff --git a/sql/gen_lex_hash.cc b/sql/gen_lex_hash.cc
index 7daab228093..7ae28e0ce77 100644
--- a/sql/gen_lex_hash.cc
+++ b/sql/gen_lex_hash.cc
@@ -200,19 +200,21 @@ void insert_sql_functions()
}
}
-void generate_find_structs()
+void calc_length()
{
- root_by_len= 0;
- max_len=0;
- size_t i;
-
SYMBOL *cur, *end= symbols + array_elements(symbols);
for (cur= symbols; cur < end; cur++)
cur->length=(uchar) strlen(cur->name);
end= sql_functions + array_elements(sql_functions);
for (cur= sql_functions; cur<end; cur++)
cur->length=(uchar) strlen(cur->name);
-
+}
+
+void generate_find_structs()
+{
+ root_by_len= 0;
+ max_len=0;
+
insert_symbols();
root_by_len2= root_by_len;
@@ -351,6 +353,45 @@ static int get_options(int argc, char **argv)
return(0);
}
+int check_dup_symbols(SYMBOL *s1, SYMBOL *s2)
+{
+ if (s1->length!=s2->length || strncmp(s1->name,s2->name,s1->length))
+ return 0;
+
+ const char *err_tmpl= "\ngen_lex_hash fatal error : \
+Unfortunately gen_lex_hash can not generate a hash,\n since \
+your lex.h has duplicate definition for a symbol \"%s\"\n\n";
+ printf (err_tmpl,s1->name);
+ fprintf (stderr,err_tmpl,s1->name);
+
+ return 1;
+}
+
+int check_duplicates()
+{
+ SYMBOL *cur1, *cur2, *s_end, *f_end;
+
+ s_end= symbols + array_elements(symbols);
+ f_end= sql_functions + array_elements(sql_functions);
+
+ for (cur1= symbols; cur1<s_end; cur1++)
+ {
+ for (cur2= cur1+1; cur2<s_end; cur2++)
+ if (check_dup_symbols(cur1,cur2))
+ return 1;
+ for (cur2= sql_functions; cur2<f_end; cur2++)
+ if (check_dup_symbols(cur1,cur2))
+ return 1;
+ }
+
+ for (cur1= sql_functions; cur1<f_end; cur1++)
+ for (cur2= cur1+1; cur2< f_end; cur2++)
+ if (check_dup_symbols(cur1,cur2))
+ return 1;
+
+ return 0;
+}
+
int main(int argc,char **argv)
{
MY_INIT(argv[0]);
@@ -376,6 +417,11 @@ int main(int argc,char **argv)
a perfect\nhash function */\n\n");
printf("#include \"lex.h\"\n\n");
+ calc_length();
+
+ if (check_duplicates())
+ exit(1);
+
generate_find_structs();
print_find_structs();
diff --git a/sql/ha_berkeley.cc b/sql/ha_berkeley.cc
index bcbc3335203..1b8a2d9b3f8 100644
--- a/sql/ha_berkeley.cc
+++ b/sql/ha_berkeley.cc
@@ -231,10 +231,9 @@ int berkeley_rollback(THD *thd, void *trans)
}
-int berkeley_show_logs(THD *thd)
+int berkeley_show_logs(Protocol *protocol)
{
char **all_logs, **free_logs, **a, **f;
- String *packet= &thd->packet;
int error=1;
MEM_ROOT show_logs_root;
MEM_ROOT *old_root=my_pthread_getspecific_ptr(MEM_ROOT*,THR_MALLOC);
@@ -243,8 +242,9 @@ int berkeley_show_logs(THD *thd)
init_alloc_root(&show_logs_root, 1024, 1024);
my_pthread_setspecific_ptr(THR_MALLOC,&show_logs_root);
- if ((error= db_env->log_archive(db_env, &all_logs, DB_ARCH_ABS | DB_ARCH_LOG))
- || (error= db_env->log_archive(db_env, &free_logs, DB_ARCH_ABS)))
+ if ((error= db_env->log_archive(db_env, &all_logs,
+ DB_ARCH_ABS | DB_ARCH_LOG)) ||
+ (error= db_env->log_archive(db_env, &free_logs, DB_ARCH_ABS)))
{
DBUG_PRINT("error", ("log_archive failed (error %d)", error));
db_env->err(db_env, error, "log_archive: DB_ARCH_ABS");
@@ -257,19 +257,18 @@ int berkeley_show_logs(THD *thd)
{
for (a = all_logs, f = free_logs; *a; ++a)
{
- packet->length(0);
- net_store_data(packet,*a);
- net_store_data(packet,"BDB");
+ protocol->prepare_for_resend();
+ protocol->store(*a);
+ protocol->store("BDB", 3);
if (f && *f && strcmp(*a, *f) == 0)
{
- ++f;
- net_store_data(packet, SHOW_LOG_STATUS_FREE);
+ f++;
+ protocol->store(SHOW_LOG_STATUS_FREE);
}
else
- net_store_data(packet, SHOW_LOG_STATUS_INUSE);
+ protocol->store(SHOW_LOG_STATUS_INUSE);
-
- if (SEND_ROW(thd, 3, (char*) packet->ptr(),packet->length()))
+ if (protocol->write())
{
error=1;
goto err;
@@ -2066,8 +2065,7 @@ void ha_berkeley::print_error(int error, myf errflag)
static void print_msg(THD *thd, const char *table_name, const char *op_name,
const char *msg_type, const char *fmt, ...)
{
- String* packet = &thd->packet;
- packet->length(0);
+ Protocol *protocol= thd->protocol;
char msgbuf[256];
msgbuf[0] = 0;
va_list args;
@@ -2075,15 +2073,14 @@ static void print_msg(THD *thd, const char *table_name, const char *op_name,
my_vsnprintf(msgbuf, sizeof(msgbuf), fmt, args);
msgbuf[sizeof(msgbuf) - 1] = 0; // healthy paranoia
-
DBUG_PRINT(msg_type,("message: %s",msgbuf));
- net_store_data(packet, table_name);
- net_store_data(packet, op_name);
- net_store_data(packet, msg_type);
- net_store_data(packet, msgbuf);
- if (my_net_write(&thd->net, (char*)thd->packet.ptr(),
- thd->packet.length()))
+ protocol->prepare_for_resend();
+ protocol->store(table_name);
+ protocol->store(op_name);
+ protocol->store(msg_type);
+ protocol->store(msgbuf);
+ if (protocol->write())
thd->killed=1;
}
#endif
diff --git a/sql/ha_berkeley.h b/sql/ha_berkeley.h
index f2a81d123f1..dfdd12470d6 100644
--- a/sql/ha_berkeley.h
+++ b/sql/ha_berkeley.h
@@ -180,4 +180,4 @@ bool berkeley_end(void);
bool berkeley_flush_logs(void);
int berkeley_commit(THD *thd, void *trans);
int berkeley_rollback(THD *thd, void *trans);
-int berkeley_show_logs(THD *thd);
+int berkeley_show_logs(Protocol *protocol);
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index 300de4748bc..f4d21bf6216 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -3924,9 +3924,8 @@ innodb_show_status(
/*===============*/
THD* thd) /* in: the MySQL query thread of the caller */
{
- String* packet = &thd->packet;
char* buf;
-
+ Protocol *protocol= thd->protocol;
DBUG_ENTER("innodb_show_status");
if (innodb_skip) {
@@ -3947,21 +3946,17 @@ innodb_show_status(
field_list.push_back(new Item_empty_string("Status", strlen(buf)));
- if(send_fields(thd, field_list, 1)) {
+ if (protocol->send_fields(&field_list, 1))
+ {
DBUG_RETURN(-1);
}
- packet->length(0);
-
- net_store_data(packet, buf);
-
- if (SEND_ROW(thd, field_list.elements, (char*)thd->packet.ptr(), packet->length())) {
- ut_free(buf);
-
- DBUG_RETURN(-1);
- }
-
+ protocol->prepare_for_resend();
+ protocol->store(buf, strlen(buf));
ut_free(buf);
+
+ if (protocol->write())
+ DBUG_RETURN(-1);
send_eof(thd);
diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc
index 5cf77698e6b..0680f13a7df 100644
--- a/sql/ha_myisam.cc
+++ b/sql/ha_myisam.cc
@@ -50,14 +50,12 @@ static void mi_check_print_msg(MI_CHECK *param, const char* msg_type,
const char *fmt, va_list args)
{
THD* thd = (THD*)param->thd;
- String* packet = &thd->packet;
- uint length;
+ Protocol *protocol= thd->protocol;
+ uint length, msg_length;
char msgbuf[MI_MAX_MSG_BUF];
char name[NAME_LEN*2+2];
- packet->length(0);
- msgbuf[0] = 0; // healthy paranoia ?
- my_vsnprintf(msgbuf, sizeof(msgbuf), fmt, args);
+ msg_length= my_vsnprintf(msgbuf, sizeof(msgbuf), fmt, args);
msgbuf[sizeof(msgbuf) - 1] = 0; // healthy paranoia
DBUG_PRINT(msg_type,("message: %s",msgbuf));
@@ -70,19 +68,20 @@ static void mi_check_print_msg(MI_CHECK *param, const char* msg_type,
}
#endif
- if (param->testflag & (T_CREATE_MISSING_KEYS | T_SAFE_REPAIR | T_AUTO_REPAIR))
+ if (param->testflag & (T_CREATE_MISSING_KEYS | T_SAFE_REPAIR |
+ T_AUTO_REPAIR))
{
my_message(ER_NOT_KEYFILE,msgbuf,MYF(MY_WME));
return;
}
length=(uint) (strxmov(name, param->db_name,".",param->table_name,NullS) -
name);
- net_store_data(packet, name, length);
- net_store_data(packet, param->op_name);
- net_store_data(packet, msg_type);
-
- net_store_data(packet, msgbuf);
- if (SEND_ROW(thd, 4, (char*)thd->packet.ptr(), thd->packet.length()))
+ protocol->prepare_for_resend();
+ protocol->store(name, length);
+ protocol->store(param->op_name);
+ protocol->store(msg_type);
+ protocol->store(msgbuf, msg_length);
+ if (protocol->write())
sql_print_error("Failed on my_net_write, writing to stderr instead: %s\n",
msgbuf);
return;
diff --git a/sql/item.cc b/sql/item.cc
index 6eb2adb9392..10d26060278 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -22,6 +22,7 @@
#include "mysql_priv.h"
#include <m_ctype.h>
#include "my_dir.h"
+#include <assert.h>
/*****************************************************************************
** Item functions
@@ -46,6 +47,12 @@ Item::Item():
loop_id= 0;
}
+Item_ref_in_optimizer::Item_ref_in_optimizer(Item_in_optimizer *master,
+ char *table_name_par,
+ char *field_name_par):
+ Item_ref(master->args, table_name_par, field_name_par), owner(master) {}
+
+
bool Item::check_loop(uint id)
{
DBUG_ENTER("Item::check_loop");
@@ -372,12 +379,6 @@ int Item_param::save_in_field(Field *field, bool no_conversions)
}
-void Item_param::make_field(Send_field *tmp_field)
-{
- init_make_field(tmp_field,FIELD_TYPE_STRING);
-}
-
-
double Item_param::val()
{
switch (item_result_type) {
@@ -436,6 +437,20 @@ String *Item_copy_string::val_str(String *str)
return &str_value;
}
+double Item_ref_in_optimizer::val()
+{
+ return owner->get_cache();
+}
+longlong Item_ref_in_optimizer::val_int()
+{
+ return owner->get_cache_int();
+}
+String* Item_ref_in_optimizer::val_str(String* s)
+{
+ return owner->get_cache_str(s);
+}
+
+
/*
Functions to convert item to field (for send_fields)
*/
@@ -511,10 +526,31 @@ bool Item_asterisk_remover::fix_fields(THD *thd,
res= item->fix_fields(thd, list, &item);
else
thd->fatal_error= 1; // no item given => out of memory
- *ref= item;
DBUG_RETURN(res);
}
+double Item_ref_null_helper::val()
+{
+ double tmp= (*ref)->val_result();
+ owner->was_null|= null_value= (*ref)->null_value;
+ return tmp;
+}
+longlong Item_ref_null_helper::val_int()
+{
+ longlong tmp= (*ref)->val_int_result();
+ owner->was_null|= null_value= (*ref)->null_value;
+ return tmp;
+}
+String* Item_ref_null_helper::val_str(String* s)
+{
+ String* tmp= (*ref)->str_result(s);
+ owner->was_null|= null_value= (*ref)->null_value;
+ return tmp;
+}
+bool Item_ref_null_helper::get_date(TIME *ltime, bool fuzzydate)
+{
+ return (owner->was_null|= null_value= (*ref)->get_date(ltime, fuzzydate));
+}
bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{
@@ -632,65 +668,24 @@ void Item::init_make_field(Send_field *tmp_field,
tmp_field->flags |= UNSIGNED_FLAG;
}
-/* ARGSUSED */
-void Item_field::make_field(Send_field *tmp_field)
-{
- field->make_field(tmp_field);
- if (name)
- tmp_field->col_name=name; // Use user supplied name
-}
-
-void Item_int::make_field(Send_field *tmp_field)
-{
- init_make_field(tmp_field,FIELD_TYPE_LONGLONG);
-}
-
-void Item_uint::make_field(Send_field *tmp_field)
+void Item::make_field(Send_field *tmp_field)
{
- init_make_field(tmp_field,FIELD_TYPE_LONGLONG);
- tmp_field->flags|= UNSIGNED_FLAG;
- unsigned_flag=1;
+ init_make_field(tmp_field, field_type());
}
-void Item_real::make_field(Send_field *tmp_field)
+enum_field_types Item::field_type() const
{
- init_make_field(tmp_field,FIELD_TYPE_DOUBLE);
+ return ((result_type() == STRING_RESULT) ? FIELD_TYPE_VAR_STRING :
+ (result_type() == INT_RESULT) ? FIELD_TYPE_LONGLONG :
+ FIELD_TYPE_DOUBLE);
}
-void Item_string::make_field(Send_field *tmp_field)
-{
- init_make_field(tmp_field,FIELD_TYPE_STRING);
-}
-
-void Item_datetime::make_field(Send_field *tmp_field)
-{
- init_make_field(tmp_field,FIELD_TYPE_DATETIME);
-}
-
-
-void Item_null::make_field(Send_field *tmp_field)
-{
- init_make_field(tmp_field,FIELD_TYPE_NULL);
- tmp_field->length=4;
-}
-
-
-void Item_func::make_field(Send_field *tmp_field)
-{
- init_make_field(tmp_field, ((result_type() == STRING_RESULT) ?
- FIELD_TYPE_VAR_STRING :
- (result_type() == INT_RESULT) ?
- FIELD_TYPE_LONGLONG : FIELD_TYPE_DOUBLE));
-}
-
-void Item_avg_field::make_field(Send_field *tmp_field)
-{
- init_make_field(tmp_field,FIELD_TYPE_DOUBLE);
-}
-
-void Item_std_field::make_field(Send_field *tmp_field)
+/* ARGSUSED */
+void Item_field::make_field(Send_field *tmp_field)
{
- init_make_field(tmp_field,FIELD_TYPE_DOUBLE);
+ field->make_field(tmp_field);
+ if (name)
+ tmp_field->col_name=name; // Use user supplied name
}
/*
@@ -899,31 +894,118 @@ int Item_varbinary::save_in_field(Field *field, bool no_conversions)
}
-void Item_varbinary::make_field(Send_field *tmp_field)
+/*
+ Pack data in buffer for sending
+*/
+
+bool Item_null::send(Protocol *protocol, String *packet)
{
- init_make_field(tmp_field,FIELD_TYPE_STRING);
+ return protocol->store_null();
}
/*
-** pack data in buffer for sending
+ This is only called from items that is not of type item_field
*/
-bool Item::send(THD *thd, String *packet)
+bool Item::send(Protocol *protocol, String *buffer)
{
- char buff[MAX_FIELD_WIDTH];
- CONVERT *convert;
- String s(buff,sizeof(buff),packet->charset()),*res;
- if (!(res=val_str(&s)))
- return net_store_null(packet);
- if ((convert=thd->variables.convert_set))
- return convert->store(packet,res->ptr(),res->length());
- return net_store_data(packet,res->ptr(),res->length());
+ bool result;
+ enum_field_types type;
+ LINT_INIT(result);
+
+ switch ((type=field_type())) {
+ default:
+ case MYSQL_TYPE_NULL:
+ case MYSQL_TYPE_DECIMAL:
+ case MYSQL_TYPE_ENUM:
+ case MYSQL_TYPE_SET:
+ case MYSQL_TYPE_TINY_BLOB:
+ case MYSQL_TYPE_MEDIUM_BLOB:
+ case MYSQL_TYPE_LONG_BLOB:
+ case MYSQL_TYPE_BLOB:
+ case MYSQL_TYPE_GEOMETRY:
+ case MYSQL_TYPE_STRING:
+ case MYSQL_TYPE_VAR_STRING:
+ {
+ String *res;
+ if ((res=val_str(buffer)))
+ result= protocol->store(res->ptr(),res->length());
+ break;
+ }
+ case MYSQL_TYPE_TINY:
+ {
+ longlong nr;
+ nr= val_int();
+ if (!null_value)
+ result= protocol->store_tiny(nr);
+ break;
+ }
+ case MYSQL_TYPE_SHORT:
+ {
+ longlong nr;
+ nr= val_int();
+ if (!null_value)
+ result= protocol->store_short(nr);
+ break;
+ }
+ case MYSQL_TYPE_INT24:
+ case MYSQL_TYPE_LONG:
+ {
+ longlong nr;
+ nr= val_int();
+ if (!null_value)
+ result= protocol->store_long(nr);
+ break;
+ }
+ case MYSQL_TYPE_LONGLONG:
+ {
+ longlong nr;
+ nr= val_int();
+ if (!null_value)
+ result= protocol->store_longlong(nr, unsigned_flag);
+ break;
+ }
+ case MYSQL_TYPE_DOUBLE:
+ {
+ double nr;
+ nr= val();
+ if (!null_value)
+ result= protocol->store(nr, decimals, buffer);
+ break;
+ }
+ case MYSQL_TYPE_DATETIME:
+ case MYSQL_TYPE_DATE:
+ case MYSQL_TYPE_TIMESTAMP:
+ {
+ TIME tm;
+ get_date(&tm, 1);
+ if (!null_value)
+ {
+ if (type == MYSQL_TYPE_DATE)
+ return protocol->store_date(&tm);
+ else
+ result= protocol->store(&tm);
+ }
+ break;
+ }
+ case MYSQL_TYPE_TIME:
+ {
+ TIME tm;
+ get_time(&tm);
+ if (!null_value)
+ result= protocol->store_time(&tm);
+ break;
+ }
+ }
+ if (null_value)
+ result= protocol->store_null();
+ return result;
}
-bool Item_null::send(THD *thd, String *packet)
+bool Item_field::send(Protocol *protocol, String *buffer)
{
- return net_store_null(packet);
+ return protocol->store(result_field);
}
#ifdef EMBEDDED_LIBRARY
@@ -985,7 +1067,6 @@ bool Item_field::embedded_send(const CONVERT *convert, CHARSET_INFO *charset, ME
#endif
-
/*
This is used for HAVING clause
Find field in select list having the same name
diff --git a/sql/item.h b/sql/item.h
index 8c7cc2a2f68..47c7541d3e3 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -20,6 +20,8 @@
#endif
class CONVERT;
+class Protocol;
+struct st_table_list;
void item_init(void); /* Init item functions */
class Item {
@@ -33,7 +35,8 @@ public:
enum Type {FIELD_ITEM,FUNC_ITEM,SUM_FUNC_ITEM,STRING_ITEM,
INT_ITEM,REAL_ITEM,NULL_ITEM,VARBIN_ITEM,
COPY_STR_ITEM,FIELD_AVG_ITEM, DEFAULT_ITEM,
- PROC_ITEM,COND_ITEM,REF_ITEM,FIELD_STD_ITEM, CONST_ITEM,
+ PROC_ITEM,COND_ITEM,REF_ITEM,FIELD_STD_ITEM,
+ FIELD_VARIANCE_ITEM,CONST_ITEM,
SUBSELECT_ITEM, ROW_ITEM};
enum cond_result { COND_UNDEF,COND_OK,COND_TRUE,COND_FALSE };
@@ -53,30 +56,30 @@ public:
virtual ~Item() { name=0; } /*lint -e1509 */
void set_name(const char *str,uint length=0);
void init_make_field(Send_field *tmp_field,enum enum_field_types type);
+ virtual void make_field(Send_field *field);
virtual bool fix_fields(THD *, struct st_table_list *, Item **);
virtual int save_in_field(Field *field, bool no_conversions);
virtual void save_org_in_field(Field *field)
{ (void) save_in_field(field, 1); }
virtual int save_safe_in_field(Field *field)
{ return save_in_field(field, 1); }
- virtual bool send(THD *thd, String *str);
+ virtual bool send(Protocol *protocol, String *str);
#ifdef EMBEDDED_LIBRARY
virtual bool embedded_send(const CONVERT *convert, CHARSET_INFO *charset, MEM_ROOT *alloc,
char **result, ulong *length);
#endif
virtual bool eq(const Item *, bool binary_cmp) const;
virtual Item_result result_type () const { return REAL_RESULT; }
+ virtual enum_field_types field_type() const;
virtual enum Type type() const =0;
virtual double val()=0;
virtual longlong val_int()=0;
virtual String *val_str(String*)=0;
- virtual void make_field(Send_field *field)=0;
virtual Field *tmp_table_field(TABLE *t_arg=(TABLE *)0) { return 0; }
virtual const char *full_name() const { return name ? name : "???"; }
virtual double val_result() { return val(); }
virtual longlong val_int_result() { return val_int(); }
virtual String *str_result(String* tmp) { return val_str(tmp); }
- virtual bool is_null_result() { return is_null(); }
virtual table_map used_tables() const { return (table_map) 0L; }
virtual bool basic_const_item() const { return 0; }
virtual Item *new_item() { return 0; } /* Only for const items */
@@ -104,6 +107,8 @@ public:
virtual Item* el(uint i) { return this; }
virtual Item** addr(uint i) { return 0; }
virtual bool check_cols(uint c);
+ // It is not row => null inside is impossible
+ virtual bool null_inside() { return 0; };
};
@@ -121,11 +126,30 @@ public:
item (it assign '*ref' with field 'item' in derived classes)
*/
enum Type type() const { return item->type(); }
+ enum_field_types field_type() const { return item->field_type(); }
double val() { return item->val(); }
longlong val_int() { return item->val_int(); }
String* val_str(String* s) { return item->val_str(s); }
- void make_field(Send_field* f) { item->make_field(f); }
bool check_cols(uint col) { return item->check_cols(col); }
+ bool eq(const Item *item, bool binary_cmp) const
+ { return item->eq(item, binary_cmp); }
+ bool is_null()
+ {
+ item->val_int();
+ return item->null_value;
+ }
+ bool get_date(TIME *ltime, bool fuzzydate)
+ {
+ return (null_value=item->get_date(ltime, fuzzydate));
+ }
+ bool send(Protocol *prot, String *tmp) { return item->send(prot, tmp); }
+ int save_in_field(Field *field, bool no_conversions)
+ {
+ return item->save_in_field(field, no_conversions);
+ }
+ void save_org_in_field(Field *field) { item->save_org_in_field(field); }
+ enum Item_result result_type () const { return item->result_type(); }
+ table_map used_tables() const { return item->used_tables(); }
};
@@ -142,19 +166,6 @@ public:
bool fix_fields(THD *, struct st_table_list *, Item ** ref);
};
-/*
- To resolve '*' field moved to condition
-*/
-class Item_asterisk_remover :public Item_wrapper
-{
-public:
- Item_asterisk_remover(Item *it)
- {
- item= it;
- }
- bool fix_fields(THD *, struct st_table_list *, Item ** ref);
-};
-
class st_select_lex;
class Item_ident :public Item
{
@@ -192,17 +203,13 @@ public:
double val_result();
longlong val_int_result();
String *str_result(String* tmp);
- bool is_null_result() { return result_field->is_null(); }
- bool send(THD *thd, String *str_arg)
- {
- return result_field->send(thd,str_arg);
- }
+ bool send(Protocol *protocol, String *str_arg);
#ifdef EMBEDDED_LIBRARY
bool embedded_send(const CONVERT *convert, CHARSET_INFO *charset, MEM_ROOT *alloc,
char **result, ulong *length);
#endif
- void make_field(Send_field *field);
bool fix_fields(THD *, struct st_table_list *, Item **);
+ void make_field(Send_field *tmp_field);
int save_in_field(Field *field,bool no_conversions);
void save_org_in_field(Field *field);
table_map used_tables() const;
@@ -210,6 +217,10 @@ public:
{
return field->result_type();
}
+ enum_field_types field_type() const
+ {
+ return field->type();
+ }
Field *tmp_table_field(TABLE *t_arg=(TABLE *)0) { return result_field; }
bool get_date(TIME *ltime,bool fuzzydate);
bool get_time(TIME *ltime);
@@ -227,16 +238,21 @@ public:
double val();
longlong val_int();
String *val_str(String *str);
- void make_field(Send_field *field);
int save_in_field(Field *field, bool no_conversions);
int save_safe_in_field(Field *field);
- enum Item_result result_type () const
- { return STRING_RESULT; }
- bool send(THD *thd, String *str);
+ bool send(Protocol *protocol, String *str);
#ifdef EMBEDDED_LIBRARY
bool embedded_send(const CONVERT *convert, CHARSET_INFO *charset, MEM_ROOT *alloc,
char **result, ulong *length);
#endif
+ enum Item_result result_type () const { return STRING_RESULT; }
+ enum_field_types field_type() const { return MYSQL_TYPE_NULL; }
+ bool fix_fields(THD *thd, struct st_table_list *list, Item **item)
+ {
+ bool res= Item::fix_fields(thd, list, item);
+ max_length=0;
+ return res;
+ }
bool basic_const_item() const { return 1; }
Item *new_item() { return new Item_null(name); }
bool is_null() { return 1; }
@@ -263,7 +279,6 @@ public:
double val();
longlong val_int();
String *val_str(String*);
- void make_field(Send_field *field);
int save_in_field(Field *field, bool no_conversions);
void set_null();
void set_int(longlong i);
@@ -277,6 +292,7 @@ public:
void (*setup_param_func)(Item_param *param, uchar **pos);
enum Item_result result_type () const
{ return item_result_type; }
+ enum_field_types field_type() const { return MYSQL_TYPE_STRING; }
Item *new_item() { return new Item_param(name); }
};
@@ -297,11 +313,11 @@ public:
(longlong) strtoull(str_arg,(char**) 0,10))
{ max_length= (uint) strlen(str_arg); name=(char*) str_arg;}
enum Type type() const { return INT_ITEM; }
- virtual enum Item_result result_type () const { return INT_RESULT; }
+ enum Item_result result_type () const { return INT_RESULT; }
+ enum_field_types field_type() const { return MYSQL_TYPE_LONGLONG; }
longlong val_int() { return value; }
double val() { return (double) value; }
String *val_str(String*);
- void make_field(Send_field *field);
int save_in_field(Field *field, bool no_conversions);
bool basic_const_item() const { return 1; }
Item *new_item() { return new Item_int(name,value,max_length); }
@@ -317,8 +333,13 @@ public:
Item_uint(uint32 i) :Item_int((longlong) i, 10) {}
double val() { return ulonglong2double(value); }
String *val_str(String*);
- void make_field(Send_field *field);
Item *new_item() { return new Item_uint(name,max_length); }
+ bool fix_fields(THD *thd, struct st_table_list *list, Item **item)
+ {
+ bool res= Item::fix_fields(thd, list, item);
+ unsigned_flag= 1;
+ return res;
+ }
void print(String *str);
};
@@ -344,10 +365,10 @@ public:
Item_real(double value_par) :value(value_par) {}
int save_in_field(Field *field, bool no_conversions);
enum Type type() const { return REAL_ITEM; }
+ enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
double val() { return value; }
longlong val_int() { return (longlong) (value+(value > 0 ? 0.5 : -0.5));}
String *val_str(String*);
- void make_field(Send_field *field);
bool basic_const_item() const { return 1; }
Item *new_item() { return new Item_real(name,value,decimals,max_length); }
};
@@ -392,13 +413,17 @@ public:
}
String *val_str(String*) { return (String*) &str_value; }
int save_in_field(Field *field, bool no_conversions);
- void make_field(Send_field *field);
enum Item_result result_type () const { return STRING_RESULT; }
+ enum_field_types field_type() const { return MYSQL_TYPE_STRING; }
bool basic_const_item() const { return 1; }
bool eq(const Item *item, bool binary_cmp) const;
- Item *new_item() { return new Item_string(name,str_value.ptr(),max_length,default_charset_info); }
+ Item *new_item()
+ {
+ return new Item_string(name, str_value.ptr(), max_length,
+ default_charset_info);
+ }
String *const_string() { return &str_value; }
- inline void append(char *str,uint length) { str_value.append(str,length); }
+ inline void append(char *str, uint length) { str_value.append(str, length); }
void print(String *str);
};
@@ -410,7 +435,6 @@ class Item_default :public Item
public:
Item_default() { name= (char*) "DEFAULT"; }
enum Type type() const { return DEFAULT_ITEM; }
- void make_field(Send_field *field) {}
int save_in_field(Field *field, bool no_conversions)
{
field->set_default();
@@ -430,7 +454,7 @@ class Item_datetime :public Item_string
public:
Item_datetime(const char *item_name): Item_string(item_name,"",0,default_charset_info)
{ max_length=19;}
- void make_field(Send_field *field);
+ enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; }
};
class Item_empty_string :public Item_string
@@ -440,6 +464,20 @@ public:
{ name=(char*) header; max_length=length;}
};
+class Item_return_int :public Item_int
+{
+ enum_field_types int_field_type;
+public:
+ Item_return_int(const char *name, uint length,
+ enum_field_types field_type_arg)
+ :Item_int(name, 0, length), int_field_type(field_type_arg)
+ {
+ unsigned_flag=1;
+ }
+ enum_field_types field_type() const { return int_field_type; }
+};
+
+
class Item_varbinary :public Item
{
public:
@@ -450,8 +488,8 @@ public:
longlong val_int();
String *val_str(String*) { return &str_value; }
int save_in_field(Field *field, bool no_conversions);
- void make_field(Send_field *field);
enum Item_result result_type () const { return INT_RESULT; }
+ enum_field_types field_type() const { return MYSQL_TYPE_STRING; }
};
@@ -482,31 +520,31 @@ public:
double val()
{
double tmp=(*ref)->val_result();
- null_value=(*ref)->is_null_result();
+ null_value=(*ref)->null_value;
return tmp;
}
longlong val_int()
{
longlong tmp=(*ref)->val_int_result();
- null_value=(*ref)->is_null_result();
+ null_value=(*ref)->null_value;
return tmp;
}
String *val_str(String* tmp)
{
tmp=(*ref)->str_result(tmp);
- null_value=(*ref)->is_null_result();
+ null_value=(*ref)->null_value;
return tmp;
}
bool is_null()
{
(void) (*ref)->val_int_result();
- return (*ref)->is_null_result();
+ return (*ref)->null_value;
}
bool get_date(TIME *ltime,bool fuzzydate)
{
return (null_value=(*ref)->get_date(ltime,fuzzydate));
}
- bool send(THD *thd, String *tmp) { return (*ref)->send(thd, tmp); }
+ bool send(Protocol *prot, String *tmp){ return (*ref)->send(prot, tmp); }
#ifdef EMBEDDED_LIBRARY
bool embedded_send(const CONVERT *convert, CHARSET_INFO *charset, MEM_ROOT *alloc,
char **result, ulong *length)
@@ -518,10 +556,59 @@ public:
{ return (*ref)->save_in_field(field, no_conversions); }
void save_org_in_field(Field *field) { (*ref)->save_org_in_field(field); }
enum Item_result result_type () const { return (*ref)->result_type(); }
+ enum_field_types field_type() const { return (*ref)->field_type(); }
table_map used_tables() const { return (*ref)->used_tables(); }
bool check_loop(uint id);
};
+class Item_in_subselect;
+class Item_ref_null_helper: public Item_ref
+{
+protected:
+ Item_in_subselect* owner;
+public:
+ Item_ref_null_helper(Item_in_subselect* master, Item **item,
+ char *table_name_par,char *field_name_par):
+ Item_ref(item, table_name_par, field_name_par), owner(master) {}
+ double val();
+ longlong val_int();
+ String* val_str(String* s);
+ bool get_date(TIME *ltime, bool fuzzydate);
+};
+
+/*
+ To resolve '*' field moved to condition
+ and register NULL values
+*/
+class Item_asterisk_remover :public Item_ref_null_helper
+{
+ Item *item;
+public:
+ Item_asterisk_remover(Item_in_subselect *master, Item *it,
+ char *table, char *field):
+ Item_ref_null_helper(master, &item, table, field),
+ item(it)
+ {}
+ bool fix_fields(THD *, struct st_table_list *, Item ** ref);
+};
+
+class Item_in_optimizer;
+class Item_ref_in_optimizer: public Item_ref
+{
+protected:
+ Item_in_optimizer* owner;
+public:
+ Item_ref_in_optimizer(Item_in_optimizer* master,
+ char *table_name_par,char *field_name_par);
+ double val();
+ longlong val_int();
+ String* val_str(String* s);
+ bool fix_fields(THD *, struct st_table_list *, Item ** ref)
+ {
+ fixed= 1;
+ return 0;
+ }
+};
/*
The following class is used to optimize comparing of date columns
@@ -555,6 +642,7 @@ public:
class Item_copy_string :public Item
{
+ enum enum_field_types cached_field_type;
public:
Item *item;
Item_copy_string(Item *i) :item(i)
@@ -563,10 +651,12 @@ public:
decimals=item->decimals;
max_length=item->max_length;
name=item->name;
+ cached_field_type= item->field_type();
}
~Item_copy_string() { delete item; }
enum Type type() const { return COPY_STR_ITEM; }
enum Item_result result_type () const { return STRING_RESULT; }
+ enum_field_types field_type() const { return cached_field_type; }
double val()
{ return null_value ? 0.0 : my_strntod(str_value.charset(),str_value.ptr(),str_value.length(),NULL); }
longlong val_int()
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index dd8d1aeff02..a30faae9a01 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -90,7 +90,7 @@ static bool convert_constant_item(Field *field, Item **item)
void Item_bool_func2::fix_length_and_dec()
{
- max_length=1; // Function returns 0 or 1
+ max_length= 1; // Function returns 0 or 1
/*
As some compare functions are generated after sql_yacc,
@@ -144,7 +144,14 @@ int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type)
}
if ((comparators= (Arg_comparator *) sql_alloc(sizeof(Arg_comparator)*n)))
for (uint i=0; i < n; i++)
+ {
+ if ((*a)->el(i)->cols() != (*b)->el(i)->cols())
+ {
+ my_error(ER_CARDINALITY_COL, MYF(0), (*a)->el(i)->cols());
+ return 1;
+ }
comparators[i].set_cmp_func(owner, (*a)->addr(i), (*b)->addr(i));
+ }
else
{
my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
@@ -263,6 +270,61 @@ int Arg_comparator::compare_e_row()
return 1;
}
+longlong Item_in_optimizer::val_int()
+{
+ int_cache_ok= 1;
+ flt_cache_ok= 0;
+ str_cache_ok= 0;
+ int_cache= args[0]->val_int_result();
+ if (args[0]->null_value)
+ {
+ null_value= 1;
+ return 0;
+ }
+ longlong tmp= args[1]->val_int_result();
+ null_value= args[1]->null_value;
+ return tmp;
+}
+
+longlong Item_in_optimizer::get_cache_int()
+{
+ if (!int_cache_ok)
+ {
+ int_cache_ok= 1;
+ flt_cache_ok= 0;
+ str_cache_ok= 0;
+ int_cache= args[0]->val_int_result();
+ null_value= args[0]->null_value;
+ }
+ return int_cache;
+}
+
+double Item_in_optimizer::get_cache()
+{
+ if (!flt_cache_ok)
+ {
+ flt_cache_ok= 1;
+ int_cache_ok= 0;
+ str_cache_ok= 0;
+ flt_cache= args[0]->val_result();
+ null_value= args[0]->null_value;
+ }
+ return flt_cache;
+}
+
+String *Item_in_optimizer::get_cache_str(String *s)
+{
+ if (!str_cache_ok)
+ {
+ str_cache_ok= 1;
+ int_cache_ok= 0;
+ flt_cache_ok= 0;
+ str_value.set(buffer, sizeof(buffer), s->charset());
+ str_cache= args[0]->str_result(&str_value);
+ null_value= args[0]->null_value;
+ }
+ return str_cache;
+}
longlong Item_func_eq::val_int()
{
@@ -356,7 +418,8 @@ void Item_func_interval::fix_length_and_dec()
intervals[i]=args[i]->val();
}
}
- maybe_null=0; max_length=2;
+ maybe_null= 0;
+ max_length= 2;
used_tables_cache|=item->used_tables();
}
@@ -415,7 +478,7 @@ bool Item_func_interval::check_loop(uint id)
void Item_func_between::fix_length_and_dec()
{
- max_length=1;
+ max_length= 1;
/*
As some compare functions are generated after sql_yacc,
@@ -968,8 +1031,8 @@ double Item_func_coalesce::val()
void Item_func_coalesce::fix_length_and_dec()
{
- max_length=0;
- decimals=0;
+ max_length= 0;
+ decimals= 0;
cached_result_type = args[0]->result_type();
for (uint i=0 ; i < arg_count ; i++)
{
@@ -992,6 +1055,11 @@ static int cmp_double(double *a,double *b)
return *a < *b ? -1 : *a == *b ? 0 : 1;
}
+static int cmp_row(cmp_item_row* a, cmp_item_row* b)
+{
+ return a->compare(b);
+}
+
int in_vector::find(Item *item)
{
byte *result=get_value(item);
@@ -1014,7 +1082,6 @@ int in_vector::find(Item *item)
return (int) ((*compare)(base+start*size,result) == 0);
}
-
in_string::in_string(uint elements,qsort_cmp cmp_func)
:in_vector(elements,sizeof(String),cmp_func),tmp(buff,sizeof(buff),default_charset_info)
{}
@@ -1041,6 +1108,29 @@ byte *in_string::get_value(Item *item)
return (byte*) item->val_str(&tmp);
}
+in_row::in_row(uint elements, Item * item)
+{
+ DBUG_ENTER("in_row::in_row");
+ base= (char*) new cmp_item_row[elements];
+ size= sizeof(cmp_item_row);
+ compare= (qsort_cmp) cmp_row;
+ tmp.store_value(item);
+ DBUG_VOID_RETURN;
+}
+
+byte *in_row::get_value(Item *item)
+{
+ tmp.store_value(item);
+ return (byte *)&tmp;
+}
+
+void in_row::set(uint pos, Item *item)
+{
+ DBUG_ENTER("in_row::set");
+ DBUG_PRINT("enter", ("pos %u item 0x%lx", pos, (ulong) item));
+ ((cmp_item_row*) base)[pos].store_value_by_template(&tmp, item);
+ DBUG_VOID_RETURN;
+}
in_longlong::in_longlong(uint elements)
:in_vector(elements,sizeof(longlong),(qsort_cmp) cmp_longlong)
@@ -1053,13 +1143,12 @@ void in_longlong::set(uint pos,Item *item)
byte *in_longlong::get_value(Item *item)
{
- tmp=item->val_int();
+ tmp= item->val_int();
if (item->null_value)
- return 0; /* purecov: inspected */
+ return 0;
return (byte*) &tmp;
}
-
in_double::in_double(uint elements)
:in_vector(elements,sizeof(double),(qsort_cmp) cmp_double)
{}
@@ -1071,21 +1160,173 @@ void in_double::set(uint pos,Item *item)
byte *in_double::get_value(Item *item)
{
- tmp=item->val();
+ tmp= item->val();
if (item->null_value)
return 0; /* purecov: inspected */
return (byte*) &tmp;
}
+cmp_item* cmp_item::get_comparator (Item *item)
+{
+ switch (item->result_type()) {
+ case STRING_RESULT:
+ if (item->binary())
+ return new cmp_item_binary_string;
+ else
+ return new cmp_item_sort_string;
+ break;
+ case INT_RESULT:
+ return new cmp_item_int;
+ break;
+ case REAL_RESULT:
+ return new cmp_item_real;
+ break;
+ case ROW_RESULT:
+ return new cmp_item_row;
+ break;
+ }
+ return 0; // to satisfy compiler :)
+}
+
+cmp_item* cmp_item_sort_string::make_same()
+{
+ return new cmp_item_sort_string_in_static();
+}
+
+cmp_item* cmp_item_binary_string::make_same()
+{
+ return new cmp_item_binary_string_in_static();
+}
+
+cmp_item* cmp_item_int::make_same()
+{
+ return new cmp_item_int();
+}
+
+cmp_item* cmp_item_real::make_same()
+{
+ return new cmp_item_real();
+}
+
+cmp_item* cmp_item_row::make_same()
+{
+ return new cmp_item_row();
+}
+
+void cmp_item_row::store_value(Item *item)
+{
+ THD *thd= current_thd;
+ n= item->cols();
+ if ((comparators= (cmp_item **) thd->alloc(sizeof(cmp_item *)*n)))
+ {
+ item->null_value= 0;
+ for (uint i=0; i < n; i++)
+ if ((comparators[i]= cmp_item::get_comparator(item->el(i))))
+ {
+ comparators[i]->store_value(item->el(i));
+ item->null_value|= item->el(i)->null_value;
+ }
+ else
+ {
+ my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
+ thd->fatal_error= 1;
+ return;
+ }
+ }
+ else
+ {
+ my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
+ thd->fatal_error= 1;
+ return;
+ }
+}
+
+void cmp_item_row::store_value_by_template(cmp_item *t, Item *item)
+{
+ cmp_item_row *tmpl= (cmp_item_row*) t;
+ if (tmpl->n != item->cols())
+ {
+ my_error(ER_CARDINALITY_COL, MYF(0), tmpl->n);
+ return;
+ }
+ n= tmpl->n;
+ if ((comparators= (cmp_item **) sql_alloc(sizeof(cmp_item *)*n)))
+ {
+ item->null_value= 0;
+ for (uint i=0; i < n; i++)
+ if ((comparators[i]= tmpl->comparators[i]->make_same()))
+ {
+ comparators[i]->store_value_by_template(tmpl->comparators[i],
+ item->el(i));
+ item->null_value|= item->el(i)->null_value;
+ }
+ else
+ {
+ my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
+ current_thd->fatal_error= 1;
+ return;
+ }
+ }
+ else
+ {
+ my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
+ current_thd->fatal_error= 1;
+ return;
+ }
+}
+
+int cmp_item_row::cmp(Item *arg)
+{
+ arg->null_value= 0;
+ if (arg->cols() != n)
+ {
+ my_error(ER_CARDINALITY_COL, MYF(0), n);
+ return 1;
+ }
+ bool was_null= 0;
+ for (uint i=0; i < n; i++)
+ if (comparators[i]->cmp(arg->el(i)))
+ {
+ if (!arg->el(i)->null_value)
+ return 1;
+ was_null= 1;
+ }
+ return (arg->null_value= was_null);
+}
+
+int cmp_item_row::compare(cmp_item *c)
+{
+ int res;
+ cmp_item_row *cmp= (cmp_item_row *) c;
+ for (uint i=0; i < n; i++)
+ if ((res= comparators[i]->compare(cmp->comparators[i])))
+ return res;
+ return 0;
+}
+
+bool Item_func_in::nulls_in_row()
+{
+ Item **arg,**arg_end;
+ for (arg= args, arg_end= args+arg_count; arg != arg_end ; arg++)
+ {
+ if ((*arg)->null_inside())
+ return 1;
+ }
+ return 0;
+}
void Item_func_in::fix_length_and_dec()
{
- if (const_item())
+ /*
+ Row item with NULLs inside can return NULL or FALSE =>
+ they can't be processed as static
+ */
+ if (const_item() && !nulls_in_row())
{
switch (item->result_type()) {
case STRING_RESULT:
if (item->binary())
- array=new in_string(arg_count,(qsort_cmp) stringcmp); /* purecov: inspected */
+ array=new in_string(arg_count,(qsort_cmp) stringcmp);
else
array=new in_string(arg_count,(qsort_cmp) sortcmp);
break;
@@ -1096,8 +1337,7 @@ void Item_func_in::fix_length_and_dec()
array= new in_double(arg_count);
break;
case ROW_RESULT:
- // This case should never be choosen
- DBUG_ASSERT(0);
+ array= new in_row(arg_count, item);
break;
}
uint j=0;
@@ -1106,33 +1346,18 @@ void Item_func_in::fix_length_and_dec()
array->set(j,args[i]);
if (!args[i]->null_value) // Skip NULL values
j++;
+ else
+ have_null= 1;
}
if ((array->used_count=j))
array->sort();
}
else
{
- switch (item->result_type()) {
- case STRING_RESULT:
- if (item->binary())
- in_item= new cmp_item_binary_string;
- else
- in_item= new cmp_item_sort_string;
- break;
- case INT_RESULT:
- in_item= new cmp_item_int;
- break;
- case REAL_RESULT:
- in_item= new cmp_item_real;
- break;
- case ROW_RESULT:
- // This case should never be choosen
- DBUG_ASSERT(0);
- break;
- }
+ in_item= cmp_item:: get_comparator(item);
}
maybe_null= item->maybe_null;
- max_length=2;
+ max_length= 1;
used_tables_cache|=item->used_tables();
const_item_cache&=item->const_item();
}
@@ -1152,17 +1377,20 @@ longlong Item_func_in::val_int()
if (array)
{
int tmp=array->find(item);
- null_value=item->null_value;
+ null_value=item->null_value || (!tmp && have_null);
return tmp;
}
in_item->store_value(item);
if ((null_value=item->null_value))
return 0;
+ have_null= 0;
for (uint i=0 ; i < arg_count ; i++)
{
if (!in_item->cmp(args[i]) && !args[i]->null_value)
return 1; // Would maybe be nice with i ?
+ have_null|= args[i]->null_value;
}
+ null_value= have_null;
return 0;
}
@@ -1452,7 +1680,8 @@ longlong Item_func_isnotnull::val_int()
void Item_func_like::fix_length_and_dec()
{
- decimals=0; max_length=1;
+ decimals= 0;
+ max_length= 1;
// cmp_type=STRING_RESULT; // For quick select
}
@@ -1559,7 +1788,8 @@ Item_func_regex::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
args[1]->fix_fields(thd,tables, args + 1))
return 1; /* purecov: inspected */
with_sum_func=args[0]->with_sum_func || args[1]->with_sum_func;
- max_length=1; decimals=0;
+ max_length= 1;
+ decimals= 0;
if (args[0]->binary() || args[1]->binary())
set_charset(my_charset_bin);
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index b4f4872bd95..994e51ef89f 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -17,6 +17,8 @@
/* compare and test functions */
+#include "assert.h"
+
#ifdef __GNUC__
#pragma interface /* gcc class implementation */
#endif
@@ -38,16 +40,12 @@ public:
Arg_comparator() {};
Arg_comparator(Item **a1, Item **a2): a(a1), b(a2) {};
- inline void seta(Item **item) { a= item; }
- inline void setb(Item **item) { b= item; }
-
int set_compare_func(Item_bool_func2 *owner, Item_result type);
inline int set_compare_func(Item_bool_func2 *owner)
{
return set_compare_func(owner, item_cmp_type((*a)->result_type(),
(*b)->result_type()));
}
-
inline int set_cmp_func(Item_bool_func2 *owner,
Item **a1, Item **a2,
Item_result type)
@@ -87,6 +85,27 @@ public:
void fix_length_and_dec() { decimals=0; max_length=1; }
};
+class Item_in_optimizer: public Item_bool_func
+{
+protected:
+ char buffer[80];
+ longlong int_cache;
+ double flt_cache;
+ String *str_cache;
+ bool int_cache_ok, flt_cache_ok, str_cache_ok;
+public:
+ Item_in_optimizer(Item *a,Item *b):
+ Item_bool_func(a,b), int_cache_ok(0), flt_cache_ok(0), str_cache_ok(0) {}
+ bool is_null() { return test(args[0]->is_null() || args[1]->is_null()); }
+ longlong val_int();
+
+ double get_cache();
+ longlong get_cache_int();
+ String *get_cache_str(String *s);
+
+ friend class Item_ref_in_optimizer;
+};
+
class Item_bool_func2 :public Item_int_func
{ /* Bool with 2 string args */
protected:
@@ -358,6 +377,7 @@ class in_vector :public Sql_alloc
uint count;
public:
uint used_count;
+ in_vector() {}
in_vector(uint elements,uint element_length,qsort_cmp cmp_func)
:base((char*) sql_calloc(elements*element_length)),
size(element_length), compare(cmp_func), count(elements),
@@ -372,7 +392,6 @@ public:
int find(Item *item);
};
-
class in_string :public in_vector
{
char buff[80];
@@ -384,7 +403,6 @@ public:
byte *get_value(Item *item);
};
-
class in_longlong :public in_vector
{
longlong tmp;
@@ -394,7 +412,6 @@ public:
byte *get_value(Item *item);
};
-
class in_double :public in_vector
{
double tmp;
@@ -404,7 +421,6 @@ public:
byte *get_value(Item *item);
};
-
/*
** Classes for easy comparing of non const items
*/
@@ -414,88 +430,201 @@ class cmp_item :public Sql_alloc
public:
cmp_item() {}
virtual ~cmp_item() {}
- virtual void store_value(Item *item)=0;
- virtual int cmp(Item *item)=0;
+ virtual void store_value(Item *item)= 0;
+ virtual int cmp(Item *item)= 0;
+ // for optimized IN with row
+ virtual int compare(cmp_item *item)= 0;
+ static cmp_item* get_comparator(Item *);
+ virtual cmp_item *make_same()= 0;
+ virtual void store_value_by_template(cmp_item *tmpl, Item *item)
+ {
+ store_value(item);
+ }
};
+typedef int (*str_cmp_func_pointer)(const String *, const String *);
+class cmp_item_string :public cmp_item
+{
+protected:
+ str_cmp_func_pointer str_cmp_func;
+ String *value_res;
+public:
+ cmp_item_string (str_cmp_func_pointer cmp): str_cmp_func(cmp) {}
+ friend class cmp_item_sort_string;
+ friend class cmp_item_binary_string;
+ friend class cmp_item_sort_string_in_static;
+ friend class cmp_item_binary_string_in_static;
+};
-class cmp_item_sort_string :public cmp_item {
- protected:
+class cmp_item_sort_string :public cmp_item_string
+{
+protected:
char value_buff[80];
- String value,*value_res;
-public:
- cmp_item_sort_string() :value(value_buff,sizeof(value_buff),default_charset_info) {}
+ String value;
+public:
+ cmp_item_sort_string(str_cmp_func_pointer cmp):
+ cmp_item_string(cmp),
+ value(value_buff, sizeof(value_buff), default_charset_info) {}
+ cmp_item_sort_string():
+ cmp_item_string(&sortcmp),
+ value(value_buff, sizeof(value_buff), default_charset_info) {}
void store_value(Item *item)
- {
- value_res=item->val_str(&value);
- }
+ {
+ value_res= item->val_str(&value);
+ }
int cmp(Item *arg)
- {
- char buff[80];
- String tmp(buff,sizeof(buff),default_charset_info),*res;
- if (!(res=arg->val_str(&tmp)))
- return 1; /* Can't be right */
- return sortcmp(value_res,res);
- }
+ {
+ char buff[80];
+ String tmp(buff, sizeof(buff), default_charset_info), *res;
+ if (!(res= arg->val_str(&tmp)))
+ return 1; /* Can't be right */
+ return (*str_cmp_func)(value_res, res);
+ }
+ int compare(cmp_item *c)
+ {
+ cmp_item_string *cmp= (cmp_item_string *)c;
+ return (*str_cmp_func)(value_res, cmp->value_res);
+ }
+ cmp_item *make_same();
};
class cmp_item_binary_string :public cmp_item_sort_string {
public:
- cmp_item_binary_string() {}
- int cmp(Item *arg)
- {
- char buff[80];
- String tmp(buff,sizeof(buff),default_charset_info),*res;
- if (!(res=arg->val_str(&tmp)))
- return 1; /* Can't be right */
- return stringcmp(value_res,res);
- }
+ cmp_item_binary_string(): cmp_item_sort_string(&stringcmp) {}
+ cmp_item *make_same();
};
-
class cmp_item_int :public cmp_item
{
longlong value;
public:
void store_value(Item *item)
- {
- value=item->val_int();
- }
+ {
+ value= item->val_int();
+ }
int cmp(Item *arg)
- {
- return value != arg->val_int();
- }
+ {
+ return value != arg->val_int();
+ }
+ int compare(cmp_item *c)
+ {
+ cmp_item_int *cmp= (cmp_item_int *)c;
+ return (value < cmp->value) ? -1 : ((value == cmp->value) ? 0 : 1);
+ }
+ cmp_item *make_same();
};
-
class cmp_item_real :public cmp_item
{
double value;
public:
void store_value(Item *item)
- {
- value= item->val();
- }
+ {
+ value= item->val();
+ }
int cmp(Item *arg)
- {
- return value != arg->val();
- }
+ {
+ return value != arg->val();
+ }
+ int compare(cmp_item *c)
+ {
+ cmp_item_real *cmp= (cmp_item_real *)c;
+ return (value < cmp->value)? -1 : ((value == cmp->value) ? 0 : 1);
+ }
+ cmp_item *make_same();
+};
+
+class cmp_item_row :public cmp_item
+{
+ cmp_item **comparators;
+ uint n;
+public:
+ cmp_item_row(): comparators(0), n(0) {}
+ ~cmp_item_row()
+ {
+ if(comparators)
+ for(uint i= 0; i < n; i++)
+ if (comparators[i])
+ delete comparators[i];
+ }
+ void store_value(Item *item);
+ int cmp(Item *arg);
+ int compare(cmp_item *arg);
+ cmp_item *make_same();
+ void store_value_by_template(cmp_item *tmpl, Item *);
+};
+
+
+class in_row :public in_vector
+{
+ cmp_item_row tmp;
+public:
+ in_row(uint elements, Item *);
+ void set(uint pos,Item *item);
+ byte *get_value(Item *item);
};
+/*
+ cmp_item for optimized IN with row (right part string, which never
+ be changed)
+*/
+
+class cmp_item_sort_string_in_static :public cmp_item_string
+{
+ protected:
+ String value;
+public:
+ cmp_item_sort_string_in_static(str_cmp_func_pointer cmp):
+ cmp_item_string(cmp) {}
+ cmp_item_sort_string_in_static(): cmp_item_string(&sortcmp) {}
+ void store_value(Item *item)
+ {
+ value_res= item->val_str(&value);
+ }
+ int cmp(Item *item)
+ {
+ // Should never be called
+ DBUG_ASSERT(0);
+ return 1;
+ }
+ int compare(cmp_item *c)
+ {
+ cmp_item_string *cmp= (cmp_item_string *)c;
+ return (*str_cmp_func)(value_res, cmp->value_res);
+ }
+ cmp_item * make_same()
+ {
+ return new cmp_item_sort_string_in_static();
+ }
+};
+
+class cmp_item_binary_string_in_static :public cmp_item_sort_string_in_static {
+public:
+ cmp_item_binary_string_in_static():
+ cmp_item_sort_string_in_static(&stringcmp) {}
+ cmp_item * make_same()
+ {
+ return new cmp_item_binary_string_in_static();
+ }
+};
class Item_func_in :public Item_int_func
{
Item *item;
in_vector *array;
cmp_item *in_item;
+ bool have_null;
public:
Item_func_in(Item *a,List<Item> &list)
- :Item_int_func(list),item(a),array(0),in_item(0) {}
+ :Item_int_func(list), item(a), array(0), in_item(0), have_null(0)
+ {
+ allowed_arg_cols= item->cols();
+ }
longlong val_int();
bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref)
{
- bool res=(item->check_cols(1) ||
- item->fix_fields(thd, tlist, &item) ||
+ // We do not check item->cols(), because allowed_arg_cols assigned from it
+ bool res=(item->fix_fields(thd, tlist, &item) ||
Item_func::fix_fields(thd, tlist, ref));
with_sum_func= with_sum_func || item->with_sum_func;
return res;
@@ -517,10 +646,9 @@ class Item_func_in :public Item_int_func
DBUG_RETURN(1);
DBUG_RETURN(item->check_loop(id));
}
+ bool nulls_in_row();
};
-
-
/* Functions used by where clause */
class Item_func_isnull :public Item_bool_func
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 0f4239ca560..bcc04aac6a9 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -1947,8 +1947,7 @@ static user_var_entry *get_variable(HASH *hash, LEX_STRING &name,
bool Item_func_set_user_var::fix_fields(THD *thd, TABLE_LIST *tables,
Item **ref)
{
- if (!thd)
- thd=current_thd; // Should never happen
+ /* fix_fields will call Item_func_set_user_var::fix_length_and_dec */
if (Item_func::fix_fields(thd, tables, ref) ||
!(entry= get_variable(&thd->user_vars, name, 1)))
return 1;
diff --git a/sql/item_func.h b/sql/item_func.h
index 98e56af368c..36d6dcbe002 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -106,7 +106,6 @@ public:
Item_func(List<Item> &list);
~Item_func() {} /* Nothing to do; Items are freed automaticly */
bool fix_fields(THD *,struct st_table_list *, Item **ref);
- void make_field(Send_field *field);
table_map used_tables() const;
void update_used_tables();
bool eq(const Item *item, bool binary_cmp) const;
@@ -909,7 +908,9 @@ class Item_func_set_user_var :public Item_func
user_var_entry *entry;
public:
- Item_func_set_user_var(LEX_STRING a,Item *b): Item_func(b), name(a) {}
+ Item_func_set_user_var(LEX_STRING a,Item *b)
+ :Item_func(b), cached_result_type(INT_RESULT), name(a)
+ {}
double val();
longlong val_int();
String *val_str(String *str);
@@ -939,6 +940,11 @@ public:
void fix_length_and_dec();
void print(String *str);
enum Item_result result_type() const;
+ /*
+ We must always return variables as strings to guard against selects of type
+ select @t1:=1,@t1,@t:="hello",@t from foo where (@t1:= t2.b)
+ */
+ enum_field_types field_type() const { return MYSQL_TYPE_STRING; }
const char *func_name() const { return "get_user_var"; }
bool const_item() const { return const_var_flag; }
table_map used_tables() const
diff --git a/sql/item_row.cc b/sql/item_row.cc
index 464a8fd0ec5..85a81a50256 100644
--- a/sql/item_row.cc
+++ b/sql/item_row.cc
@@ -18,8 +18,10 @@
#include "assert.h"
Item_row::Item_row(List<Item> &arg):
- Item(), array_holder(1)
+ Item(), array_holder(1), used_tables_cache(0), const_item_cache(1)
{
+
+ //TODO: think placing 2-3 component items in item (as it done for function)
if ((arg_count= arg.elements))
items= (Item**) sql_alloc(sizeof(Item*)*arg_count);
else
@@ -45,16 +47,31 @@ void Item_row::illegal_method_call(const char *method)
bool Item_row::fix_fields(THD *thd, TABLE_LIST *tabl, Item **ref)
{
- tables= 0;
+ null_value= 0;
+ maybe_null= 0;
for (uint i= 0; i < arg_count; i++)
{
if (items[i]->fix_fields(thd, tabl, items+i))
return 1;
- tables |= items[i]->used_tables();
+ used_tables_cache |= items[i]->used_tables();
+ const_item_cache&= items[i]->const_item();
+ maybe_null|= items[i]->maybe_null;
}
return 0;
}
+void Item_row::update_used_tables()
+{
+ used_tables_cache= 0;
+ const_item_cache= 1;
+ for (uint i= 0; i < arg_count; i++)
+ {
+ items[i]->update_used_tables();
+ used_tables_cache|= items[i]->used_tables();
+ const_item_cache&= items[i]->const_item();
+ }
+}
+
bool Item_row::check_cols(uint c)
{
if (c != arg_count)
@@ -64,3 +81,22 @@ bool Item_row::check_cols(uint c)
}
return 0;
}
+
+bool Item_row::null_inside()
+{
+ for (uint i= 0; i < arg_count; i++)
+ {
+ if (items[i]->cols() > 1)
+ {
+ if (items[i]->null_inside())
+ return 1;
+ }
+ else
+ {
+ items[i]->val_int();
+ if (items[i]->null_value)
+ return 1;
+ }
+ }
+ return 0;
+}
diff --git a/sql/item_row.h b/sql/item_row.h
index 5580250b4fb..4767d19d08f 100644
--- a/sql/item_row.h
+++ b/sql/item_row.h
@@ -17,13 +17,17 @@
class Item_row: public Item
{
bool array_holder;
- table_map tables;
+ table_map used_tables_cache;
+ bool const_item_cache;
uint arg_count;
Item **items;
public:
Item_row(List<Item> &);
Item_row(Item_row *item):
- Item(), array_holder(0), tables(item->tables), arg_count(item->arg_count),
+ Item(), array_holder(0),
+ used_tables_cache(item->used_tables_cache),
+ const_item_cache(item->const_item_cache),
+ arg_count(item->arg_count),
items(item->items)
{}
@@ -56,11 +60,14 @@ public:
return 0;
};
bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref);
- table_map used_tables() const { return tables; };
+ table_map used_tables() const { return used_tables_cache; };
+ bool const_item() const { return const_item_cache; };
enum Item_result result_type() const { return ROW_RESULT; }
+ void update_used_tables();
- virtual uint cols() { return arg_count; }
- virtual Item* el(uint i) { return items[i]; }
- virtual Item** addr(uint i) { return items + i; }
- virtual bool check_cols(uint c);
+ uint cols() { return arg_count; }
+ Item* el(uint i) { return items[i]; }
+ Item** addr(uint i) { return items + i; }
+ bool check_cols(uint c);
+ bool null_inside();
};
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index e087664e060..a8bbc433b7a 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -33,9 +33,10 @@ SUBSELECT TODO:
#include "sql_select.h"
Item_subselect::Item_subselect():
- Item_result_field(), engine_owner(1), value_assigned(0), substitution(0)
+ Item_result_field(), engine_owner(1), value_assigned(0), substitution(0),
+ have_to_be_excluded(0)
{
- assign_null();
+ reset();
/*
item value is NULL if select_subselect not changed this value
(i.e. some rows will be found returned)
@@ -73,28 +74,16 @@ void Item_subselect::select_transformer(st_select_lex *select_lex)
}
-void Item_subselect::make_field (Send_field *tmp_field)
-{
- if (null_value)
- {
- init_make_field(tmp_field,FIELD_TYPE_NULL);
- tmp_field->length=4;
- } else {
- init_make_field(tmp_field, ((result_type() == STRING_RESULT) ?
- FIELD_TYPE_VAR_STRING :
- (result_type() == INT_RESULT) ?
- FIELD_TYPE_LONGLONG : FIELD_TYPE_DOUBLE));
- }
-}
-
bool Item_subselect::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{
if (substitution)
{
(*ref)= substitution;
substitution->name= name;
- engine->exclude();
- return substitution->fix_fields(thd, tables, ref);
+ if (have_to_be_excluded)
+ engine->exclude();
+ substitution= 0;
+ return (*ref)->fix_fields(thd, tables, ref);
}
char const *save_where= thd->where;
@@ -159,7 +148,7 @@ double Item_singleval_subselect::val ()
{
if (engine->exec())
{
- assign_null();
+ reset();
return 0;
}
return real_value;
@@ -169,7 +158,7 @@ longlong Item_singleval_subselect::val_int ()
{
if (engine->exec())
{
- assign_null();
+ reset();
return 0;
}
return int_value;
@@ -179,7 +168,7 @@ String *Item_singleval_subselect::val_str (String *str)
{
if (engine->exec() || null_value)
{
- assign_null();
+ reset();
return 0;
}
return &string_value;
@@ -208,9 +197,8 @@ Item_in_subselect::Item_in_subselect(THD *thd, Item * left_exp,
left_expr= left_exp;
init(thd, select_lex, new select_exists_subselect(this));
max_columns= UINT_MAX;
- null_value= 0; //can't be NULL
- maybe_null= 0; //can't be NULL
- value= 0;
+ maybe_null= 1;
+ reset();
// We need only 1 row to determinate existence
select_lex->master_unit()->global_parameters->select_limit= 1;
DBUG_VOID_RETURN;
@@ -226,9 +214,7 @@ Item_allany_subselect::Item_allany_subselect(THD *thd, Item * left_exp,
func= f;
init(thd, select_lex, new select_exists_subselect(this));
max_columns= UINT_MAX;
- null_value= 0; //can't be NULL
- maybe_null= 0; //can't be NULL
- value= 0;
+ reset();
// We need only 1 row to determinate existence
select_lex->master_unit()->global_parameters->select_limit= 1;
DBUG_VOID_RETURN;
@@ -237,14 +223,15 @@ Item_allany_subselect::Item_allany_subselect(THD *thd, Item * left_exp,
void Item_exists_subselect::fix_length_and_dec()
{
- max_length= 1;
+ decimals=0;
+ max_length= 1;
}
double Item_exists_subselect::val ()
{
if (engine->exec())
{
- assign_null();
+ reset();
return 0;
}
return (double) value;
@@ -254,7 +241,7 @@ longlong Item_exists_subselect::val_int ()
{
if (engine->exec())
{
- assign_null();
+ reset();
return 0;
}
return value;
@@ -264,7 +251,50 @@ String *Item_exists_subselect::val_str(String *str)
{
if (engine->exec())
{
- assign_null();
+ reset();
+ return 0;
+ }
+ str->set(value,thd_charset());
+ return str;
+}
+
+double Item_in_subselect::val ()
+{
+ if (engine->exec())
+ {
+ reset();
+ null_value= 1;
+ return 0;
+ }
+ if (was_null && !value)
+ null_value= 1;
+ return (double) value;
+}
+
+longlong Item_in_subselect::val_int ()
+{
+ if (engine->exec())
+ {
+ reset();
+ null_value= 1;
+ return 0;
+ }
+ if (was_null && !value)
+ null_value= 1;
+ return value;
+}
+
+String *Item_in_subselect::val_str(String *str)
+{
+ if (engine->exec())
+ {
+ reset();
+ null_value= 1;
+ return 0;
+ }
+ if (was_null && !value)
+ {
+ null_value= 1;
return 0;
}
str->set(value,thd_charset());
@@ -288,8 +318,23 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex,
compare_func_creator func)
{
DBUG_ENTER("Item_in_subselect::single_value_transformer");
+ Item_in_optimizer *optimizer;
+ substitution= optimizer= new Item_in_optimizer(left_expr, this);
+ if (!optimizer)
+ {
+ current_thd->fatal_error= 1;
+ DBUG_VOID_RETURN;
+ }
+ /*
+ As far as Item_ref_in_optimizer do not substitude itself on fix_fields
+ we can use same item for all selects.
+ */
+ Item *expr= new Item_ref_in_optimizer(optimizer, (char *)"<no matter>",
+ (char*)"<left expr>");
+ select_lex->master_unit()->dependent= 1;
for (SELECT_LEX * sl= select_lex; sl; sl= sl->next_select())
{
+ select_lex->dependent= 1;
Item *item;
if (sl->item_list.elements > 1)
{
@@ -299,14 +344,14 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex,
else
item= (Item*) sl->item_list.pop();
- Item *expr= new Item_outer_select_context_saver(left_expr);
-
if (sl->having || sl->with_sum_func || sl->group_list.first ||
sl->order_list.first)
{
sl->item_list.push_back(item);
- item= (*func)(expr, new Item_ref(sl->item_list.head_ref(),
- 0, (char*)"<result>"));
+ item= (*func)(expr, new Item_ref_null_helper(this,
+ sl->item_list.head_ref(),
+ (char *)"<no matter>",
+ (char*)"<result>"));
if (sl->having || sl->with_sum_func || sl->group_list.first)
if (sl->having)
sl->having= new Item_cond_and(sl->having, item);
@@ -324,7 +369,9 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex,
sl->item_list.push_back(new Item_int(1));
if (sl->table_list.elements)
{
- item= (*func)(expr, new Item_asterisk_remover(item));
+ item= (*func)(expr, new Item_asterisk_remover(this, item,
+ (char *)"<no matter>",
+ (char*)"<result>"));
if (sl->where)
sl->where= new Item_cond_and(sl->where, item);
else
@@ -340,14 +387,21 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex,
}
if (select_lex->next_select())
{
- // it is in union => we should perform it
- sl->having= (*func)(expr, item);
+ /*
+ It is in union => we should perform it.
+ Item_asterisk_remover used only as wrapper to receine NULL value
+ */
+ sl->having= (*func)(expr,
+ new Item_asterisk_remover(this, item,
+ (char *)"<no matter>",
+ (char*)"<result>"));
}
else
{
// it is single select without tables => possible optimization
item= (*func)(left_expr, item);
substitution= item;
+ have_to_be_excluded= 1;
THD *thd= current_thd;
if (thd->lex.describe)
{
@@ -489,7 +543,7 @@ int subselect_single_select_engine::exec()
join->thd->where= save_where;
DBUG_RETURN(1);
}
- item->assign_null();
+ item->reset();
item->assigned((executed= 0));
}
if (!executed)
diff --git a/sql/item_subselect.h b/sql/item_subselect.h
index d323dab51f1..0e6f939803d 100644
--- a/sql/item_subselect.h
+++ b/sql/item_subselect.h
@@ -42,6 +42,8 @@ protected:
subselect_engine *engine;
/* allowed number of columns (1 for single value subqueries) */
uint max_columns;
+ /* work with 'substitution' */
+ bool have_to_be_excluded;
public:
Item_subselect();
@@ -65,7 +67,7 @@ public:
select_subselect *result);
~Item_subselect();
- virtual void assign_null()
+ virtual void reset()
{
null_value= 1;
}
@@ -73,8 +75,11 @@ public:
bool assigned() { return value_assigned; }
void assigned(bool a) { value_assigned= a; }
enum Type type() const;
- bool is_null() { return null_value; }
- void make_field (Send_field *);
+ bool is_null()
+ {
+ val_int();
+ return null_value;
+ }
bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref);
virtual void fix_length_and_dec();
table_map used_tables() const;
@@ -110,7 +115,7 @@ public:
decimals= item->decimals;
res_type= item->res_type;
}
- virtual void assign_null()
+ virtual void reset()
{
null_value= 1;
int_value= 0;
@@ -144,7 +149,7 @@ public:
}
Item_exists_subselect(): Item_subselect() {}
- virtual void assign_null()
+ virtual void reset()
{
value= 0;
}
@@ -155,6 +160,7 @@ public:
double val();
String *val_str(String*);
void fix_length_and_dec();
+
friend class select_exists_subselect;
};
@@ -164,14 +170,26 @@ class Item_in_subselect :public Item_exists_subselect
{
protected:
Item * left_expr;
-
+ bool was_null;
public:
Item_in_subselect(THD *thd, Item * left_expr, st_select_lex *select_lex);
Item_in_subselect(Item_in_subselect *item);
Item_in_subselect(): Item_exists_subselect() {}
+ void reset()
+ {
+ value= 0;
+ null_value= 0;
+ was_null= 0;
+ }
virtual void select_transformer(st_select_lex *select_lex);
void single_value_transformer(st_select_lex *select_lex,
Item *left_expr, compare_func_creator func);
+ longlong val_int();
+ double val();
+ String *val_str(String*);
+
+ friend class Item_asterisk_remover;
+ friend class Item_ref_null_helper;
};
/* ALL/ANY/SOME subselect */
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 4a2d716c953..f54ab87b81d 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -47,28 +47,21 @@ void Item_sum::mark_as_sum_func()
with_sum_func= 1;
}
+
void Item_sum::make_field(Send_field *tmp_field)
{
if (args[0]->type() == Item::FIELD_ITEM && keep_field_type())
- ((Item_field*) args[0])->field->make_field(tmp_field);
- else
{
- tmp_field->flags=0;
- if (!maybe_null)
- tmp_field->flags|= NOT_NULL_FLAG;
- if (unsigned_flag)
- tmp_field->flags |= UNSIGNED_FLAG;
- tmp_field->length=max_length;
- tmp_field->decimals=decimals;
- tmp_field->type=(result_type() == INT_RESULT ? FIELD_TYPE_LONG :
- result_type() == REAL_RESULT ? FIELD_TYPE_DOUBLE :
- FIELD_TYPE_VAR_STRING);
+ ((Item_field*) args[0])->field->make_field(tmp_field);
+ tmp_field->db_name=(char*)"";
+ tmp_field->org_table_name=tmp_field->table_name=(char*)"";
+ tmp_field->org_col_name=tmp_field->col_name=name;
}
- tmp_field->db_name=(char*)"";
- tmp_field->org_table_name=tmp_field->table_name=(char*)"";
- tmp_field->org_col_name=tmp_field->col_name=name;
+ else
+ init_make_field(tmp_field, field_type());
}
+
void Item_sum::print(String *str)
{
str->append(func_name());
@@ -168,6 +161,10 @@ Item_sum_hybrid::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
null_value=1;
fix_length_and_dec();
thd->allow_sum_func=1; // Allow group functions
+ if (item->type() == Item::FIELD_ITEM)
+ hybrid_field_type= ((Item_field*) item)->field->type();
+ else
+ hybrid_field_type= Item::field_type();
fixed= 1;
return 0;
}
@@ -253,12 +250,24 @@ double Item_sum_avg::val()
** Standard deviation
*/
-void Item_sum_std::reset()
+double Item_sum_std::val()
{
- sum=sum_sqr=0.0; count=0; (void) Item_sum_std::add();
+ double tmp= Item_sum_variance::val();
+ return tmp <= 0.0 ? 0.0 : sqrt(tmp);
}
-bool Item_sum_std::add()
+/*
+** variance
+*/
+
+void Item_sum_variance::reset()
+{
+ sum=sum_sqr=0.0;
+ count=0;
+ (void) Item_sum_variance::add();
+}
+
+bool Item_sum_variance::add()
{
double nr=args[0]->val();
if (!args[0]->null_value)
@@ -270,7 +279,7 @@ bool Item_sum_std::add()
return 0;
}
-double Item_sum_std::val()
+double Item_sum_variance::val()
{
if (!count)
{
@@ -281,11 +290,10 @@ double Item_sum_std::val()
/* Avoid problems when the precision isn't good enough */
double tmp=ulonglong2double(count);
double tmp2=(sum_sqr - sum*sum/tmp)/tmp;
- return tmp2 <= 0.0 ? 0.0 : sqrt(tmp2);
+ return tmp2 <= 0.0 ? 0.0 : tmp2;
}
-
-void Item_sum_std::reset_field()
+void Item_sum_variance::reset_field()
{
double nr=args[0]->val();
char *res=result_field->ptr;
@@ -302,7 +310,7 @@ void Item_sum_std::reset_field()
}
}
-void Item_sum_std::update_field(int offset)
+void Item_sum_variance::update_field(int offset)
{
double nr,old_nr,old_sqr;
longlong field_count;
@@ -836,6 +844,17 @@ String *Item_avg_field::val_str(String *str)
}
Item_std_field::Item_std_field(Item_sum_std *item)
+ : Item_variance_field(item)
+{
+}
+
+double Item_std_field::val()
+{
+ double tmp= Item_variance_field::val();
+ return tmp <= 0.0 ? 0.0 : sqrt(tmp);
+}
+
+Item_variance_field::Item_variance_field(Item_sum_variance *item)
{
name=item->name;
decimals=item->decimals;
@@ -844,7 +863,7 @@ Item_std_field::Item_std_field(Item_sum_std *item)
maybe_null=1;
}
-double Item_std_field::val()
+double Item_variance_field::val()
{
double sum,sum_sqr;
longlong count;
@@ -860,10 +879,10 @@ double Item_std_field::val()
null_value=0;
double tmp= (double) count;
double tmp2=(sum_sqr - sum*sum/tmp)/tmp;
- return tmp2 <= 0.0 ? 0.0 : sqrt(tmp2);
+ return tmp2 <= 0.0 ? 0.0 : tmp2;
}
-String *Item_std_field::val_str(String *str)
+String *Item_variance_field::val_str(String *str)
{
double nr=val();
if (null_value)
diff --git a/sql/item_sum.h b/sql/item_sum.h
index 23b8482d41a..50375fbf77c 100644
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@ -27,7 +27,7 @@ class Item_sum :public Item_result_field
{
public:
enum Sumfunctype {COUNT_FUNC,COUNT_DISTINCT_FUNC,SUM_FUNC,AVG_FUNC,MIN_FUNC,
- MAX_FUNC, UNIQUE_USERS_FUNC,STD_FUNC,SUM_BIT_FUNC,
+ MAX_FUNC, UNIQUE_USERS_FUNC,STD_FUNC,VARIANCE_FUNC,SUM_BIT_FUNC,
UDF_SUM_FUNC };
Item **args,*tmp_args[2];
@@ -210,7 +210,7 @@ public:
longlong val_int() { return (longlong) val(); }
bool is_null() { (void) val_int(); return null_value; }
String *val_str(String*);
- void make_field(Send_field *field);
+ enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
void fix_length_and_dec() {}
};
@@ -235,42 +235,79 @@ class Item_sum_avg :public Item_sum_num
const char *func_name() const { return "avg"; }
};
-class Item_sum_std;
+class Item_sum_variance;
-class Item_std_field :public Item_result_field
+class Item_variance_field :public Item_result_field
{
public:
Field *field;
- Item_std_field(Item_sum_std *item);
- enum Type type() const { return FIELD_STD_ITEM; }
+ Item_variance_field(Item_sum_variance *item);
+ enum Type type() const {return FIELD_VARIANCE_ITEM; }
double val();
longlong val_int() { return (longlong) val(); }
String *val_str(String*);
bool is_null() { (void) val_int(); return null_value; }
- void make_field(Send_field *field);
+ enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
void fix_length_and_dec() {}
};
-class Item_sum_std :public Item_sum_num
+/*
+
+variance(a) =
+
+= sum (ai - avg(a))^2 / count(a) )
+= sum (ai^2 - 2*ai*avg(a) + avg(a)^2) / count(a)
+= (sum(ai^2) - sum(2*ai*avg(a)) + sum(avg(a)^2))/count(a) =
+= (sum(ai^2) - 2*avg(a)*sum(a) + count(a)*avg(a)^2)/count(a) =
+= (sum(ai^2) - 2*sum(a)*sum(a)/count(a) + count(a)*sum(a)^2/count(a)^2 )/count(a) =
+= (sum(ai^2) - 2*sum(a)^2/count(a) + sum(a)^2/count(a) )/count(a) =
+= (sum(ai^2) - sum(a)^2/count(a))/count(a)
+
+*/
+
+class Item_sum_variance : public Item_sum_num
{
- double sum;
- double sum_sqr;
+ double sum, sum_sqr;
ulonglong count;
void fix_length_and_dec() { decimals+=4; maybe_null=1; }
public:
- Item_sum_std(Item *item_par) :Item_sum_num(item_par),count(0) {}
- enum Sumfunctype sum_func () const { return STD_FUNC; }
+ Item_sum_variance(Item *item_par) :Item_sum_num(item_par),count(0) {}
+ enum Sumfunctype sum_func () const { return VARIANCE_FUNC; }
void reset();
bool add();
double val();
void reset_field();
void update_field(int offset);
Item *result_item(Field *field)
- { return new Item_std_field(this); }
- const char *func_name() const { return "std"; }
+ { return new Item_variance_field(this); }
+ const char *func_name() const { return "variance"; }
};
+class Item_sum_std;
+
+class Item_std_field :public Item_variance_field
+{
+public:
+ Item_std_field(Item_sum_std *item);
+ enum Type type() const { return FIELD_STD_ITEM; }
+ double val();
+};
+
+/*
+ standard_deviation(a) = sqrt(variance(a))
+*/
+
+class Item_sum_std :public Item_sum_variance
+{
+ public:
+ Item_sum_std(Item *item_par) :Item_sum_variance(item_par){}
+ enum Sumfunctype sum_func () const { return STD_FUNC; }
+ double val();
+ Item *result_item(Field *field)
+ { return new Item_std_field(this); }
+ const char *func_name() const { return "std"; }
+};
// This class is a string or number function depending on num_func
@@ -281,6 +318,7 @@ class Item_sum_hybrid :public Item_sum
double sum;
longlong sum_int;
Item_result hybrid_type;
+ enum_field_types hybrid_field_type;
int cmp_sign;
table_map used_table_cache;
@@ -307,6 +345,7 @@ class Item_sum_hybrid :public Item_sum
void make_const() { used_table_cache=0; }
bool keep_field_type(void) const { return 1; }
enum Item_result result_type () const { return hybrid_type; }
+ enum enum_field_types field_type() const { return hybrid_field_type; }
void update_field(int offset);
void min_max_update_str_field(int offset);
void min_max_update_real_field(int offset);
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index 7e2e8f7cfbd..061cf208052 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -295,8 +295,8 @@ longlong Item_func_time_to_sec::val_int()
/*
-** Convert a string to a interval value
-** To make code easy, allow interval objects without separators.
+ Convert a string to a interval value
+ To make code easy, allow interval objects without separators.
*/
static bool get_interval_value(Item *args,interval_type int_type,
@@ -516,12 +516,14 @@ void Item_func_curtime::fix_length_and_dec()
(int) start->tm_sec);
}
+
String *Item_func_now::val_str(String *str)
{
str_value.set(buff,buff_length,thd_charset());
return &str_value;
}
+
void Item_func_now::fix_length_and_dec()
{
struct tm tm_tmp,*start;
@@ -540,13 +542,14 @@ void Item_func_now::fix_length_and_dec()
(ulong) (((uint) start->tm_min)*100L+
(uint) start->tm_sec)));
- buff_length= (uint) cs->snprintf(cs,buff, sizeof(buff),"%04d-%02d-%02d %02d:%02d:%02d",
- ((int) (start->tm_year+1900)) % 10000,
- (int) start->tm_mon+1,
- (int) start->tm_mday,
- (int) start->tm_hour,
- (int) start->tm_min,
- (int) start->tm_sec);
+ buff_length= (uint) cs->snprintf(cs,buff, sizeof(buff),
+ "%04d-%02d-%02d %02d:%02d:%02d",
+ ((int) (start->tm_year+1900)) % 10000,
+ (int) start->tm_mon+1,
+ (int) start->tm_mday,
+ (int) start->tm_hour,
+ (int) start->tm_min,
+ (int) start->tm_sec);
/* For getdate */
ltime.year= start->tm_year+1900;
ltime.month= start->tm_mon+1;
@@ -995,7 +998,42 @@ bool Item_func_from_unixtime::get_date(TIME *ltime,
return 0;
}
- /* Here arg[1] is a Item_interval object */
+
+void Item_date_add_interval::fix_length_and_dec()
+{
+ enum_field_types arg0_field_type;
+ set_charset(thd_charset());
+ maybe_null=1;
+ max_length=19*thd_charset()->mbmaxlen;
+ value.alloc(32);
+
+ /*
+ The field type for the result of an Item_date function is defined as
+ follows:
+
+ - If first arg is a MYSQL_TYPE_DATETIME result is MYSQL_TYPE_DATETIME
+ - If first arg is a MYSQL_TYPE_DATE and the interval type uses hours,
+ minutes or seconds then type is MYSQL_TYPE_DATETIME.
+ - Otherwise the result is MYSQL_TYPE_STRING
+ (This is because you can't know if the string contains a DATE, TIME or
+ DATETIME argument)
+ */
+ cached_field_type= MYSQL_TYPE_STRING;
+ arg0_field_type= args[0]->field_type();
+ if (arg0_field_type == MYSQL_TYPE_DATETIME ||
+ arg0_field_type == MYSQL_TYPE_TIMESTAMP)
+ cached_field_type= MYSQL_TYPE_DATETIME;
+ else if (arg0_field_type == MYSQL_TYPE_DATE)
+ {
+ if (int_type <= INTERVAL_DAY || int_type == INTERVAL_YEAR_MONTH)
+ cached_field_type= arg0_field_type;
+ else
+ cached_field_type= MYSQL_TYPE_DATETIME;
+ }
+}
+
+
+/* Here arg[1] is a Item_interval object */
bool Item_date_add_interval::get_date(TIME *ltime, bool fuzzy_date)
{
diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h
index 40397351c18..aa075e1a91d 100644
--- a/sql/item_timefunc.h
+++ b/sql/item_timefunc.h
@@ -316,6 +316,7 @@ public:
Item_date() :Item_func() {}
Item_date(Item *a) :Item_func(a) {}
enum Item_result result_type () const { return STRING_RESULT; }
+ enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
String *val_str(String *str);
double val() { return (double) val_int(); }
const char *func_name() const { return "date"; }
@@ -326,10 +327,6 @@ public:
max_length=10*thd_charset()->mbmaxlen;
}
int save_in_field(Field *to, bool no_conversions);
- void make_field(Send_field *tmp_field)
- {
- init_make_field(tmp_field,FIELD_TYPE_DATE);
- }
Field *tmp_table_field(TABLE *t_arg)
{
return (!t_arg) ? result_field : new Field_date(maybe_null, name, t_arg, thd_charset());
@@ -343,10 +340,7 @@ public:
Item_date_func() :Item_str_func() {}
Item_date_func(Item *a) :Item_str_func(a) {}
Item_date_func(Item *a,Item *b) :Item_str_func(a,b) {}
- void make_field(Send_field *tmp_field)
- {
- init_make_field(tmp_field,FIELD_TYPE_DATETIME);
- }
+ enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; }
Field *tmp_table_field(TABLE *t_arg)
{
return (!t_arg) ? result_field : new Field_datetime(maybe_null, name,
@@ -364,15 +358,12 @@ public:
Item_func_curtime() :Item_func() {}
Item_func_curtime(Item *a) :Item_func(a) {}
enum Item_result result_type () const { return STRING_RESULT; }
+ enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
double val() { return (double) value; }
longlong val_int() { return value; }
String *val_str(String *str);
const char *func_name() const { return "curtime"; }
void fix_length_and_dec();
- void make_field(Send_field *tmp_field)
- {
- init_make_field(tmp_field,FIELD_TYPE_TIME);
- }
Field *tmp_table_field(TABLE *t_arg)
{
return (!t_arg) ? result_field :
@@ -452,7 +443,6 @@ class Item_func_from_unixtime :public Item_date_func
decimals=0;
max_length=19*thd_charset()->mbmaxlen;
}
-// enum Item_result result_type () const { return STRING_RESULT; }
bool get_date(TIME *res,bool fuzzy_date);
};
@@ -470,11 +460,8 @@ public:
maybe_null=1;
max_length=13*thd_charset()->mbmaxlen;
}
+ enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
const char *func_name() const { return "sec_to_time"; }
- void make_field(Send_field *tmp_field)
- {
- init_make_field(tmp_field,FIELD_TYPE_TIME);
- }
Field *tmp_table_field(TABLE *t_arg)
{
return (!t_arg) ? result_field :
@@ -482,32 +469,34 @@ public:
}
};
+/*
+ The following must be sorted so that simple intervals comes first.
+ (get_interval_value() depends on this)
+*/
+
+enum interval_type
+{
+ INTERVAL_YEAR, INTERVAL_MONTH, INTERVAL_DAY, INTERVAL_HOUR, INTERVAL_MINUTE,
+ INTERVAL_SECOND, INTERVAL_YEAR_MONTH, INTERVAL_DAY_HOUR, INTERVAL_DAY_MINUTE,
+ INTERVAL_DAY_SECOND, INTERVAL_HOUR_MINUTE, INTERVAL_HOUR_SECOND,
+ INTERVAL_MINUTE_SECOND
+};
-enum interval_type { INTERVAL_YEAR, INTERVAL_MONTH, INTERVAL_DAY,
- INTERVAL_HOUR, INTERVAL_MINUTE, INTERVAL_SECOND,
- INTERVAL_YEAR_MONTH, INTERVAL_DAY_HOUR,
- INTERVAL_DAY_MINUTE, INTERVAL_DAY_SECOND,
- INTERVAL_HOUR_MINUTE, INTERVAL_HOUR_SECOND,
- INTERVAL_MINUTE_SECOND};
class Item_date_add_interval :public Item_date_func
{
const interval_type int_type;
String value;
const bool date_sub_interval;
+ enum_field_types cached_field_type;
public:
Item_date_add_interval(Item *a,Item *b,interval_type type_arg,bool neg_arg)
:Item_date_func(a,b),int_type(type_arg), date_sub_interval(neg_arg) {}
String *val_str(String *);
const char *func_name() const { return "date_add_interval"; }
- void fix_length_and_dec()
- {
- set_charset(thd_charset());
- maybe_null=1;
- max_length=19*thd_charset()->mbmaxlen;
- value.alloc(32);
- }
+ void fix_length_and_dec();
+ enum_field_types field_type() const { return cached_field_type; }
double val() { return (double) val_int(); }
longlong val_int();
bool get_date(TIME *res,bool fuzzy_date);
@@ -566,10 +555,7 @@ class Item_date_typecast :public Item_typecast
public:
Item_date_typecast(Item *a) :Item_typecast(a) {}
const char *func_name() const { return "date"; }
- void make_field(Send_field *tmp_field)
- {
- init_make_field(tmp_field,FIELD_TYPE_DATE);
- }
+ enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
Field *tmp_table_field(TABLE *t_arg)
{
return (!t_arg) ? result_field :
@@ -583,10 +569,7 @@ class Item_time_typecast :public Item_typecast
public:
Item_time_typecast(Item *a) :Item_typecast(a) {}
const char *func_name() const { return "time"; }
- void make_field(Send_field *tmp_field)
- {
- init_make_field(tmp_field,FIELD_TYPE_TIME);
- }
+ enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
Field *tmp_table_field(TABLE *t_arg)
{
return (!t_arg) ? result_field :
@@ -600,10 +583,7 @@ class Item_datetime_typecast :public Item_typecast
public:
Item_datetime_typecast(Item *a) :Item_typecast(a) {}
const char *func_name() const { return "datetime"; }
- void make_field(Send_field *tmp_field)
- {
- init_make_field(tmp_field,FIELD_TYPE_DATETIME);
- }
+ enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; }
Field *tmp_table_field(TABLE *t_arg)
{
return (!t_arg) ? result_field : new Field_datetime(maybe_null, name,
diff --git a/sql/lex.h b/sql/lex.h
index eb03c0b36ec..421ac933f50 100644
--- a/sql/lex.h
+++ b/sql/lex.h
@@ -344,6 +344,7 @@ static SYMBOL symbols[] = {
{ "SQL_NO_CACHE", SYM(SQL_NO_CACHE_SYM), 0, 0},
{ "SQL_SMALL_RESULT", SYM(SQL_SMALL_RESULT),0,0},
{ "SQL_THREAD", SYM(SQL_THREAD),0,0},
+ { "SOUNDS", SYM(SOUNDS_SYM),0,0},
{ "SSL", SYM(SSL_SYM),0,0},
{ "STRAIGHT_JOIN", SYM(STRAIGHT_JOIN),0,0},
{ "START", SYM(START_SYM),0,0},
@@ -584,6 +585,7 @@ static SYMBOL sql_functions[] = {
{ "UNIX_TIMESTAMP", SYM(UNIX_TIMESTAMP),0,0},
{ "UPPER", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ucase)},
{ "USER", SYM(USER),0,0},
+ { "VARIANCE", SYM(VARIANCE_SYM),0,0},
{ "VERSION", SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_version)},
{ "WEEK", SYM(WEEK_SYM),0,0},
{ "WEEKDAY", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_weekday)},
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 6bb1a1c65a9..913af1bdd7c 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -313,9 +313,9 @@ int Log_event::exec_event(struct st_relay_log_info* rli)
Log_event::pack_info()
****************************************************************************/
-void Log_event::pack_info(String* packet)
+void Log_event::pack_info(Protocol *protocol)
{
- net_store_data(packet, "", 0);
+ protocol->store("",0);
}
#endif /* EMBEDDED_LIBRARY */
@@ -327,10 +327,13 @@ void Log_event::pack_info(String* packet)
void Log_event::init_show_field_list(List<Item>* field_list)
{
field_list->push_back(new Item_empty_string("Log_name", 20));
- field_list->push_back(new Item_empty_string("Pos", 20));
+ field_list->push_back(new Item_return_int("Pos", 11,
+ MYSQL_TYPE_LONGLONG));
field_list->push_back(new Item_empty_string("Event_type", 20));
- field_list->push_back(new Item_empty_string("Server_id", 20));
- field_list->push_back(new Item_empty_string("Orig_log_pos", 20));
+ field_list->push_back(new Item_return_int("Server_id", 10,
+ MYSQL_TYPE_LONG));
+ field_list->push_back(new Item_return_int("Orig_log_pos", 11,
+ MYSQL_TYPE_LONGLONG));
field_list->push_back(new Item_empty_string("Info", 20));
}
@@ -342,23 +345,22 @@ void Log_event::init_show_field_list(List<Item>* field_list)
****************************************************************************/
#ifndef EMBEDDED_LIBRARY
-int Log_event::net_send(THD* thd_arg, const char* log_name, my_off_t pos)
+int Log_event::net_send(Protocol *protocol, const char* log_name, my_off_t pos)
{
- String* packet = &thd_arg->packet;
const char *p= strrchr(log_name, FN_LIBCHAR);
const char *event_type;
if (p)
log_name = p + 1;
- packet->length(0);
- net_store_data(packet, log_name, strlen(log_name));
- net_store_data(packet, (longlong) pos);
+ protocol->prepare_for_resend();
+ protocol->store(log_name);
+ protocol->store((ulonglong) pos);
event_type = get_type_str();
- net_store_data(packet, event_type, strlen(event_type));
- net_store_data(packet, server_id);
- net_store_data(packet, (longlong) log_pos);
- pack_info(packet);
- return SEND_ROW(thd_arg, 5, (char*) packet->ptr(), packet->length());
+ protocol->store(event_type, strlen(event_type));
+ protocol->store((uint32) server_id);
+ protocol->store((ulonglong) log_pos);
+ pack_info(protocol);
+ return protocol->write();
}
#endif /* EMBEDDED_LIBRARY */
#endif // !MYSQL_CLIENT
@@ -686,7 +688,7 @@ void Log_event::set_log_pos(MYSQL_LOG* log)
Query_log_event::pack_info()
****************************************************************************/
-void Query_log_event::pack_info(String* packet)
+void Query_log_event::pack_info(Protocol *protocol)
{
char buf[256];
String tmp(buf, sizeof(buf), system_charset_info);
@@ -700,7 +702,7 @@ void Query_log_event::pack_info(String* packet)
if (query && q_len)
tmp.append(query, q_len);
- net_store_data(packet, (char*)tmp.ptr(), tmp.length());
+ protocol->store((char*) tmp.ptr(), tmp.length());
}
#endif // !MYSQL_CLIENT
#endif /* EMBEDDED_LIBRARY */
@@ -944,7 +946,7 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli)
****************************************************************************/
#ifndef EMBEDDED_LIBRARY
#ifndef MYSQL_CLIENT
-void Start_log_event::pack_info(String* packet)
+void Start_log_event::pack_info(Protocol *protocol)
{
char buf1[256];
String tmp(buf1, sizeof(buf1), system_charset_info);
@@ -955,7 +957,7 @@ void Start_log_event::pack_info(String* packet)
tmp.append(server_version);
tmp.append(", Binlog ver: ");
tmp.append(llstr(binlog_version, buf));
- net_store_data(packet, tmp.ptr(), tmp.length());
+ protocol->store(tmp.ptr(), tmp.length());
}
#endif // !MYSQL_CLIENT
#endif /* EMBEDDED_LIBRARY */
@@ -1059,7 +1061,7 @@ int Start_log_event::exec_event(struct st_relay_log_info* rli)
****************************************************************************/
#ifndef EMBEDDED_LIBRARY
#ifndef MYSQL_CLIENT
-void Load_log_event::pack_info(String* packet)
+void Load_log_event::pack_info(Protocol *protocol)
{
char buf[256];
String tmp(buf, sizeof(buf), system_charset_info);
@@ -1132,7 +1134,7 @@ void Load_log_event::pack_info(String* packet)
tmp.append(')');
}
- net_store_data(packet, tmp.ptr(), tmp.length());
+ protocol->store(tmp.ptr(), tmp.length());
}
#endif // !MYSQL_CLIENT
#endif /* EMBEDDED_LIBRARY */
@@ -1569,7 +1571,7 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli)
****************************************************************************/
#ifndef EMBEDDED_LIBRARY
#ifndef MYSQL_CLIENT
-void Rotate_log_event::pack_info(String* packet)
+void Rotate_log_event::pack_info(Protocol *protocol)
{
char buf1[256], buf[22];
String tmp(buf1, sizeof(buf1), system_charset_info);
@@ -1579,7 +1581,7 @@ void Rotate_log_event::pack_info(String* packet)
tmp.append(llstr(pos,buf));
if (flags & LOG_EVENT_FORCED_ROTATE_F)
tmp.append("; forced by master");
- net_store_data(packet, tmp.ptr(), tmp.length());
+ protocol->store(tmp.ptr(), tmp.length());
}
#endif // !MYSQL_CLIENT
#endif /* EMBEDDED_LIBRARY */
@@ -1711,7 +1713,7 @@ int Rotate_log_event::exec_event(struct st_relay_log_info* rli)
****************************************************************************/
#ifndef EMBEDDED_LIBRARY
#ifndef MYSQL_CLIENT
-void Intvar_log_event::pack_info(String* packet)
+void Intvar_log_event::pack_info(Protocol *protocol)
{
char buf1[256], buf[22];
String tmp(buf1, sizeof(buf1), system_charset_info);
@@ -1719,7 +1721,7 @@ void Intvar_log_event::pack_info(String* packet)
tmp.append(get_var_type_name());
tmp.append('=');
tmp.append(llstr(val, buf));
- net_store_data(packet, tmp.ptr(), tmp.length());
+ protocol->store(tmp.ptr(), tmp.length());
}
#endif // !MYSQL_CLIENT
#endif /* EMBEDDED_LIBRARY */
@@ -1836,14 +1838,14 @@ int Intvar_log_event::exec_event(struct st_relay_log_info* rli)
****************************************************************************/
#ifndef EMBEDDED_LIBRARY
#ifndef MYSQL_CLIENT
-void Rand_log_event::pack_info(String* packet)
+void Rand_log_event::pack_info(Protocol *protocol)
{
char buf1[256], *pos;
pos= strmov(buf1,"rand_seed1=");
pos= int10_to_str((long) seed1, pos, 10);
pos= strmov(pos, ",rand_seed2=");
pos= int10_to_str((long) seed2, pos, 10);
- net_store_data(packet, buf1, (uint) (pos-buf1));
+ protocol->store(buf1, (uint) (pos-buf1));
}
#endif // !MYSQL_CLIENT
#endif /* EMBEDDED_LIBRARY */
@@ -1928,7 +1930,7 @@ int Rand_log_event::exec_event(struct st_relay_log_info* rli)
#ifndef EMBEDDED_LIBRARY
#ifndef MYSQL_CLIENT
-void Slave_log_event::pack_info(String* packet)
+void Slave_log_event::pack_info(Protocol *protocol)
{
char buf1[256], buf[22], *end;
String tmp(buf1, sizeof(buf1), system_charset_info);
@@ -1942,7 +1944,7 @@ void Slave_log_event::pack_info(String* packet)
tmp.append(master_log);
tmp.append(",pos=");
tmp.append(llstr(master_pos,buf));
- net_store_data(packet, tmp.ptr(), tmp.length());
+ protocol->store(tmp.ptr(), tmp.length());
}
#endif // !MYSQL_CLIENT
@@ -2278,7 +2280,7 @@ void Create_file_log_event::print(FILE* file, bool short_form,
****************************************************************************/
#ifndef EMBEDDED_LIBRARY
#ifndef MYSQL_CLIENT
-void Create_file_log_event::pack_info(String* packet)
+void Create_file_log_event::pack_info(Protocol *protocol)
{
char buf1[256],buf[22], *end;
String tmp(buf1, sizeof(buf1), system_charset_info);
@@ -2293,7 +2295,7 @@ void Create_file_log_event::pack_info(String* packet)
tmp.append(";block_len=");
end= int10_to_str((long) block_len, buf, 10);
tmp.append(buf, (uint32) (end-buf));
- net_store_data(packet, (char*) tmp.ptr(), tmp.length());
+ protocol->store((char*) tmp.ptr(), tmp.length());
}
#endif // !MYSQL_CLIENT
#endif /* EMBEDDED_LIBRARY */
@@ -2441,14 +2443,14 @@ void Append_block_log_event::print(FILE* file, bool short_form,
****************************************************************************/
#ifndef EMBEDDED_LIBRARY
#ifndef MYSQL_CLIENT
-void Append_block_log_event::pack_info(String* packet)
+void Append_block_log_event::pack_info(Protocol *protocol)
{
char buf[256];
uint length;
length= (uint) my_sprintf(buf,
(buf, ";file_id=%u;block_len=%u", file_id,
block_len));
- net_store_data(packet, buf, (int32) length);
+ protocol->store(buf, (int32) length);
}
#endif // !MYSQL_CLIENT
#endif /* EMBEDDED_LIBRARY */
@@ -2560,12 +2562,12 @@ void Delete_file_log_event::print(FILE* file, bool short_form,
****************************************************************************/
#ifndef EMBEDDED_LIBRARY
#ifndef MYSQL_CLIENT
-void Delete_file_log_event::pack_info(String* packet)
+void Delete_file_log_event::pack_info(Protocol *protocol)
{
char buf[64];
uint length;
length= (uint) my_sprintf(buf, (buf, ";file_id=%u", (uint) file_id));
- net_store_data(packet, buf, (int32) length);
+ protocol->store(buf, (int32) length);
}
#endif // !MYSQL_CLIENT
#endif /* EMBEDDED_LIBRARY */
@@ -2663,12 +2665,12 @@ void Execute_load_log_event::print(FILE* file, bool short_form,
****************************************************************************/
#ifndef EMBEDDED_LIBRARY
#ifndef MYSQL_CLIENT
-void Execute_load_log_event::pack_info(String* packet)
+void Execute_load_log_event::pack_info(Protocol *protocol)
{
char buf[64];
uint length;
length= (uint) my_sprintf(buf, (buf, ";file_id=%u", (uint) file_id));
- net_store_data(packet, buf, (int32) length);
+ protocol->store(buf, (int32) length);
}
#endif // !MYSQL_CLIENT
#endif /* EMBEDDED_LIBRARY */
diff --git a/sql/log_event.h b/sql/log_event.h
index db5b1790123..e0ebe4150bb 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -269,8 +269,8 @@ public:
void set_log_pos(MYSQL_LOG* log);
static void init_show_field_list(List<Item>* field_list);
#ifndef EMBEDDED_LIBRARY
- int net_send(THD* thd, const char* log_name, my_off_t pos);
- virtual void pack_info(String* packet);
+ int net_send(Protocol *protocol, const char* log_name, my_off_t pos);
+ virtual void pack_info(Protocol *protocol);
virtual int exec_event(struct st_relay_log_info* rli);
#endif /* EMBEDDED_LIBRARY */
virtual const char* get_db()
@@ -358,7 +358,7 @@ public:
bool using_trans);
const char* get_db() { return db; }
#ifndef EMBEDDED_LIBRARY
- void pack_info(String* packet);
+ void pack_info(Protocol* protocol);
int exec_event(struct st_relay_log_info* rli);
#endif /* EMBEDDED_LIBRARY */
#else
@@ -410,7 +410,7 @@ public:
#ifndef MYSQL_CLIENT
Slave_log_event(THD* thd_arg, struct st_relay_log_info* rli);
#ifndef EMBEDDED_LIBRARY
- void pack_info(String* packet);
+ void pack_info(Protocol* protocol);
int exec_event(struct st_relay_log_info* rli);
#endif /* EMBEDDED_LIBRARY */
#else
@@ -465,7 +465,7 @@ public:
void set_fields(List<Item> &fields_arg);
const char* get_db() { return db; }
#ifndef EMBEDDED_LIBRARY
- void pack_info(String* packet);
+ void pack_info(Protocol* protocol);
int exec_event(struct st_relay_log_info* rli)
{
return exec_event(thd->slave_net,rli);
@@ -519,7 +519,7 @@ public:
memcpy(server_version, ::server_version, ST_SERVER_VER_LEN);
}
#ifndef EMBEDDED_LIBRARY
- void pack_info(String* packet);
+ void pack_info(Protocol* protocol);
int exec_event(struct st_relay_log_info* rli);
#endif /* EMBEDDED_LIBRARY */
#else
@@ -556,7 +556,7 @@ public:
:Log_event(),val(val_arg),type(type_arg)
{}
#ifndef EMBEDDED_LIBRARY
- void pack_info(String* packet);
+ void pack_info(Protocol* protocol);
int exec_event(struct st_relay_log_info* rli);
#endif /* EMBEDDED_LIBRARY */
#else
@@ -590,7 +590,7 @@ class Rand_log_event: public Log_event
:Log_event(thd_arg,0,0),seed1(seed1_arg),seed2(seed2_arg)
{}
#ifndef EMBEDDED_LIBRARY
- void pack_info(String* packet);
+ void pack_info(Protocol* protocol);
int exec_event(struct st_relay_log_info* rli);
#endif /* EMBEDDED_LIBRARY */
#else
@@ -660,7 +660,7 @@ public:
(uint) strlen(new_log_ident_arg)), alloced(0)
{}
#ifndef EMBEDDED_LIBRARY
- void pack_info(String* packet);
+ void pack_info(Protocol* protocol);
int exec_event(struct st_relay_log_info* rli);
#endif /* EMBEDDED_LIBRARY */
#else
@@ -709,7 +709,7 @@ public:
char* block_arg, uint block_len_arg,
bool using_trans);
#ifndef EMBEDDED_LIBRARY
- void pack_info(String* packet);
+ void pack_info(Protocol* protocol);
int exec_event(struct st_relay_log_info* rli);
#endif /* EMBEDDED_LIBRARY */
#else
@@ -762,7 +762,7 @@ public:
uint block_len_arg, bool using_trans);
#ifndef EMBEDDED_LIBRARY
int exec_event(struct st_relay_log_info* rli);
- void pack_info(String* packet);
+ void pack_info(Protocol* protocol);
#endif /* EMBEDDED_LIBRARY */
#else
void print(FILE* file, bool short_form = 0, char* last_db = 0);
@@ -789,7 +789,7 @@ public:
#ifndef MYSQL_CLIENT
Delete_file_log_event(THD* thd, bool using_trans);
#ifndef EMBEDDED_LIBRARY
- void pack_info(String* packet);
+ void pack_info(Protocol* protocol);
int exec_event(struct st_relay_log_info* rli);
#endif /* EMBEDDED_LIBRARY */
#else
@@ -817,7 +817,7 @@ public:
#ifndef MYSQL_CLIENT
Execute_load_log_event(THD* thd, bool using_trans);
#ifndef EMBEDDED_LIBRARY
- void pack_info(String* packet);
+ void pack_info(Protocol* protocol);
int exec_event(struct st_relay_log_info* rli);
#endif /* EMBEDDED_LIBRARY */
#else
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index ed618f3ba80..a489237a6e8 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -283,6 +283,7 @@ inline THD *_current_thd(void)
#include "handler.h"
#include "table.h"
#include "field.h" /* Field definitions */
+#include "protocol.h"
#include "sql_udf.h"
#include "item.h"
typedef compare_func_creator (*chooser_compare_func_creator)(bool invert);
@@ -377,30 +378,6 @@ int mysql_optimize_table(THD* thd, TABLE_LIST* table_list,
HA_CHECK_OPT* check_opt);
bool check_simple_select();
-/* net_pkg.c */
-void send_warning(THD *thd, uint sql_errno, const char *err=0);
-void net_printf(THD *thd,uint sql_errno, ...);
-void send_ok(THD *thd, ha_rows affected_rows=0L, ulonglong id=0L,
- const char *info=0);
-void send_eof(THD *thd, bool no_flush=0);
-void net_send_error(NET *net, uint sql_errno, const char *err);
-char *net_store_length(char *packet,ulonglong length);
-char *net_store_length(char *packet,uint length);
-char *net_store_data(char *to,const char *from);
-char *net_store_data(char *to,int32 from);
-char *net_store_data(char *to,longlong from);
-
-bool net_store_null(String *packet);
-bool net_store_data(String *packet,uint32 from);
-bool net_store_data(String *packet,longlong from);
-bool net_store_data(String *packet,const char *from);
-bool net_store_data(String *packet,const char *from,uint length);
-bool net_store_data(String *packet,struct tm *tmp);
-bool net_store_data(String* packet, I_List<i_string>* str_list);
-bool net_store_data(String *packet,CONVERT *convert, const char *from,
- uint length);
-bool net_store_data(String *packet, CONVERT *convert, const char *from);
-
SORT_FIELD * make_unireg_sortorder(ORDER *order, uint *length);
int setup_order(THD *thd,TABLE_LIST *tables, List<Item> &fields,
List <Item> &all_fields, ORDER *order);
@@ -419,7 +396,7 @@ int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit,
select_result *result);
int mysql_explain_select(THD *thd, SELECT_LEX *sl, char const *type,
select_result *result);
-int mysql_union(THD *thd, LEX *lex,select_result *result);
+int mysql_union(THD *thd, LEX *lex,select_result *result,SELECT_LEX_UNIT *unit);
int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *s, TABLE_LIST *t);
Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
Item_result_field ***copy_func, Field **from_field,
@@ -594,7 +571,6 @@ int lock_tables(THD *thd,TABLE_LIST *tables);
TABLE *open_temporary_table(THD *thd, const char *path, const char *db,
const char *table_name, bool link_in_list);
bool rm_temporary_table(enum db_type base, char *path);
-bool send_fields(THD *thd,List<Item> &item,uint send_field_count);
void free_io_cache(TABLE *entry);
void intern_close_table(TABLE *entry);
bool close_thread_table(THD *thd, TABLE **table_ptr);
@@ -818,6 +794,7 @@ bool str_to_time(const char *str,uint length,TIME *l_time);
longlong str_to_datetime(const char *str,uint length,bool fuzzy_date);
timestamp_type str_to_TIME(const char *str, uint length, TIME *l_time,
bool fuzzy_date);
+void localtime_to_TIME(TIME *to, struct tm *from);
int test_if_number(char *str,int *res,bool allow_wildcards);
void change_byte(byte *,uint,char,char);
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 78cbfba26ca..8869a642ed3 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -184,7 +184,6 @@ static uint handler_count;
static bool opt_enable_named_pipe = 0;
#endif
#ifdef __WIN__
-static bool opt_console=0,start_mode=0;
static pthread_cond_t COND_handler_count;
static uint handler_count;
static bool opt_console=0, start_mode=0, use_opt_args;
@@ -1551,7 +1550,7 @@ static void start_signal_handler(void)
(void) pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED);
if (!(opt_specialflag & SPECIAL_NO_PRIOR))
my_pthread_attr_setprio(&thr_attr,INTERRUPT_PRIOR);
- pthread_attr_setstacksize(&thr_attr,32768);
+ pthread_attr_setstacksize(&thr_attr, 129*1024);
#endif
(void) pthread_mutex_lock(&LOCK_thread_count);
diff --git a/sql/net_pkg.cc b/sql/net_pkg.cc
deleted file mode 100644
index 7a3ec5ebf64..00000000000
--- a/sql/net_pkg.cc
+++ /dev/null
@@ -1,525 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-
-#include "mysql_priv.h"
-#include <stdarg.h>
-
- /* Send a error string to client */
-
-void send_error(THD *thd, uint sql_errno, const char *err)
-{
- uint length;
- char buff[MYSQL_ERRMSG_SIZE+2];
- NET *net= &thd->net;
- DBUG_ENTER("send_error");
- DBUG_PRINT("enter",("sql_errno: %d err: %s", sql_errno,
- err ? err : net->last_error[0] ?
- net->last_error : "NULL"));
-
-#ifndef EMBEDDED_LIBRARY
- query_cache_abort(net);
-#endif
- thd->query_error= 1; // needed to catch query errors during replication
- if (!err)
- {
- if (sql_errno)
- err=ER(sql_errno);
- else
- {
- if ((err=net->last_error)[0])
- sql_errno=net->last_errno;
- else
- {
- sql_errno=ER_UNKNOWN_ERROR;
- err=ER(sql_errno); /* purecov: inspected */
- }
- }
- }
-
-#ifdef EMBEDDED_LIBRARY
- net->last_errno= sql_errno;
- strmake(net->last_error, err, sizeof(net->last_error)-1);
-#else
-
- if (net->vio == 0)
- {
- if (thd->bootstrap)
- {
- /* In bootstrap it's ok to print on stderr */
- fprintf(stderr,"ERROR: %d %s\n",sql_errno,err);
- }
- DBUG_VOID_RETURN;
- }
-
- if (net->return_errno)
- { // new client code; Add errno before message
- int2store(buff,sql_errno);
- length= (uint) (strmake(buff+2,err,MYSQL_ERRMSG_SIZE-1) - buff);
- err=buff;
- }
- else
- {
- length=(uint) strlen(err);
- set_if_smaller(length,MYSQL_ERRMSG_SIZE-1);
- }
- VOID(net_write_command(net,(uchar) 255, "", 0, (char*) err,length));
-#endif /* EMBEDDED_LIBRARY*/
- thd->fatal_error=0; // Error message is given
- thd->net.report_error= 0;
- DBUG_VOID_RETURN;
-}
-
-/*
- Send an error to the client when a connection is forced close
- This is used by mysqld.cc, which doesn't have a THD
-*/
-
-#ifndef EMBEDDED_LIBRARY
-void net_send_error(NET *net, uint sql_errno, const char *err)
-{
- char buff[2];
- uint length;
- DBUG_ENTER("send_net_error");
-
- int2store(buff,sql_errno);
- length=(uint) strlen(err);
- set_if_smaller(length,MYSQL_ERRMSG_SIZE-1);
- net_write_command(net,(uchar) 255, buff, 2, err, length);
- DBUG_VOID_RETURN;
-}
-#endif
-
-/*
- Send a warning to the end user
-
- SYNOPSIS
- send_warning()
- thd Thread handler
- sql_errno Warning number (error message)
- err Error string. If not set, use ER(sql_errno)
-
- DESCRIPTION
- Register the warning so that the user can get it with mysql_warnings()
- Send an ok (+ warning count) to the end user.
-*/
-
-void send_warning(THD *thd, uint sql_errno, const char *err)
-{
- DBUG_ENTER("send_warning");
- push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, sql_errno,
- err ? err : ER(sql_errno));
- send_ok(thd);
- DBUG_VOID_RETURN;
-}
-
-
-/*
- Write error package and flush to client
- It's a little too low level, but I don't want to use another buffer for
- this
-*/
-
-void
-net_printf(THD *thd, uint errcode, ...)
-{
- va_list args;
- uint length,offset;
- const char *format;
-#ifndef EMBEDDED_LIBRARY
- const char *text_pos;
-#else
- char text_pos[500];
-#endif
- int head_length= NET_HEADER_SIZE;
- NET *net= &thd->net;
-
- DBUG_ENTER("net_printf");
- DBUG_PRINT("enter",("message: %u",errcode));
-
- thd->query_error= 1; // needed to catch query errors during replication
-#ifndef EMBEDDED_LIBRARY
- query_cache_abort(net); // Safety
-#endif
- va_start(args,errcode);
- /*
- The following is needed to make net_printf() work with 0 argument for
- errorcode and use the argument after that as the format string. This
- is useful for rare errors that are not worth the hassle to put in
- errmsg.sys, but at the same time, the message is not fixed text
- */
- if (errcode)
- format= ER(errcode);
- else
- {
- format=va_arg(args,char*);
- errcode= ER_UNKNOWN_ERROR;
- }
- offset= net->return_errno ? 2 : 0;
-#ifndef EMBEDDED_LIBRARY
- text_pos=(char*) net->buff+head_length+offset+1;
-#endif
- (void) vsprintf(my_const_cast(char*) (text_pos),format,args);
- length=(uint) strlen((char*) text_pos);
- if (length >= sizeof(net->last_error))
- length=sizeof(net->last_error)-1; /* purecov: inspected */
- va_end(args);
-
-#ifndef EMBEDDED_LIBRARY
- if (net->vio == 0)
- {
- if (thd->bootstrap)
- {
- /* In bootstrap it's ok to print on stderr */
- fprintf(stderr,"ERROR: %d %s\n",errcode,text_pos);
- thd->fatal_error=1;
- }
- DBUG_VOID_RETURN;
- }
-
- int3store(net->buff,length+1+offset);
- net->buff[3]= (net->compress) ? 0 : (uchar) (net->pkt_nr++);
- net->buff[head_length]=(uchar) 255; // Error package
- if (offset)
- int2store(text_pos-2, errcode);
- VOID(net_real_write(net,(char*) net->buff,length+head_length+1+offset));
-#else
- net->last_errno= errcode;
- strmake(net->last_error, text_pos, length);
-#endif
- thd->fatal_error=0; // Error message is given
- DBUG_VOID_RETURN;
-}
-
-/*
- Function called by my_net_init() to set some check variables
-*/
-
-#ifndef EMBEDDED_LIBRARY
-extern "C" {
-void my_net_local_init(NET *net)
-{
- net->max_packet= (uint) global_system_variables.net_buffer_length;
- net->read_timeout= (uint) global_system_variables.net_read_timeout;
- net->write_timeout=(uint) global_system_variables.net_write_timeout;
- net->retry_count= (uint) global_system_variables.net_retry_count;
- net->max_packet_size= max(global_system_variables.net_buffer_length,
- global_system_variables.max_allowed_packet);
-}
-}
-
-#else /* EMBEDDED_LIBRARY */
-void my_net_local_init(NET *net __attribute__(unused))
-{
-}
-#endif /* EMBEDDED_LIBRARY */
-
-/*
- Return ok to the client.
-
- SYNOPSIS
- send_ok()
- thd Thread handler
- affected_rows Number of rows changed by statement
- id Auto_increment id for first row (if used)
- message Message to send to the client (Used by mysql_status)
-
- DESCRIPTION
- The ok packet has the following structure
-
- 0 Marker (1 byte)
- affected_rows Stored in 1-9 bytes
- id Stored in 1-9 bytes
- server_status Copy of thd->server_status; Can be used by client
- to check if we are inside an transaction
- New in 4.0 protocol
- warning_count Stored in 2 bytes; New in 4.1 protocol
- message Stored as packed length (1-9 bytes) + message
- Is not stored if no message
-
- If net->no_send_ok return without sending packet
-*/
-#ifndef EMBEDDED_LIBRARY
-
-void
-send_ok(THD *thd, ha_rows affected_rows, ulonglong id, const char *message)
-{
- NET *net= &thd->net;
- if (net->no_send_ok || !net->vio) // hack for re-parsing queries
- return;
-
- char buff[MYSQL_ERRMSG_SIZE+10],*pos;
- DBUG_ENTER("send_ok");
- buff[0]=0; // No fields
- pos=net_store_length(buff+1,(ulonglong) affected_rows);
- pos=net_store_length(pos, (ulonglong) id);
- if (thd->client_capabilities & CLIENT_PROTOCOL_41)
- {
- int2store(pos,thd->server_status);
- pos+=2;
-
- /* We can only return up to 65535 warnings in two bytes */
- uint tmp= min(thd->total_warn_count, 65535);
- int2store(pos, tmp);
- pos+= 2;
- }
- else if (net->return_status) // For 4.0 protocol
- {
- int2store(pos,thd->server_status);
- pos+=2;
- }
- if (message)
- pos=net_store_data((char*) pos,message);
- VOID(my_net_write(net,buff,(uint) (pos-buff)));
- VOID(net_flush(net));
- DBUG_VOID_RETURN;
-}
-
-
-/*
- Send eof (= end of result set) to the client
-
- SYNOPSIS
- send_eof()
- thd Thread handler
- no_flush Set to 1 if there will be more data to the client,
- like in send_fields().
-
- DESCRIPTION
- The eof packet has the following structure
-
- 254 Marker (1 byte)
- warning_count Stored in 2 bytes; New in 4.1 protocol
- status_flag Stored in 2 bytes;
- For flags like SERVER_STATUS_MORE_RESULTS
-
- Note that the warning count will not be sent if 'no_flush' is set as
- we don't want to report the warning count until all data is sent to the
- client.
-*/
-
-void
-send_eof(THD *thd, bool no_flush)
-{
- static char eof_buff[1]= { (char) 254 }; /* Marker for end of fields */
- NET *net= &thd->net;
- DBUG_ENTER("send_eof");
- if (net->vio != 0)
- {
- if (!no_flush && (thd->client_capabilities & CLIENT_PROTOCOL_41))
- {
- uchar buff[5];
- uint tmp= min(thd->total_warn_count, 65535);
- buff[0]=254;
- int2store(buff+1, tmp);
- int2store(buff+3, 0); // No flags yet
- VOID(my_net_write(net,(char*) buff,5));
- VOID(net_flush(net));
- }
- else
- {
- VOID(my_net_write(net,eof_buff,1));
- if (!no_flush)
- VOID(net_flush(net));
- }
- }
- DBUG_VOID_RETURN;
-}
-#endif /* EMBEDDED_LIBRARY */
-
-
-/****************************************************************************
-** Store a field length in logical packet
-****************************************************************************/
-
-char *
-net_store_length(char *pkg, ulonglong length)
-{
- uchar *packet=(uchar*) pkg;
- if (length < LL(251))
- {
- *packet=(uchar) length;
- return (char*) packet+1;
- }
- /* 251 is reserved for NULL */
- if (length < LL(65536))
- {
- *packet++=252;
- int2store(packet,(uint) length);
- return (char*) packet+2;
- }
- if (length < LL(16777216))
- {
- *packet++=253;
- int3store(packet,(ulong) length);
- return (char*) packet+3;
- }
- *packet++=254;
- int8store(packet,length);
- return (char*) packet+9;
-}
-
-char *
-net_store_length(char *pkg, uint length)
-{
- uchar *packet=(uchar*) pkg;
- if (length < 251)
- {
- *packet=(uchar) length;
- return (char*) packet+1;
- }
- *packet++=252;
- int2store(packet,(uint) length);
- return (char*) packet+2;
-}
-
-/* The following will only be used for short strings < 65K */
-char *
-net_store_data(char *to,const char *from)
-{
- uint length=(uint) strlen(from);
- to=net_store_length(to,length);
- memcpy(to,from,length);
- return to+length;
-}
-
-
-char *
-net_store_data(char *to,int32 from)
-{
- char buff[20];
- uint length=(uint) (int10_to_str(from,buff,10)-buff);
- to=net_store_length(to,length);
- memcpy(to,buff,length);
- return to+length;
-}
-
-char *
-net_store_data(char *to,longlong from)
-{
- char buff[22];
- uint length=(uint) (longlong10_to_str(from,buff,10)-buff);
- to=net_store_length(to,length);
- memcpy(to,buff,length);
- return to+length;
-}
-
-
-bool net_store_null(String *packet)
-{
- return packet->append((char) 251);
-}
-
-bool
-net_store_data(String *packet,const char *from,uint length)
-{
- ulong packet_length=packet->length();
- if (packet_length+5+length > packet->alloced_length() &&
- packet->realloc(packet_length+5+length))
- return 1;
- char *to=(char*) net_store_length((char*) packet->ptr()+packet_length,
- (ulonglong) length);
- memcpy(to,from,length);
- packet->length((uint) (to+length-packet->ptr()));
- return 0;
-}
-
-/* The following is only used at short, null terminated data */
-
-bool
-net_store_data(String *packet,const char *from)
-{
- uint length=(uint) strlen(from);
- uint packet_length=packet->length();
- if (packet_length+5+length > packet->alloced_length() &&
- packet->realloc(packet_length+5+length))
- return 1;
- char *to=(char*) net_store_length((char*) packet->ptr()+packet_length,
- length);
- memcpy(to,from,length);
- packet->length((uint) (to+length-packet->ptr()));
- return 0;
-}
-
-
-bool
-net_store_data(String *packet,uint32 from)
-{
- char buff[20];
- return net_store_data(packet,(char*) buff,
- (uint) (int10_to_str(from,buff,10)-buff));
-}
-
-bool
-net_store_data(String *packet, longlong from)
-{
- char buff[22];
- return net_store_data(packet,(char*) buff,
- (uint) (longlong10_to_str(from,buff,10)-buff));
-}
-
-bool
-net_store_data(String *packet,struct tm *tmp)
-{
- char buff[20];
- sprintf(buff,"%04d-%02d-%02d %02d:%02d:%02d",
- ((int) (tmp->tm_year+1900)) % 10000,
- (int) tmp->tm_mon+1,
- (int) tmp->tm_mday,
- (int) tmp->tm_hour,
- (int) tmp->tm_min,
- (int) tmp->tm_sec);
- return net_store_data(packet,(char*) buff,19);
-}
-
-bool net_store_data(String* packet, I_List<i_string>* str_list)
-{
- char buf[256];
- String tmp(buf, sizeof(buf), default_charset_info);
- tmp.length(0);
- I_List_iterator<i_string> it(*str_list);
- i_string* s;
-
- while ((s=it++))
- {
- if (tmp.length())
- tmp.append(',');
- tmp.append(s->ptr);
- }
-
- return net_store_data(packet, (char*)tmp.ptr(), tmp.length());
-}
-
-/*
-** translate and store data; These are mainly used by the SHOW functions
-*/
-
-bool
-net_store_data(String *packet,CONVERT *convert, const char *from,uint length)
-{
- if (convert)
- return convert->store(packet, from, length);
- return net_store_data(packet,from,length);
-}
-
-bool
-net_store_data(String *packet, CONVERT *convert, const char *from)
-{
- uint length=(uint) strlen(from);
- if (convert)
- return convert->store(packet, from, length);
- return net_store_data(packet,from,length);
-}
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index d76737e8e31..bcea522cb6d 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -1042,7 +1042,8 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part,
DBUG_RETURN(0);
if (maybe_null)
*str= (char) field->is_real_null(); // Set to 1 if null
- field->get_key_image(str+maybe_null,key_part->part_length, key_part->image_type);
+ field->get_key_image(str+maybe_null,key_part->part_length,
+ key_part->image_type);
if (!(tree=new SEL_ARG(field,str,str)))
DBUG_RETURN(0);
@@ -2284,9 +2285,11 @@ get_quick_keys(PARAM *param,QUICK_SELECT *quick,KEY_PART *key,
key_tree->min_flag : key_tree->min_flag | key_tree->max_flag;
}
- /* Ensure that some part of min_key and max_key are used. If not,
- regard this as no lower/upper range */
- if((flag & GEOM_FLAG) == 0)
+ /*
+ Ensure that some part of min_key and max_key are used. If not,
+ regard this as no lower/upper range
+ */
+ if ((flag & GEOM_FLAG) == 0)
{
if (tmp_min_key != param->min_key)
flag&= ~NO_MIN_RANGE;
@@ -2451,17 +2454,17 @@ int QUICK_SELECT::get_next()
if (!(range=it++))
DBUG_RETURN(HA_ERR_END_OF_FILE); // All ranges used
- if(range->flag & GEOM_FLAG)
+ if (range->flag & GEOM_FLAG)
{
if ((result = file->index_read(record,
- (byte*) (range->min_key + ((range->flag & GEOM_FLAG) > 0)),
- range->min_length,
- (ha_rkey_function)(range->flag ^ GEOM_FLAG))))
-
+ (byte*) (range->min_key +1),
+ range->min_length,
+ (ha_rkey_function)(range->flag ^
+ GEOM_FLAG))))
{
if (result != HA_ERR_KEY_NOT_FOUND)
DBUG_RETURN(result);
- range=0; // Not found, to next range
+ range=0; // Not found, to next range
continue;
}
DBUG_RETURN(0);
@@ -2478,13 +2481,14 @@ int QUICK_SELECT::get_next()
continue;
}
if ((result = file->index_read(record,
- (byte*) (range->min_key + ((range->flag & GEOM_FLAG) > 0)),
- range->min_length,
- (range->flag & NEAR_MIN) ?
- HA_READ_AFTER_KEY:
- (range->flag & EQ_RANGE) ?
- HA_READ_KEY_EXACT :
- HA_READ_KEY_OR_NEXT)))
+ (byte*) (range->min_key +
+ test(range->flag & GEOM_FLAG)),
+ range->min_length,
+ (range->flag & NEAR_MIN) ?
+ HA_READ_AFTER_KEY:
+ (range->flag & EQ_RANGE) ?
+ HA_READ_KEY_EXACT :
+ HA_READ_KEY_OR_NEXT)))
{
if (result != HA_ERR_KEY_NOT_FOUND)
@@ -2502,8 +2506,11 @@ int QUICK_SELECT::get_next()
}
}
- /* compare if found key is over max-value */
- /* Returns 0 if key <= range->max_key */
+
+/*
+ Compare if found key is over max-value
+ Returns 0 if key <= range->max_key
+*/
int QUICK_SELECT::cmp_next(QUICK_RANGE *range_arg)
{
diff --git a/sql/procedure.h b/sql/procedure.h
index b72c5cb559f..bc1b6062e1d 100644
--- a/sql/procedure.h
+++ b/sql/procedure.h
@@ -55,7 +55,7 @@ public:
decimals=dec; max_length=float_length(dec);
}
enum Item_result result_type () const { return REAL_RESULT; }
- enum_field_types field_type() const { return FIELD_TYPE_DOUBLE; }
+ enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
void set(double nr) { value=nr; }
void set(longlong nr) { value=(double) nr; }
void set(const char *str,uint length,CHARSET_INFO *cs)
@@ -73,7 +73,7 @@ public:
Item_proc_int(const char *name_par) :Item_proc(name_par)
{ max_length=11; }
enum Item_result result_type () const { return INT_RESULT; }
- enum_field_types field_type() const { return FIELD_TYPE_LONG; }
+ enum_field_types field_type() const { return MYSQL_TYPE_LONGLONG; }
void set(double nr) { value=(longlong) nr; }
void set(longlong nr) { value=nr; }
void set(const char *str,uint length, CHARSET_INFO *cs)
@@ -91,7 +91,7 @@ public:
Item_proc_string(const char *name_par,uint length) :Item_proc(name_par)
{ this->max_length=length; }
enum Item_result result_type () const { return STRING_RESULT; }
- enum_field_types field_type() const { return FIELD_TYPE_STRING; }
+ enum_field_types field_type() const { return MYSQL_TYPE_STRING; }
void set(double nr) { str_value.set(nr, 2, thd_charset()); }
void set(longlong nr) { str_value.set(nr, thd_charset()); }
void set(const char *str, uint length, CHARSET_INFO *cs)
diff --git a/sql/protocol.cc b/sql/protocol.cc
new file mode 100644
index 00000000000..ec7ced0e626
--- /dev/null
+++ b/sql/protocol.cc
@@ -0,0 +1,1038 @@
+/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/*
+ Low level functions for storing data to be send to the MySQL client
+ The actual communction is handled by the net_xxx functions in net_serv.cc
+*/
+
+#ifdef __GNUC__
+#pragma implementation // gcc: Class implementation
+#endif
+
+#include "mysql_priv.h"
+#include <stdarg.h>
+#include <assert.h>
+
+ /* Send a error string to client */
+
+void send_error(THD *thd, uint sql_errno, const char *err)
+{
+ uint length;
+ char buff[MYSQL_ERRMSG_SIZE+2];
+ NET *net= &thd->net;
+ DBUG_ENTER("send_error");
+ DBUG_PRINT("enter",("sql_errno: %d err: %s", sql_errno,
+ err ? err : net->last_error[0] ?
+ net->last_error : "NULL"));
+
+#ifndef EMBEDDED_LIBRARY
+ query_cache_abort(net);
+#endif
+ thd->query_error= 1; // needed to catch query errors during replication
+ if (!err)
+ {
+ if (sql_errno)
+ err=ER(sql_errno);
+ else
+ {
+ if ((err=net->last_error)[0])
+ sql_errno=net->last_errno;
+ else
+ {
+ sql_errno=ER_UNKNOWN_ERROR;
+ err=ER(sql_errno); /* purecov: inspected */
+ }
+ }
+ }
+
+#ifdef EMBEDDED_LIBRARY
+ net->last_errno= sql_errno;
+ strmake(net->last_error, err, sizeof(net->last_error)-1);
+#else
+
+ if (net->vio == 0)
+ {
+ if (thd->bootstrap)
+ {
+ /* In bootstrap it's ok to print on stderr */
+ fprintf(stderr,"ERROR: %d %s\n",sql_errno,err);
+ }
+ DBUG_VOID_RETURN;
+ }
+
+ if (net->return_errno)
+ { // new client code; Add errno before message
+ int2store(buff,sql_errno);
+ length= (uint) (strmake(buff+2,err,MYSQL_ERRMSG_SIZE-1) - buff);
+ err=buff;
+ }
+ else
+ {
+ length=(uint) strlen(err);
+ set_if_smaller(length,MYSQL_ERRMSG_SIZE-1);
+ }
+ VOID(net_write_command(net,(uchar) 255, "", 0, (char*) err,length));
+#endif /* EMBEDDED_LIBRARY*/
+ thd->fatal_error=0; // Error message is given
+ thd->net.report_error= 0;
+ DBUG_VOID_RETURN;
+}
+
+/*
+ Send an error to the client when a connection is forced close
+ This is used by mysqld.cc, which doesn't have a THD
+*/
+
+#ifndef EMBEDDED_LIBRARY
+void net_send_error(NET *net, uint sql_errno, const char *err)
+{
+ char buff[2];
+ uint length;
+ DBUG_ENTER("send_net_error");
+
+ int2store(buff,sql_errno);
+ length=(uint) strlen(err);
+ set_if_smaller(length,MYSQL_ERRMSG_SIZE-1);
+ net_write_command(net,(uchar) 255, buff, 2, err, length);
+ DBUG_VOID_RETURN;
+}
+#endif
+
+/*
+ Send a warning to the end user
+
+ SYNOPSIS
+ send_warning()
+ thd Thread handler
+ sql_errno Warning number (error message)
+ err Error string. If not set, use ER(sql_errno)
+
+ DESCRIPTION
+ Register the warning so that the user can get it with mysql_warnings()
+ Send an ok (+ warning count) to the end user.
+*/
+
+void send_warning(THD *thd, uint sql_errno, const char *err)
+{
+ DBUG_ENTER("send_warning");
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, sql_errno,
+ err ? err : ER(sql_errno));
+ send_ok(thd);
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ Write error package and flush to client
+ It's a little too low level, but I don't want to use another buffer for
+ this
+*/
+
+void
+net_printf(THD *thd, uint errcode, ...)
+{
+ va_list args;
+ uint length,offset;
+ const char *format;
+#ifndef EMBEDDED_LIBRARY
+ const char *text_pos;
+#else
+ char text_pos[500];
+#endif
+ int head_length= NET_HEADER_SIZE;
+ NET *net= &thd->net;
+
+ DBUG_ENTER("net_printf");
+ DBUG_PRINT("enter",("message: %u",errcode));
+
+ thd->query_error= 1; // needed to catch query errors during replication
+#ifndef EMBEDDED_LIBRARY
+ query_cache_abort(net); // Safety
+#endif
+ va_start(args,errcode);
+ /*
+ The following is needed to make net_printf() work with 0 argument for
+ errorcode and use the argument after that as the format string. This
+ is useful for rare errors that are not worth the hassle to put in
+ errmsg.sys, but at the same time, the message is not fixed text
+ */
+ if (errcode)
+ format= ER(errcode);
+ else
+ {
+ format=va_arg(args,char*);
+ errcode= ER_UNKNOWN_ERROR;
+ }
+ offset= net->return_errno ? 2 : 0;
+#ifndef EMBEDDED_LIBRARY
+ text_pos=(char*) net->buff+head_length+offset+1;
+#endif
+ (void) vsprintf(my_const_cast(char*) (text_pos),format,args);
+ length=(uint) strlen((char*) text_pos);
+ if (length >= sizeof(net->last_error))
+ length=sizeof(net->last_error)-1; /* purecov: inspected */
+ va_end(args);
+
+#ifndef EMBEDDED_LIBRARY
+ if (net->vio == 0)
+ {
+ if (thd->bootstrap)
+ {
+ /* In bootstrap it's ok to print on stderr */
+ fprintf(stderr,"ERROR: %d %s\n",errcode,text_pos);
+ thd->fatal_error=1;
+ }
+ DBUG_VOID_RETURN;
+ }
+
+ int3store(net->buff,length+1+offset);
+ net->buff[3]= (net->compress) ? 0 : (uchar) (net->pkt_nr++);
+ net->buff[head_length]=(uchar) 255; // Error package
+ if (offset)
+ int2store(text_pos-2, errcode);
+ VOID(net_real_write(net,(char*) net->buff,length+head_length+1+offset));
+#else
+ net->last_errno= errcode;
+ strmake(net->last_error, text_pos, length);
+#endif
+ thd->fatal_error=0; // Error message is given
+ DBUG_VOID_RETURN;
+}
+
+/*
+ Function called by my_net_init() to set some check variables
+*/
+
+#ifndef EMBEDDED_LIBRARY
+extern "C" {
+void my_net_local_init(NET *net)
+{
+ net->max_packet= (uint) global_system_variables.net_buffer_length;
+ net->read_timeout= (uint) global_system_variables.net_read_timeout;
+ net->write_timeout=(uint) global_system_variables.net_write_timeout;
+ net->retry_count= (uint) global_system_variables.net_retry_count;
+ net->max_packet_size= max(global_system_variables.net_buffer_length,
+ global_system_variables.max_allowed_packet);
+}
+}
+
+#else /* EMBEDDED_LIBRARY */
+void my_net_local_init(NET *net __attribute__(unused))
+{
+}
+#endif /* EMBEDDED_LIBRARY */
+
+/*
+ Return ok to the client.
+
+ SYNOPSIS
+ send_ok()
+ thd Thread handler
+ affected_rows Number of rows changed by statement
+ id Auto_increment id for first row (if used)
+ message Message to send to the client (Used by mysql_status)
+
+ DESCRIPTION
+ The ok packet has the following structure
+
+ 0 Marker (1 byte)
+ affected_rows Stored in 1-9 bytes
+ id Stored in 1-9 bytes
+ server_status Copy of thd->server_status; Can be used by client
+ to check if we are inside an transaction
+ New in 4.0 protocol
+ warning_count Stored in 2 bytes; New in 4.1 protocol
+ message Stored as packed length (1-9 bytes) + message
+ Is not stored if no message
+
+ If net->no_send_ok return without sending packet
+*/
+#ifndef EMBEDDED_LIBRARY
+
+void
+send_ok(THD *thd, ha_rows affected_rows, ulonglong id, const char *message)
+{
+ NET *net= &thd->net;
+ if (net->no_send_ok || !net->vio) // hack for re-parsing queries
+ return;
+
+ char buff[MYSQL_ERRMSG_SIZE+10],*pos;
+ DBUG_ENTER("send_ok");
+ buff[0]=0; // No fields
+ pos=net_store_length(buff+1,(ulonglong) affected_rows);
+ pos=net_store_length(pos, (ulonglong) id);
+ if (thd->client_capabilities & CLIENT_PROTOCOL_41)
+ {
+ int2store(pos,thd->server_status);
+ pos+=2;
+
+ /* We can only return up to 65535 warnings in two bytes */
+ uint tmp= min(thd->total_warn_count, 65535);
+ int2store(pos, tmp);
+ pos+= 2;
+ }
+ else if (net->return_status) // For 4.0 protocol
+ {
+ int2store(pos,thd->server_status);
+ pos+=2;
+ }
+ if (message)
+ pos=net_store_data((char*) pos, message, strlen(message));
+ VOID(my_net_write(net,buff,(uint) (pos-buff)));
+ VOID(net_flush(net));
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ Send eof (= end of result set) to the client
+
+ SYNOPSIS
+ send_eof()
+ thd Thread handler
+ no_flush Set to 1 if there will be more data to the client,
+ like in send_fields().
+
+ DESCRIPTION
+ The eof packet has the following structure
+
+ 254 Marker (1 byte)
+ warning_count Stored in 2 bytes; New in 4.1 protocol
+ status_flag Stored in 2 bytes;
+ For flags like SERVER_STATUS_MORE_RESULTS
+
+ Note that the warning count will not be sent if 'no_flush' is set as
+ we don't want to report the warning count until all data is sent to the
+ client.
+*/
+
+void
+send_eof(THD *thd, bool no_flush)
+{
+ static char eof_buff[1]= { (char) 254 }; /* Marker for end of fields */
+ NET *net= &thd->net;
+ DBUG_ENTER("send_eof");
+ if (net->vio != 0)
+ {
+ if (!no_flush && (thd->client_capabilities & CLIENT_PROTOCOL_41))
+ {
+ uchar buff[5];
+ uint tmp= min(thd->total_warn_count, 65535);
+ buff[0]=254;
+ int2store(buff+1, tmp);
+ int2store(buff+3, 0); // No flags yet
+ VOID(my_net_write(net,(char*) buff,5));
+ VOID(net_flush(net));
+ }
+ else
+ {
+ VOID(my_net_write(net,eof_buff,1));
+ if (!no_flush)
+ VOID(net_flush(net));
+ }
+ }
+ DBUG_VOID_RETURN;
+}
+#endif /* EMBEDDED_LIBRARY */
+
+
+/****************************************************************************
+ Store a field length in logical packet
+
+ This is used to code the string length for normal protocol
+****************************************************************************/
+
+char *
+net_store_length(char *pkg, ulonglong length)
+{
+ uchar *packet=(uchar*) pkg;
+ if (length < LL(251))
+ {
+ *packet=(uchar) length;
+ return (char*) packet+1;
+ }
+ /* 251 is reserved for NULL */
+ if (length < LL(65536))
+ {
+ *packet++=252;
+ int2store(packet,(uint) length);
+ return (char*) packet+2;
+ }
+ if (length < LL(16777216))
+ {
+ *packet++=253;
+ int3store(packet,(ulong) length);
+ return (char*) packet+3;
+ }
+ *packet++=254;
+ int8store(packet,length);
+ return (char*) packet+9;
+}
+
+
+/*
+ Faster net_store_length when we know length is a 32 bit integer
+*/
+
+char *net_store_length(char *pkg, uint length)
+{
+ uchar *packet=(uchar*) pkg;
+ if (length < 251)
+ {
+ *packet=(uchar) length;
+ return (char*) packet+1;
+ }
+ *packet++=252;
+ int2store(packet,(uint) length);
+ return (char*) packet+2;
+}
+
+
+/*
+ Used internally for storing strings in packet
+*/
+
+static bool net_store_data(String *packet, const char *from, uint length)
+{
+ ulong packet_length=packet->length();
+ if (packet_length+5+length > packet->alloced_length() &&
+ packet->realloc(packet_length+5+length))
+ return 1;
+ char *to=(char*) net_store_length((char*) packet->ptr()+packet_length,
+ (ulonglong) length);
+ memcpy(to,from,length);
+ packet->length((uint) (to+length-packet->ptr()));
+ return 0;
+}
+
+/****************************************************************************
+ Functions used by the protocol functions (like send_ok) to store strings
+ and numbers in the header result packet.
+****************************************************************************/
+
+/* The following will only be used for short strings < 65K */
+
+char *net_store_data(char *to,const char *from, uint length)
+{
+ to=net_store_length(to,length);
+ memcpy(to,from,length);
+ return to+length;
+}
+
+char *net_store_data(char *to,int32 from)
+{
+ char buff[20];
+ uint length=(uint) (int10_to_str(from,buff,10)-buff);
+ to=net_store_length(to,length);
+ memcpy(to,buff,length);
+ return to+length;
+}
+
+char *net_store_data(char *to,longlong from)
+{
+ char buff[22];
+ uint length=(uint) (longlong10_to_str(from,buff,10)-buff);
+ to=net_store_length(to,length);
+ memcpy(to,buff,length);
+ return to+length;
+}
+
+/*
+ Function called by my_net_init() to set some check variables
+*/
+
+extern "C" {
+void my_net_local_init(NET *net)
+{
+ net->max_packet= (uint) global_system_variables.net_buffer_length;
+ net->read_timeout= (uint) global_system_variables.net_read_timeout;
+ net->write_timeout=(uint) global_system_variables.net_write_timeout;
+ net->retry_count= (uint) global_system_variables.net_retry_count;
+ net->max_packet_size= max(global_system_variables.net_buffer_length,
+ global_system_variables.max_allowed_packet);
+}
+}
+
+
+/*****************************************************************************
+ Default Protocol functions
+*****************************************************************************/
+
+void Protocol::init(THD *thd_arg)
+{
+ thd=thd_arg;
+ convert=thd->variables.convert_set;
+ packet= &thd->packet;
+#ifndef DEBUG_OFF
+ field_types= 0;
+#endif
+}
+
+/*
+ Send name and type of result to client.
+
+ SYNOPSIS
+ send_fields()
+ THD Thread data object
+ list List of items to send to client
+ convert object used to convertation to another character set
+ flag Bit mask with the following functions:
+ 1 send number of rows
+ 2 send default values
+
+ DESCRIPTION
+ Sum fields has table name empty and field_name.
+ Uses send_fields_convert() and send_fields() depending on
+ if we have an active character set convert or not.
+
+ RETURN VALUES
+ 0 ok
+ 1 Error (Note that in this case the error is not sent to the client)
+*/
+
+bool Protocol::send_fields(List<Item> *list, uint flag)
+{
+ List_iterator_fast<Item> it(*list);
+ Item *item;
+ char buff[80];
+ String tmp((char*) buff,sizeof(buff),default_charset_info);
+ Protocol_simple prot(thd);
+ String *packet= prot.storage_packet();
+ DBUG_ENTER("send_fields");
+
+ if (flag & 1)
+ { // Packet with number of elements
+ char *pos=net_store_length(buff, (uint) list->elements);
+ (void) my_net_write(&thd->net, buff,(uint) (pos-buff));
+ }
+
+#ifndef DEBUG_OFF
+ field_types= (enum_field_types*) thd->alloc(sizeof(field_types) *
+ list->elements);
+ uint count= 0;
+#endif
+
+ while ((item=it++))
+ {
+ char *pos;
+ Send_field field;
+ item->make_field(&field);
+ prot.prepare_for_resend();
+
+ if (thd->client_capabilities & CLIENT_PROTOCOL_41)
+ {
+ if (prot.store(field.db_name, (uint) strlen(field.db_name)) ||
+ prot.store(field.table_name, (uint) strlen(field.table_name)) ||
+ prot.store(field.org_table_name,
+ (uint) strlen(field.org_table_name)) ||
+ prot.store(field.col_name, (uint) strlen(field.col_name)) ||
+ prot.store(field.org_col_name, (uint) strlen(field.org_col_name)))
+ goto err;
+ }
+ else
+ {
+ if (prot.store(field.table_name, (uint) strlen(field.table_name)) ||
+ prot.store(field.col_name, (uint) strlen(field.col_name)))
+ goto err;
+ }
+ if (packet->realloc(packet->length()+10))
+ goto err;
+ pos= (char*) packet->ptr()+packet->length();
+
+#ifdef TO_BE_DELETED_IN_6
+ if (!(thd->client_capabilities & CLIENT_LONG_FLAG))
+ {
+ packet->length(packet->length()+9);
+ pos[0]=3; int3store(pos+1,field.length);
+ pos[4]=1; pos[5]=field.type;
+ pos[6]=2; pos[7]=(char) field.flags; pos[8]= (char) field.decimals;
+ }
+ else
+#endif
+ {
+ packet->length(packet->length()+10);
+ pos[0]=3; int3store(pos+1,field.length);
+ pos[4]=1; pos[5]=field.type;
+ pos[6]=3; int2store(pos+7,field.flags); pos[9]= (char) field.decimals;
+ }
+ if (flag & 2)
+ item->send(&prot, &tmp); // Send default value
+ if (prot.write())
+ break; /* purecov: inspected */
+#ifndef DEBUG_OFF
+ field_types[count++]= field.type;
+#endif
+ }
+
+ send_eof(thd);
+ DBUG_RETURN(prepare_for_send(list));
+
+err:
+ send_error(thd,ER_OUT_OF_RESOURCES); /* purecov: inspected */
+ DBUG_RETURN(1); /* purecov: inspected */
+}
+
+
+bool Protocol::write()
+{
+ DBUG_ENTER("Protocol::write");
+ DBUG_RETURN(my_net_write(&thd->net, packet->ptr(), packet->length()));
+}
+
+
+/*
+ Send \0 end terminated string
+
+ SYNOPSIS
+ store()
+ from NullS or \0 terminated string
+
+ NOTES
+ In most cases one should use store(from, length) instead of this function
+
+ RETURN VALUES
+ 0 ok
+ 1 error
+*/
+
+bool Protocol::store(const char *from)
+{
+ if (!from)
+ return store_null();
+ uint length= strlen(from);
+ return store(from, length);
+}
+
+
+/*
+ Send a set of strings as one long string with ',' in between
+*/
+
+bool Protocol::store(I_List<i_string>* str_list)
+{
+ char buf[256];
+ String tmp(buf, sizeof(buf), default_charset_info);
+ uint32 len;
+ I_List_iterator<i_string> it(*str_list);
+ i_string* s;
+
+ tmp.length(0);
+ while ((s=it++))
+ {
+ tmp.append(s->ptr);
+ tmp.append(',');
+ }
+ if ((len= tmp.length()))
+ len--; // Remove last ','
+ return store((char*) tmp.ptr(), len);
+}
+
+
+/****************************************************************************
+ Functions to handle the simple (default) protocol where everything is
+ This protocol is the one that is used by default between the MySQL server
+ and client when you are not using prepared statements.
+
+ All data are sent as 'packed-string-length' followed by 'string-data'
+
+****************************************************************************/
+
+void Protocol_simple::prepare_for_resend()
+{
+ packet->length(0);
+#ifndef DEBUG_OFF
+ field_pos= 0;
+#endif
+}
+
+bool Protocol_simple::store_null()
+{
+#ifndef DEBUG_OFF
+ field_pos++;
+#endif
+ char buff[1];
+ buff[0]= 251;
+ return packet->append(buff, sizeof(buff), PACKET_BUFFET_EXTRA_ALLOC);
+}
+
+bool Protocol_simple::store(const char *from, uint length)
+{
+#ifndef DEBUG_OFF
+ DBUG_ASSERT(field_types == 0 ||
+ field_types[field_pos] == MYSQL_TYPE_DECIMAL ||
+ (field_types[field_pos] >= MYSQL_TYPE_ENUM &&
+ field_types[field_pos] <= MYSQL_TYPE_GEOMETRY));
+ field_pos++;
+#endif
+ if (convert)
+ return convert->store(packet, from, length);
+ return net_store_data(packet, from, length);
+}
+
+
+bool Protocol_simple::store_tiny(longlong from)
+{
+#ifndef DEBUG_OFF
+ DBUG_ASSERT(field_types == 0 || field_types[field_pos++] == MYSQL_TYPE_TINY);
+#endif
+ char buff[20];
+ return net_store_data(packet,(char*) buff,
+ (uint) (int10_to_str((int) from,buff, -10)-buff));
+}
+
+bool Protocol_simple::store_short(longlong from)
+{
+#ifndef DEBUG_OFF
+ DBUG_ASSERT(field_types == 0 ||
+ field_types[field_pos++] == MYSQL_TYPE_SHORT);
+#endif
+ char buff[20];
+ return net_store_data(packet,(char*) buff,
+ (uint) (int10_to_str((int) from,buff, -10)-buff));
+}
+
+bool Protocol_simple::store_long(longlong from)
+{
+#ifndef DEBUG_OFF
+ DBUG_ASSERT(field_types == 0 || field_types[field_pos++] == MYSQL_TYPE_LONG);
+#endif
+ char buff[20];
+ return net_store_data(packet,(char*) buff,
+ (uint) (int10_to_str((int) from,buff, -10)-buff));
+}
+
+
+bool Protocol_simple::store_longlong(longlong from, bool unsigned_flag)
+{
+#ifndef DEBUG_OFF
+ DBUG_ASSERT(field_types == 0 ||
+ field_types[field_pos++] == MYSQL_TYPE_LONGLONG);
+#endif
+ char buff[22];
+ return net_store_data(packet,(char*) buff,
+ (uint) (longlong10_to_str(from,buff,
+ unsigned_flag ? 10 : -10)-
+ buff));
+}
+
+
+bool Protocol_simple::store(float from, uint32 decimals, String *buffer)
+{
+#ifndef DEBUG_OFF
+ DBUG_ASSERT(field_types == 0 ||
+ field_types[field_pos++] == MYSQL_TYPE_FLOAT);
+#endif
+ buffer->set((double) from, decimals, thd->thd_charset);
+ return net_store_data(packet,(char*) buffer->ptr(), buffer->length());
+}
+
+bool Protocol_simple::store(double from, uint32 decimals, String *buffer)
+{
+#ifndef DEBUG_OFF
+ DBUG_ASSERT(field_types == 0 ||
+ field_types[field_pos++] == MYSQL_TYPE_DOUBLE);
+#endif
+ buffer->set(from, decimals, thd->thd_charset);
+ return net_store_data(packet,(char*) buffer->ptr(), buffer->length());
+}
+
+
+bool Protocol_simple::store(Field *field)
+{
+ if (field->is_null())
+ return store_null();
+#ifndef DEBUG_OFF
+ field_pos++;
+#endif
+ char buff[MAX_FIELD_WIDTH];
+ String tmp(buff,sizeof(buff),default_charset_info);
+ field->val_str(&tmp,&tmp);
+ if (convert)
+ return convert->store(packet, tmp.ptr(), tmp.length());
+ return net_store_data(packet, tmp.ptr(), tmp.length());
+}
+
+
+bool Protocol_simple::store(TIME *tm)
+{
+#ifndef DEBUG_OFF
+ DBUG_ASSERT(field_types == 0 ||
+ field_types[field_pos] == MYSQL_TYPE_DATETIME ||
+ field_types[field_pos] == MYSQL_TYPE_TIMESTAMP);
+ field_pos++;
+#endif
+ char buff[40];
+ uint length;
+ length= my_sprintf(buff,(buff, "%04d-%02d-%02d %02d:%02d:%02d",
+ (int) tm->year,
+ (int) tm->month,
+ (int) tm->day,
+ (int) tm->hour,
+ (int) tm->minute,
+ (int) tm->second));
+ return net_store_data(packet, (char*) buff, length);
+}
+
+
+bool Protocol_simple::store_date(TIME *tm)
+{
+#ifndef DEBUG_OFF
+ DBUG_ASSERT(field_types == 0 ||
+ field_types[field_pos++] == MYSQL_TYPE_DATE);
+#endif
+ char buff[40];
+ uint length;
+ length= my_sprintf(buff,(buff, "%04d-%02d-%02d",
+ (int) tm->year,
+ (int) tm->month,
+ (int) tm->day));
+ return net_store_data(packet, (char*) buff, length);
+}
+
+
+bool Protocol_simple::store_time(TIME *tm)
+{
+#ifndef DEBUG_OFF
+ DBUG_ASSERT(field_types == 0 ||
+ field_types[field_pos++] == MYSQL_TYPE_TIME);
+#endif
+ char buff[40];
+ uint length;
+ length= my_sprintf(buff,(buff, "%s%02ld:%02d:%02d",
+ tm->neg ? "-" : "",
+ (long) tm->day*3600L+(long) tm->hour,
+ (int) tm->minute,
+ (int) tm->second));
+ return net_store_data(packet, (char*) buff, length);
+}
+
+
+/****************************************************************************
+ Functions to handle the binary protocol used with prepared statements
+****************************************************************************/
+
+bool Protocol_prep::prepare_for_send(List<Item> *item_list)
+{
+ field_count=item_list->elements;
+ bit_fields= (field_count+3)/8;
+ if (packet->alloc(bit_fields))
+ return 1;
+ /* prepare_for_resend will be called after this one */
+ return 0;
+}
+
+
+void Protocol_prep::prepare_for_resend()
+{
+ packet->length(bit_fields);
+ bzero((char*) packet->ptr()+1, bit_fields-1);
+ packet[0]=1; // Marker for ok packet
+ field_pos=0;
+}
+
+
+bool Protocol_prep::store(const char *from,uint length)
+{
+#ifndef DEBUG_OFF
+ DBUG_ASSERT(field_types == 0 ||
+ field_types[field_pos] == MYSQL_TYPE_DECIMAL ||
+ (field_types[field_pos] >= MYSQL_TYPE_ENUM &&
+ field_types[field_pos] <= MYSQL_TYPE_GEOMETRY));
+#endif
+ field_pos++;
+ if (convert)
+ return convert->store(packet, from, length);
+ return net_store_data(packet, from, length);
+}
+
+
+bool Protocol_prep::store_null()
+{
+ uint offset=(field_pos+2)/8, bit= (1 << ((field_pos+2) & 7));
+ /* Room for this as it's allocated in prepare_for_send */
+ char *to= (char*) packet->ptr()+offset;
+ *to= (char) ((uchar) *to | (uchar) bit);
+ field_pos++;
+ return 0;
+}
+
+
+bool Protocol_prep::store_tiny(longlong from)
+{
+#ifndef DEBUG_OFF
+ DBUG_ASSERT(field_types == 0 ||
+ field_types[field_pos] == MYSQL_TYPE_TINY);
+#endif
+ char buff[1];
+ field_pos++;
+ buff[0]= (uchar) from;
+ return packet->append(buff, sizeof(buff), PACKET_BUFFET_EXTRA_ALLOC);
+}
+
+
+bool Protocol_prep::store_short(longlong from)
+{
+#ifndef DEBUG_OFF
+ DBUG_ASSERT(field_types == 0 ||
+ field_types[field_pos] == MYSQL_TYPE_SHORT);
+#endif
+ field_pos++;
+ char *to= packet->prep_append(2, PACKET_BUFFET_EXTRA_ALLOC);
+ if (!to)
+ return 1;
+ int2store(to, (int) from);
+ return 0;
+}
+
+
+bool Protocol_prep::store_long(longlong from)
+{
+#ifndef DEBUG_OFF
+ DBUG_ASSERT(field_types == 0 ||
+ field_types[field_pos] == MYSQL_TYPE_LONG);
+#endif
+ field_pos++;
+ char *to= packet->prep_append(4, PACKET_BUFFET_EXTRA_ALLOC);
+ if (!to)
+ return 1;
+ int4store(to, from);
+ return 0;
+}
+
+
+bool Protocol_prep::store_longlong(longlong from, bool unsigned_flag)
+{
+#ifndef DEBUG_OFF
+ DBUG_ASSERT(field_types == 0 ||
+ field_types[field_pos] == MYSQL_TYPE_LONGLONG);
+#endif
+ field_pos++;
+ char *to= packet->prep_append(8, PACKET_BUFFET_EXTRA_ALLOC);
+ if (!to)
+ return 1;
+ int8store(to, from);
+ return 0;
+}
+
+
+bool Protocol_prep::store(float from, uint32 decimals, String *buffer)
+{
+#ifndef DEBUG_OFF
+ DBUG_ASSERT(field_types == 0 ||
+ field_types[field_pos] == MYSQL_TYPE_FLOAT);
+#endif
+ field_pos++;
+ char *to= packet->prep_append(4, PACKET_BUFFET_EXTRA_ALLOC);
+ if (!to)
+ return 1;
+ float4store(to, from);
+ return 0;
+}
+
+
+bool Protocol_prep::store(double from, uint32 decimals, String *buffer)
+{
+#ifndef DEBUG_OFF
+ DBUG_ASSERT(field_types == 0 ||
+ field_types[field_pos] == MYSQL_TYPE_DOUBLE);
+#endif
+ field_pos++;
+ char *to= packet->prep_append(8, PACKET_BUFFET_EXTRA_ALLOC);
+ if (!to)
+ return 1;
+ float8store(to, from);
+ return 0;
+}
+
+
+bool Protocol_prep::store(Field *field)
+{
+ /*
+ We should not count up field_pos here as send_binary() will call another
+ protocol function to do this for us
+ */
+ if (field->is_null())
+ return store_null();
+ return field->send_binary(this);
+}
+
+
+bool Protocol_prep::store(TIME *tm)
+{
+#ifndef DEBUG_OFF
+ DBUG_ASSERT(field_types == 0 ||
+ field_types[field_pos] == MYSQL_TYPE_DATETIME ||
+ field_types[field_pos] == MYSQL_TYPE_DATE ||
+ field_types[field_pos] == MYSQL_TYPE_TIMESTAMP);
+#endif
+ char buff[12],*pos;
+ uint length;
+ field_pos++;
+ pos= buff+1;
+
+ int2store(pos, tm->year);
+ int2store(pos+2, tm->month);
+ int2store(pos+3, tm->day);
+ int2store(pos+4, tm->hour);
+ int2store(pos+5, tm->minute);
+ int2store(pos+6, tm->second);
+ int4store(pos+7, tm->second_part);
+ if (tm->second_part)
+ length=11;
+ else if (tm->hour || tm->minute || tm->second)
+ length=7;
+ else if (tm->year || tm->month || tm->day)
+ length=4;
+ else
+ length=0;
+ buff[0]=(char) length; // Length is stored first
+ return packet->append(buff, length+1, PACKET_BUFFET_EXTRA_ALLOC);
+}
+
+bool Protocol_prep::store_date(TIME *tm)
+{
+ tm->hour= tm->minute= tm->second=0;
+ tm->second_part= 0;
+ return Protocol_prep::store(tm);
+}
+
+
+bool Protocol_prep::store_time(TIME *tm)
+{
+#ifndef DEBUG_OFF
+ DBUG_ASSERT(field_types == 0 ||
+ field_types[field_pos] == MYSQL_TYPE_TIME);
+#endif
+ char buff[15],*pos;
+ uint length;
+ field_pos++;
+ pos= buff+1;
+ pos[0]= tm->neg ? 1 : 0;
+ int4store(pos+1, tm->day);
+ int2store(pos+5, tm->hour);
+ int2store(pos+7, tm->minute);
+ int2store(pos+9, tm->second);
+ int4store(pos+11, tm->second_part);
+ if (tm->second_part)
+ length=14;
+ else if (tm->hour || tm->minute || tm->second || tm->day)
+ length=10;
+ else
+ length=0;
+ buff[0]=(char) length; // Length is stored first
+ return packet->append(buff, length+1, PACKET_BUFFET_EXTRA_ALLOC);
+}
diff --git a/sql/protocol.h b/sql/protocol.h
new file mode 100644
index 00000000000..b3ab0a2b31d
--- /dev/null
+++ b/sql/protocol.h
@@ -0,0 +1,131 @@
+/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifdef __GNUC__
+#pragma interface /* gcc class implementation */
+#endif
+
+#define PACKET_BUFFET_EXTRA_ALLOC 1024
+
+class CONVERT;
+class i_string;
+class THD;
+
+class Protocol
+{
+protected:
+ THD *thd;
+ String *packet;
+ uint field_pos;
+#ifndef DEBUG_OFF
+ enum enum_field_types *field_types;
+#endif
+
+public:
+ CONVERT *convert;
+
+ Protocol() {}
+ Protocol(THD *thd) { init(thd); }
+ void init(THD* thd);
+ bool send_fields(List<Item> *list, uint flag);
+ bool store(I_List<i_string> *str_list);
+ bool store(const char *from);
+ String *storage_packet() { return packet; }
+ inline void free() { packet->free(); }
+ bool write();
+ inline bool store(uint32 from)
+ { return store_long((longlong) from); }
+ inline bool store(longlong from)
+ { return store_longlong((longlong) from, 0); }
+ inline bool store(ulonglong from)
+ { return store_longlong((longlong) from, 1); }
+
+ virtual bool prepare_for_send(List<Item> *item_list) { return 0;}
+ virtual void prepare_for_resend()=0;
+
+ virtual bool store_null()=0;
+ virtual bool store_tiny(longlong from)=0;
+ virtual bool store_short(longlong from)=0;
+ virtual bool store_long(longlong from)=0;
+ virtual bool store_longlong(longlong from, bool unsigned_flag)=0;
+ virtual bool store(const char *from, uint length)=0;
+ virtual bool store(float from, uint32 decimals, String *buffer)=0;
+ virtual bool store(double from, uint32 decimals, String *buffer)=0;
+ virtual bool store(TIME *time)=0;
+ virtual bool store_date(TIME *time)=0;
+ virtual bool store_time(TIME *time)=0;
+ virtual bool store(Field *field)=0;
+};
+
+
+/* Class used for the old (MySQL 4.0 protocol) */
+
+class Protocol_simple :public Protocol
+{
+public:
+ Protocol_simple() {}
+ Protocol_simple(THD *thd) :Protocol(thd) {}
+ virtual void prepare_for_resend();
+ virtual bool store_null();
+ virtual bool store_tiny(longlong from);
+ virtual bool store_short(longlong from);
+ virtual bool store_long(longlong from);
+ virtual bool store_longlong(longlong from, bool unsigned_flag);
+ virtual bool store(const char *from, uint length);
+ virtual bool store(TIME *time);
+ virtual bool store_date(TIME *time);
+ virtual bool store_time(TIME *time);
+ virtual bool store(float nr, uint32 decimals, String *buffer);
+ virtual bool store(double from, uint32 decimals, String *buffer);
+ virtual bool store(Field *field);
+};
+
+
+class Protocol_prep :public Protocol
+{
+private:
+ uint field_count, bit_fields;
+public:
+ Protocol_prep() {}
+ Protocol_prep(THD *thd) :Protocol(thd) {}
+ virtual bool prepare_for_send(List<Item> *item_list);
+ virtual void prepare_for_resend();
+ virtual bool store_null();
+ virtual bool store_tiny(longlong from);
+ virtual bool store_short(longlong from);
+ virtual bool store_long(longlong from);
+ virtual bool store_longlong(longlong from, bool unsigned_flag);
+ virtual bool store(const char *from,uint length);
+ virtual bool store(TIME *time);
+ virtual bool store_date(TIME *time);
+ virtual bool store_time(TIME *time);
+ virtual bool store(float nr, uint32 decimals, String *buffer);
+ virtual bool store(double from, uint32 decimals, String *buffer);
+ virtual bool store(Field *field);
+};
+
+
+void send_warning(THD *thd, uint sql_errno, const char *err=0);
+void net_printf(THD *thd,uint sql_errno, ...);
+void send_ok(THD *thd, ha_rows affected_rows=0L, ulonglong id=0L,
+ const char *info=0);
+void send_eof(THD *thd, bool no_flush=0);
+void net_send_error(NET *net, uint sql_errno, const char *err);
+char *net_store_length(char *packet,ulonglong length);
+char *net_store_length(char *packet,uint length);
+char *net_store_data(char *to,const char *from, uint length);
+char *net_store_data(char *to,int32 from);
+char *net_store_data(char *to,longlong from);
diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc
index 2af2d5ab737..4942dd9cfd8 100644
--- a/sql/repl_failsafe.cc
+++ b/sql/repl_failsafe.cc
@@ -418,6 +418,7 @@ static Slave_log_event* find_slave_event(IO_CACHE* log,
int show_new_master(THD* thd)
{
+ Protocol *protocol= thd->protocol;
DBUG_ENTER("show_new_master");
List<Item> field_list;
char errmsg[SLAVE_ERRMSG_SIZE];
@@ -433,15 +434,15 @@ int show_new_master(THD* thd)
}
else
{
- String* packet = &thd->packet;
field_list.push_back(new Item_empty_string("Log_name", 20));
- field_list.push_back(new Item_empty_string("Log_pos", 20));
- if (send_fields(thd, field_list, 1))
+ field_list.push_back(new Item_return_int("Log_pos", 10,
+ MYSQL_TYPE_LONGLONG));
+ if (protocol->send_fields(&field_list, 1))
DBUG_RETURN(-1);
- packet->length(0);
- net_store_data(packet, lex_mi->log_file_name);
- net_store_data(packet, (longlong)lex_mi->pos);
- if (my_net_write(&thd->net, packet->ptr(), packet->length()))
+ protocol->prepare_for_resend();
+ protocol->store(lex_mi->log_file_name);
+ protocol->store((ulonglong) lex_mi->pos);
+ if (protocol->write())
DBUG_RETURN(-1);
send_eof(thd);
DBUG_RETURN(0);
@@ -582,21 +583,24 @@ int show_slave_hosts(THD* thd)
{
List<Item> field_list;
NET* net = &thd->net;
- String* packet = &thd->packet;
+ Protocol *protocol= thd->protocol;
DBUG_ENTER("show_slave_hosts");
- field_list.push_back(new Item_empty_string("Server_id", 20));
+ field_list.push_back(new Item_return_int("Server_id", 10,
+ MYSQL_TYPE_LONG));
field_list.push_back(new Item_empty_string("Host", 20));
if (opt_show_slave_auth_info)
{
field_list.push_back(new Item_empty_string("User",20));
field_list.push_back(new Item_empty_string("Password",20));
}
- field_list.push_back(new Item_empty_string("Port",20));
- field_list.push_back(new Item_empty_string("Rpl_recovery_rank", 20));
- field_list.push_back(new Item_empty_string("Master_id", 20));
+ field_list.push_back(new Item_return_int("Port", 7, MYSQL_TYPE_LONG));
+ field_list.push_back(new Item_return_int("Rpl_recovery_rank", 7,
+ MYSQL_TYPE_LONG));
+ field_list.push_back(new Item_return_int("Master_id", 10,
+ MYSQL_TYPE_LONG));
- if (send_fields(thd, field_list, 1))
+ if (protocol->send_fields(&field_list, 1))
DBUG_RETURN(-1);
pthread_mutex_lock(&LOCK_slave_list);
@@ -604,18 +608,18 @@ int show_slave_hosts(THD* thd)
for (uint i = 0; i < slave_list.records; ++i)
{
SLAVE_INFO* si = (SLAVE_INFO*) hash_element(&slave_list, i);
- packet->length(0);
- net_store_data(packet, si->server_id);
- net_store_data(packet, si->host);
+ protocol->prepare_for_resend();
+ protocol->store((uint32) si->server_id);
+ protocol->store(si->host);
if (opt_show_slave_auth_info)
{
- net_store_data(packet, si->user);
- net_store_data(packet, si->password);
+ protocol->store(si->user);
+ protocol->store(si->password);
}
- net_store_data(packet, (uint32) si->port);
- net_store_data(packet, si->rpl_recovery_rank);
- net_store_data(packet, si->master_id);
- if (my_net_write(net, (char*)packet->ptr(), packet->length()))
+ protocol->store((uint32) si->port);
+ protocol->store((uint32) si->rpl_recovery_rank);
+ protocol->store((uint32) si->master_id);
+ if (protocol->write())
{
pthread_mutex_unlock(&LOCK_slave_list);
DBUG_RETURN(-1);
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 81b4e59a450..dd30d2e377d 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -1012,8 +1012,12 @@ bool sys_var_thd_conv_charset::update(THD *thd, set_var *var)
if (var->type == OPT_GLOBAL)
global_system_variables.convert_set= var->save_result.convert;
else
+ {
thd->lex.convert_set= thd->variables.convert_set=
var->save_result.convert;
+ thd->protocol_simple.init(thd);
+ thd->protocol_prep.init(thd);
+ }
return 0;
}
diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt
index 6b19034ae59..c996066d0eb 100644
--- a/sql/share/german/errmsg.txt
+++ b/sql/share/german/errmsg.txt
@@ -2,7 +2,13 @@
This file is public domain and comes with NO WARRANTY of any kind
Dirk Munzinger (dmun@4t2.com)
- Version: 07.06.2001 */
+ Version: 07.06.2001
+
+ Georg Richter (georg@php.net)
+ fixed typos and translation
+ translated new error messages
+ 2002-12-11
+ */
"hashchk",
"isamchk",
@@ -13,41 +19,41 @@
"Kann Datenbank '%-.64s' nicht erzeugen. (Fehler: %d)",
"Kann Datenbank '%-.64s' nicht erzeugen. Datenbank '%-.64s' existiert bereits.",
"Kann Datenbank '%-.64s' nicht löschen. Keine Datenbank '%-.64s' vorhanden.",
-"Fehler beim Löschen der Datenbank. ('%-.64s' kann nicht gelöscht werden, Fehler %d)",
-"Fehler beim Löschen der Datenbank. (Verzeichnis '%-.64s' kann nicht gelöscht werden, Fehler %d)",
+"Fehler beim Löschen der Datenbank. ('%-.64s' kann nicht gelöscht werden, Fehlernuumer: %d)",
+"Fehler beim Löschen der Datenbank. (Verzeichnis '%-.64s' kann nicht gelöscht werden, Fehlernummer: %d)",
"Fehler beim Löschen von '%-.64s'. (Fehler: %d)",
"Datensatz in der Systemtabelle nicht lesbar.",
-"Kann Status von '%-.64s' nicht erhalten. (Fehler: %d)",
-"Kann Arbeitsverzeichnis nicht erhalten. (Fehler: %d)",
-"File nicht sperrbar. (Fehler: %d)",
+"Kann Status von '%-.64s' nicht ermitteln. (Fehler: %d)",
+"Kann Arbeitsverzeichnis nicht ermitteln. (Fehler: %d)",
+"Datei nicht sperrbar. (Fehler: %d)",
"Kann Datei '%-.64s' nicht öffnen. (Fehler: %d)",
"Kann Datei '%-.64s' nicht finden. (Fehler: %d)",
"Verzeichnis von '%-.64s' nicht lesbar. (Fehler: %d)",
-"Verzeichnis kann nicht nach '%-.64s' gewechselt werden. (Fehler: %d)",
+"Kann nicht in das Verzeichnis '%-.64s' wechseln. (Fehler: %d)",
"Datensatz hat sich seit dem letzten Zugriff auf Tabelle '%-.64s' geändert.",
"Festplatte voll (%-.64s). Warte bis jemand Platz schafft ...",
"Kann nicht speichern, doppelter Schlüssel in Tabelle '%-.64s'.",
"Fehler beim Schließen von '%-.64s'. (Fehler: %d)",
"Fehler beim Lesen der Datei '%-.64s'. (Fehler: %d)",
-"Fehler beim Umbennenen von '%-.64s' nach '%-.64s'. (Fehler: %d)",
+"Fehler beim Umbenennen von '%-.64s' nach '%-.64s'. (Fehler: %d)",
"Fehler beim Speichern der Datei '%-.64s'. (Fehler: %d)",
"'%-.64s' ist für Veränderungen gesperrt.",
"Sortieren abgebrochen.",
"View '%-.64s' existiert für '%-.64s' nicht.",
-"Fehler %d. (table handler)",
-"Diese Option gibt es nicht. (table handler)",
+"Fehler %d. (Tabellenhandler)",
+"Diese Option gibt es nicht. (Tabellenhandler)",
"Kann Datensatz nicht finden.",
"Falsche Information in Datei: '%-.64s'",
"Falsche Schlüssel-Datei für Tabelle '%-.64s'. Versuche zu reparieren!",
"Alte Schlüssel-Datei für Tabelle '%-.64s'. Repariere!
"'%-.64s' ist nur lesbar.",
-"Kein Speicher (benötigt %d bytes). Server neu starten.",
-"Kein Speicher zum Sortieren. Server Sortier-Buffer erhöhen.",
-"Unerwartetes EOF beim Lesen der Datei '%-.64s'. (Fehler: %d)",
+"Kein Speicher vorhanden (benötigt %d bytes). Server neu starten.",
+"Kein Speicher zum Sortieren. sort_buffer_size sollte erhöht werden.",
+"Unerwartetes Ende beim Lesen der Datei '%-.64s'. (Fehler: %d)",
"Zu viele Verbindungen.",
"Zuwenig Speicher.",
"Kann Hostname für diese Adresse nicht erhalten.",
-"Schlechter handshake.",
+"Schlechter Handshake.",
"Keine Zugriffsberechtigung für Benutzer: '%-.32s@%-.64s' für Datenbank '%-.64s'.",
"Keine Zugriffsberechtigung für Benutzer: '%-.32s@%-.64s'. (Verwendetes Passwort: %-.64s)",
"Keine Datenbank ausgewählt.",
@@ -61,16 +67,16 @@
"Unbekanntes Tabellenfeld '%-.64s' in %-.64s.",
"'%-.64s' ist nicht in GROUP BY.",
"Gruppierung nicht möglich bei '%-.64s'.",
-"Im Statement wurden sowohl sum-Funktionen als auch Spalten verwendet. Nicht möglich.",
+"Die Verwendung von sum-Funktionen und Spalten ist nicht möglich.",
"Spaltenzähler entspricht nicht dem Wertzähler.",
-"Name des Identifizierers '%-.64s' ist zu lang.",
+"Name des Bezeichners '%-.64s' ist zu lang.",
"Doppelter Spaltenname vorhanden: '%-.64s'",
"Doppelter Name für Schlüssel (Key) vorhanden: '%-.64s'",
"Doppelter Eintrag '%-.64s' für Schlüssel %d.",
"Falsche Spalten-Spezifizierung für Spalte '%-.64s'.",
"%-.64s bei '%-.64s' in Zeile %d.",
"Leere Abfrage.",
-"Keine eindeutige(n) Tabelle/Alias: '%-.64s'",
+"Keine eindeutiger Tabellenname/Alias: '%-.64s'",
"Fehlerhafter Vorgabewert (Default-Wert): '%-.64s'",
"Mehrfacher Primärschlüssel (Primary Key) definiert.",
"Zuviele Schlüssel definiert. Maximal %d Schlüssel erlaubt.",
@@ -78,37 +84,37 @@
"Schlüssel ist zu lang. Die maximale Schlüssellänge beträgt %d.",
"In der Tabelle gibt es keine Schlüsselspalte '%-.64s'.",
"BLOB-Feld '%-.64s' kann nicht als Schlüssel verwendet werden.",
-"Feldlänge für Feld '%-.64s' zu groß (max = %d). BLOB-Feld verwenden!",
+"Feldlänge für Feld '%-.64s' zu groß (max. = %d). BLOB-Feld verwenden!",
"Nur ein Auto-Feld möglich, welches als Schlüssel definiert werden muß.",
-"%-.64s: Warten auf Verbindungen.\n",
+"%-.64s: Warte auf Verbindungen.\n",
"%-.64s: Normal beendet.\n",
"%-.64s: Signal %d erhalten. Abbruch!\n",
"%-.64s: Shutdown ausgeführt.\n",
-"%-.64s: Beendigung des Thread %ld veranlaßt. Benutzer: '%-.64s'\n",
+"%-.64s: Beendigung des Thread %ld veranlasst. Benutzer: '%-.64s'\n",
"Kann IP-Socket nicht erstellen.",
-"Tabelle '%-.64s' hat keinen solchen Index wie in CREATE INDEX verwendet. Index neu anlegen.",
-"Feld-Separator Argument ist nicht in der Form wie erwartet. Bitte im Manual nachlesen.",
+"Tabelle '%-.64s' besitzt keinen wie in CREATE INDEX verwendeten Index. Index neu anlegen.",
+"Feldbegrenzer Argument ist nicht in der Form wie erwartet. Bitte im Manual nachlesen.",
"Eine feste Reihenlänge kann für BLOBs nicht verwendet werden. Verwende 'fields terminated by' stattdessen.",
-"Feld '%-.64s' muß im Datenbank-Directory vorhanden und lesbar für alle sein.",
-"File '%-.64s' bereits vorhanden.",
+"Feld '%-.64s' muß im Datenbank-Verzeichnis vorhanden und lesbar für alle sein.",
+"Datei '%-.64s' bereits vorhanden.",
"Datensätze: %ld Gelöscht: %ld Ausgelassen: %ld Warnungen: %ld",
"Datensätze: %ld Duplikate: %ld",
-"Falscher Subteilschlüssel. Der verwendete Schlüsselteil ist entweder kein String oder die verwendete Länge ist länger als der Teilschlüssel.",
+"Falscher Unterteilschlüssel. Der verwendete Schlüsselteil ist entweder kein String, die verwendete Länge ist länger als der Teilschlüssel oder der Tabellenhandler unterstützt keine Unterteilschlüssel.",
"Mit ALTER TABLE können nicht alle Felder auf einmal gelöscht werden. Verwende DROP TABLE stattdessen.",
"Kann '%-.64s' nicht löschen (DROP). Existiert das Feld/der Schlüssel?",
"Datensätze: %ld Duplikate: %ld Warnungen: %ld",
-"You can't specify target table '%-.64s' for update in FROM clause",
+"Die Verwendung der Zieltabelle '%-.64s' ist bei Update in FROM Teil nicht zulässig.",
"Unbekannte Thread-ID: %lu",
-"Nicht Besitzer des Threads %lu.",
+"Threads %lu. ist einem anderen Besitzer zugeordnet.",
"Keine Tabellen in Verwendung.",
-"Zuviele Strings für Spalte %-.64s und SET.",
-"Kann keinen eindeutigen Log-Filenamen erstellen %-.64s.(1-999)\n",
-"Tabelle '%-.64s' mit Lese-Sperre versehen und kann nicht upgedated werden.",
+"Zuviele Angaben für Spalte %-.64s und SET.",
+"Kann keinen eindeutigen Dateinamen für die Logdatei ermitteln %-.64s.(1-999)\n",
+"Tabelle '%-.64s' mit Lese-Sperre versehen und kann nicht aktualisiert werden.",
"Tabelle '%-.64s' wurde nicht mittels LOCK TABLES gesperrt.",
"BLOB-Feld '%-.64s' kann keinen Vorgabewert (Default-Value) besitzen.",
"Unerlaubter Datenbankname '%-.64s'.",
"Unerlaubter Tabellenname '%-.64s'.",
-"Die Ausführung des SELECT würde zu viele Datensätze untersuchen und wahrscheinlich sehr lange daueren. Bitte WHERE überprüfen und SET OPTION SQL_BIG_SELECTS=1 verwenden, sofern SELECT ok ist.",
+"Die Ausführung des SELECT würde zu viele Datensätze untersuchen und wahrscheinlich sehr lange daueren. Bitte WHERE überprüfen oder gegebenenfalls SET OPTION SQL_BIG_SELECTS=1 verwenden.",
"Unbekannter Fehler.",
"Unbekannte Procedure %-.64s.",
"Falsche Parameterzahl für Procedure %-.64s.",
@@ -135,51 +141,51 @@
"Funktion '%-.64s' ist nicht definiert.",
"Host blockiert wegen zu vieler Verbindungsfehler. Aufheben der Blockierung mit 'mysqladmin flush-hosts'.",
"Host hat keine Berechtigung, eine Verbindung zu diesem MySQL Server herzustellen.",
-"Sie benutzen MySQL als anonymer User; diese User dürfen keine Passwörter ändern.",
-"Sie müssen autorisiert sein zum UPDATE von Tabellen in der mysql Datenbank, um für andere Benutzer Passwörter ändern zu können.",
-"Kann keinen passenden Datensatz in der User-Tabelle finden.",
+"Sie benutzen MySQL als anonymer Benutzer und dürfen daher keine Passwörter ändern.",
+"Sie müssen autorisiert sein zum Aktualisieren von Tabellen in der mysql Datenbank, um für andere Benutzer Passwörter ändern zu können.",
+"Kann keinen passenden Datensatz in der Benutzer-Tabelle finden.",
"Datensätze gefunden: %ld Geändert: %ld Warnungen: %ld",
-"Kann keinen neuen Thread erzeugen (errno %d). Sollte nicht die Speichergrenze erreicht sein, bitte im Manual nach vorhanden OS-Abhängigen Fehlern nachschauen.",
+"Kann keinen neuen Thread erzeugen (Fehler: %d). Sollte die Speichergrenze nicht erreicht sein, bitte in der Dokumentation nach evtl. Betriebssystem abhängigen Fehlern nachlesen.",
"Spaltenzahl stimmt nicht mit der Anzahl der Werte überein in Reihe%ld",
"Kann Tabelle'%-.64s' nicht wieder öffnen",
"Unerlaubte Verwendung eines NULL-Wertes",
"Fehler '%-.64s' von regexp",
"Das Vermischen von GROUP Spalten (MIN(),MAX(),COUNT()...) mit Nicht-GROUP Spalten ist nicht erlaubt, sofern keine GROUP BY Klausel vorhanden ist.",
"Keine solche Berechtigung für User '%-.32s' auf Host '%-.64s'",
-"%-.16s Kommando abgelehnt für User: '%-.32s@%-.64s' für Tabelle '%-.64s'",
-"%-.16s Kommando abgelehnt für User: '%-.32s@%-.64s' in Spalte '%-.64s' in Tabelle '%-.64s'",
-"Unzulässiges GRANT/REVOKE Kommando. Weiteres zum Thema Berechtigungen im Manual.",
+"%-.16s Befehl nicht erlaubt für User: '%-.32s@%-.64s' für Tabelle '%-.64s'",
+"%-.16s Befehl nicht erlaubt für User: '%-.32s@%-.64s' in Spalte '%-.64s' in Tabelle '%-.64s'",
+"Unzulässiger GRANT/REVOKE Befehl. Weiteres zum Thema Berechtigungen im Manual.",
"Das Host oder User Argument für GRANT ist zu lang",
"Tabelle '%-.64s.%-.64s' existiert nicht",
"Keine solche Berechtigung für User '%-.32s' auf Host '%-.64s' an Tabelle '%-.64s'",
-"Das used Kommando ist mit dieser MySQL Version nicht erlaubt",
+"Der used Befehl ist mit dieser MySQL Version nicht erlaubt",
"Fehler in der Syntax",
-"Verzögerter Einfüge-Thread konnte den angeforderten Lock für Tabelle %-.64s nicht bekommen",
+"Verzögerter Einfüge-Thread konnte den angeforderten Lock für Tabelle %-.64s nicht erhalten",
"Zu viele Delayed Threads in Verwendung",
"Abbruch der Verbindung %ld zur Datenbank: '%-.64s' User: '%-.64s' (%-.64s)",
"Empfangenes Paket ist größer als 'max_allowed_packet'",
"Lese-Fehler bei einer Kommunikations-Pipe",
"Fehler von fcntl()",
"Empfangenes Paket ist nicht in Reihenfolge",
-"Communikation-Packet läßt sich nicht entpacken",
-"Fehler beim Lesen eines Communication-Packets"
-"Timeout beim Lesen eines Communication-Packets",
-"Fehler beim Schreiben eines Communication-Packets",
-"Timeout beim Schreiben eines Communication-Packets",
-"Ergebnisstring ist länger als max_allowed_packet",
+"Kommunikationspaket läßt sich nicht entpacken",
+"Fehler beim Lesen eines Kommunikationspakets"
+"Zeitüberschreitung beim Lesen eines Kommunikationspakets.",
+"Fehler beim Schreiben eines Kommunikationspakets.",
+"Zeitüberschreitung beim Schreiben eines Kommunikationspakets.",
+"Ergebnis ist länger als max_allowed_packet",
"Der verwendete Tabellentyp unterstützt keine BLOB/TEXT Spalten",
"Der verwendete Tabellentyp unterstützt keine AUTO_INCREMENT Spalte",
"INSERT DELAYED kann nicht auf Tabelle '%-.64s' angewendet werden, da diese mit LOCK TABLES gesperrt ist",
"Falscher Spaltenname '%-.100s'",
"Der verwendete Tabellen-Handler kann die Spalte '%-.64s' nicht indizieren",
-"Alle Tabelle in der MERGE-Tabelle sind nicht gleich definiert",
+"Alle Tabellen in der MERGE-Tabelle sind nicht gleich definiert",
"Schreiben in Tabelle '%-.64s' nicht möglich wegen eines Unique Constraint",
"BLOB Spalte '%-.64s' wird in der Key-Definition ohne Längenangabe verwendet",
"Alle Teile eines PRIMARY KEY müssen als NOT NULL definiert sein; Wenn NULL benötigt wird sollte ein UNIQUE Key verwendet werden",
"Ergebnis besteht aus mehr als einer Reihe",
"Dieser Tabellentyp verlangt nach einem PRIMARY KEY",
"Diese MySQL-Version ist nicht mit RAID-Unterstützung kompiliert",
-"Unter Verwendung des Sicheren Updatemodes wurde versucht eine Tabelle zu updaten ohne eine KEY-Spalte in der WHERE-Klausel",
+"Unter Verwendung des sicheren Aktualisierungsmodus wurde versucht eine Tabelle zu aktualisieren ohne eine KEY-Spalte in der WHERE-Klausel",
"Schlüssel '%-.64s' existiert nicht in der Tabelle '%-.64s'",
"Kann Tabelle nicht öffnen",
"Der Tabellen-Handler für diese Tabelle unterstützt kein %s",
@@ -191,65 +197,66 @@
"Verbindungsabbruch %ld zu db: '%-.64s' user: '%-.32s' host: `%-.64s' (%-.64s)",
"Der Tabellenhandler für die Tabelle unterstützt kein Binary Tabellendump",
"Binlog wurde beendet wärend FLUSH MASTER",
-"Neubau des Index der gedumpten Tabelle '%-.64s' fehlgeschlagen",
+"Neuerstellung des Index der gedumpten Tabelle '%-.64s' fehlgeschlagen",
"Fehler vom Master: '%-.64s'",
"Netzfehler beim Lesen vom Master",
"Netzfehler beim Schreiben zum Master",
-"Kann keinen FULLTEXT-Index finden der der Spaltenliste entspricht",
+"Kann keinen FULLTEXT-Index finden, der der Spaltenliste entspricht",
"Kann das aktuelle Kommando wegen aktiver Tabellensperre oder aktiver Transaktion nicht ausführen",
-"Unbekannte System-Variabel '%-.64s'",
+"Unbekannte Systemvariable '%-.64s'",
"Tabelle '%-.64s' ist als defekt makiert und sollte repariert werden",
"Tabelle '%-.64s' ist als defekt makiert und der letzte (automatische) Reparaturversuch schlug fehl.",
"Warnung: Das Rollback konnte bei einigen Tabellen, die nicht mittels Transaktionen geändert wurden, nicht ausgeführt werden.",
-"Multi-Statement Transaktionen benötigen mehr als 'max_binlog_cache_size' Bytes An Speicher. Diese mysqld-Variabel vergrössern und nochmal versuchen.',
+"Multi-Statement Transaktionen benötigen mehr als 'max_binlog_cache_size' Bytes An Speicher. Diese mysqld-Variable vergrössern und erneut versuchen.',
"Diese Operation kann nicht bei einem aktiven Slave durchgeführt werden. Das Kommand SLAVE STOP muss zuerst ausgeführt werden.",
-"Diese Operationbenötigt einen aktiven Slave. Slave konfigurieren und mittels SLAVE START aktivieren.",
+"Diese Operation benötigt einen aktiven Slave. Slave konfigurieren und mittels SLAVE START aktivieren.",
"Der Server ist nicht als Slave konfigiriert. Im Konfigurations-File oder mittel CHANGE MASTER TO beheben.",
"Konnte Master-Info-Struktur nicht initialisieren; Berechtigungen von master.info prüfen.",
"Konnte keinen Slave-Thread starten. System-Resourcen überprüfen.",
"Benutzer %-.64s hat mehr als 'max_user_connections' aktive Verbindungen",
-"Bei der Verwendung mit SET dürfen nur Constante Ausdrücke verwendet werden",
-"Lock wait timeout exceeded",
-"The total number of locks exceeds the lock table size",
-"Update locks cannot be acquired during a READ UNCOMMITTED transaction",
-"DROP DATABASE not allowed while thread is holding global read lock",
-"CREATE DATABASE not allowed while thread is holding global read lock",
-"Wrong arguments to %s",
-"%-.32s@%-.64s is not allowed to create new users",
-"Incorrect table definition; All MERGE tables must be in the same database",
-"Deadlock found when trying to get lock; Try restarting transaction",
-"The used table type doesn't support FULLTEXT indexes",
-"Cannot add foreign key constraint",
-"Cannot add a child row: a foreign key constraint fails",
-"Cannot delete a parent row: a foreign key constraint fails",
-"Error connecting to master: %-.128s",
-"Error running query on master: %-.128s",
-"Error when executing command %s: %-.128s",
-"Wrong usage of %s and %s",
-"The used SELECT statements have a different number of columns",
-"Can't execute the query because you have a conflicting read lock",
-"Mixing of transactional and non-transactional tables is disabled",
-"Option '%s' used twice in statement",
-"User '%-.64s' has exceeded the '%s' resource (current value: %ld)",
-"Access denied. You need the %-.128s privilege for this operation",
-"Variable '%-.64s' is a LOCAL variable and can't be used with SET GLOBAL",
-"Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL",
-"Variable '%-.64s' doesn't have a default value",
-"Variable '%-.64s' can't be set to the value of '%-.64s'",
-"Wrong argument type to variable '%-.64s'",
-"Variable '%-.64s' can only be set, not read",
-"Wrong usage/placement of '%s'",
-"This version of MySQL doesn't yet support '%s'",
-"Got fatal error %d: '%-.128s' from master when reading data from binary log",
-"Wrong foreign key definition for '%-.64s': %s",
-"Key reference and table reference doesn't match",
-"Cardinality error (more/less than %d columns)",
-"Subselect return more than 1 record",
-"Unknown prepared statement handler (%ld) given to %s",
-"Help database is corrupt or does not exist",
-"Cyclic reference on subqueries",
-"Converting column '%s' from %s to %s",
-"Reference '%-.64s' not supported (%s)",
-"Every derived table must have it's own alias"
-"Select %u was reduced during optimisation",
-"Table '%-.64s' from one of SELECT's can not be used in %-.32s"
+"Bei der Verwendung mit SET dürfen nur konstante Ausdrücke verwendet werden",
+"Beim Warten auf einen LOCK wurde die zulässige Wartezeit überschritten.",
+"Die Gesamtanzahl der LOCKS überschreitet die Grösse der Locktabelle.",
+"Während einer READ UNCOMMITED Transaktion kann keine Update LOCK angefordert werden.",
+"Solange ein globaler Read LOCK gesetzt ist, ist DROP DATABASE nicht zulässig.",
+"Solange ein globaler Read LOCK gesetzt ist, ist CREATE DATABASE nicht zulässig.",
+"Falsche Argumente für %s",
+"%-.32s@%-.64s is nicht berechtigt neue Benutzer hinzuzufügen.",
+"Falsche Tabellendefinition: Sämtliche MERGE-Tabellen müssen in derselben Datenbank sein.",
+"Beim Versuch einen Lock anzufordern ist ein Deadlock aufgetreten. Es wird versucht die Transaktion erneut zu starten.",
+"Der verwendete Tabellentyp unterstützt keinen FULLTEXT-Index.",
+"Foreign_Key Beschränkung konnte nicht hinzugefügt werden."
+"Hinzufügen eines Kind-Datensatzes schlug aufgrund einer Foreign-Key Beschränkung fehl.",
+"Löschen eines Eltern-Datensatzes schlug aufgrund einer Foreign-Key Beschränkung fehl.",
+"Datensatz kann aufgrund einer Foreign-Key Beschränkung nicht gelöscht werden.",
+"Fehler bei der Verbindung zum Master: %-.128s",
+"Beim Ausführen einer Abfrage auf dem Master trat ein Fehler auf: %-.128s.",
+"Fehler beim Ausführen des Befehls %s: %-.128s.",
+"Falsche Verwendung von %s und %s.",
+"Die verwendeten SELECTs liefern eine unterschiedliche Anzahl von Spalten zurück.",
+"Augrund eines READ LOCK Konflikts kann die Abfrage nicht ausgeführt werden.",
+"Die Verwendung von transaktions- und nicht transaktionsaktionsunterstützenden Tabellen ist deaktiviert.",
+"Option '%s' wird im Befehl zweimal verwendet.",
+"Benutzer '%-.64s' hat Limit '%s' überschritten. (Momentaner Wert: %ld)",
+"Befehl nicht zulässig. Hierfür wird die Berechtigung %-.128s benötigt.",
+"Variable '%-.64s' ist eine lokale Variable und kann nicht mit SET GLOBAL verändert werden.",
+"Variable '%-.64s' ist eine globale Variable und muss mit SET GLOBAL verändert werden.",
+"Variable '%-.64s' besitzt keinen vorgegebenen Wert.",
+"Der Variablen '%-.64s' kann nicht der Wert '%-.64s' zugewiesen werden.",
+"Falscher Typ für Variable '%-.64s'",
+"Variable '%-.64s' kann nur verändert, nicht aber gelesen werden.",
+"Falsche Verwendung oder Platzierung von '%s'",
+"Diese MySQL-Version unterstützt momentan nicht '%s'.",
+"Schwerer Fehler %d: '%-.128s vom Master beim Lesen des Binary Logs.",
+"Falsche Foreign-Key Definition für '%-64s': %s",
+"Schlüssel- und Tabellenreferenz passen nicht zueinander.",
+"Kardinalitäts-Fehler (mehr/oder weniger als %d Spalten).",
+"Unterabfrage lieferte mehr als einen Datensatz zurück.",
+"Unbekannter prepared statement handler (%ld) für %s angegeben.",
+"Die Hilfedatenbank ist beschädigt oder existiert nicht.",
+"Zyklische Referenz in den Unterabfragen.",
+"Spalte '%s' wird von %s nach %s umgewandelt",
+"Referenz '%-.64s' wird nicht unterstützt (%s)",
+"Für jede abgeleitete Tabelle muss ein eigener Alias angegeben werden.",
+"Select %u wurde während der Optimierung reduziert.",
+"Tabelle '%-.64s', die in einem der SELECT-Befehle verwendet wurde kann nicht in %-.32s verwendet werden."
diff --git a/sql/slave.cc b/sql/slave.cc
index 16bc08a2b6e..24ec1fc2536 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -1513,42 +1513,38 @@ err:
*****************************************************************************/
int register_slave_on_master(MYSQL* mysql)
{
- String packet;
- char buf[4];
+ char buf[1024], *pos= buf;
+ uint report_host_len, report_user_len=0, report_password_len=0;
if (!report_host)
return 0;
-
- int4store(buf, server_id);
- packet.append(buf, 4);
-
- net_store_data(&packet, report_host);
+ report_host_len= strlen(report_host);
if (report_user)
- net_store_data(&packet, report_user);
- else
- packet.append((char)0);
-
+ report_user_len= strlen(report_user);
if (report_password)
- net_store_data(&packet, report_user);
- else
- packet.append((char)0);
-
- int2store(buf, (uint16)report_port);
- packet.append(buf, 2);
- int4store(buf, rpl_recovery_rank);
- packet.append(buf, 4);
- int4store(buf, 0); /* tell the master will fill in master_id */
- packet.append(buf, 4);
-
- if (mc_simple_command(mysql, COM_REGISTER_SLAVE, (char*)packet.ptr(),
- packet.length(), 0))
+ report_password_len= strlen(report_password);
+ /* 30 is a good safety margin */
+ if (report_host_len + report_user_len + report_password_len + 30 >
+ sizeof(buf))
+ return 0; // safety
+
+ int4store(pos, server_id); pos+= 4;
+ pos= net_store_data(pos, report_host, report_host_len);
+ pos= net_store_data(pos, report_user, report_user_len);
+ pos= net_store_data(pos, report_password, report_password_len);
+ int2store(pos, (uint16) report_port); pos+= 2;
+ int4store(pos, rpl_recovery_rank); pos+= 4;
+ /* The master will fill in master_id */
+ int4store(pos, 0); pos+= 4;
+
+ if (mc_simple_command(mysql, COM_REGISTER_SLAVE, (char*) buf,
+ (uint) (pos- buf), 0))
{
sql_print_error("Error on COM_REGISTER_SLAVE: %d '%s'",
mc_mysql_errno(mysql),
mc_mysql_error(mysql));
return 1;
}
-
return 0;
}
@@ -1560,60 +1556,69 @@ int register_slave_on_master(MYSQL* mysql)
int show_master_info(THD* thd, MASTER_INFO* mi)
{
// TODO: fix this for multi-master
- DBUG_ENTER("show_master_info");
List<Item> field_list;
+ Protocol *protocol= thd->protocol;
+ DBUG_ENTER("show_master_info");
+
field_list.push_back(new Item_empty_string("Master_Host",
sizeof(mi->host)));
field_list.push_back(new Item_empty_string("Master_User",
sizeof(mi->user)));
- field_list.push_back(new Item_empty_string("Master_Port", 6));
- field_list.push_back(new Item_empty_string("Connect_retry", 6));
+ field_list.push_back(new Item_return_int("Master_Port", 7,
+ MYSQL_TYPE_LONG));
+ field_list.push_back(new Item_return_int("Connect_retry", 10,
+ MYSQL_TYPE_LONG));
field_list.push_back(new Item_empty_string("Master_Log_File",
- FN_REFLEN));
- field_list.push_back(new Item_empty_string("Read_Master_Log_Pos", 12));
+ FN_REFLEN));
+ field_list.push_back(new Item_return_int("Read_Master_Log_Pos", 10,
+ MYSQL_TYPE_LONGLONG));
field_list.push_back(new Item_empty_string("Relay_Log_File",
- FN_REFLEN));
- field_list.push_back(new Item_empty_string("Relay_Log_Pos", 12));
+ FN_REFLEN));
+ field_list.push_back(new Item_return_int("Relay_Log_Pos", 10,
+ MYSQL_TYPE_LONGLONG));
field_list.push_back(new Item_empty_string("Relay_Master_Log_File",
- FN_REFLEN));
+ FN_REFLEN));
field_list.push_back(new Item_empty_string("Slave_IO_Running", 3));
field_list.push_back(new Item_empty_string("Slave_SQL_Running", 3));
field_list.push_back(new Item_empty_string("Replicate_do_db", 20));
field_list.push_back(new Item_empty_string("Replicate_ignore_db", 20));
- field_list.push_back(new Item_empty_string("Last_errno", 4));
+ field_list.push_back(new Item_return_int("Last_errno", 4, MYSQL_TYPE_LONG));
field_list.push_back(new Item_empty_string("Last_error", 20));
- field_list.push_back(new Item_empty_string("Skip_counter", 12));
- field_list.push_back(new Item_empty_string("Exec_master_log_pos", 12));
- field_list.push_back(new Item_empty_string("Relay_log_space", 12));
- if (send_fields(thd, field_list, 1))
+ field_list.push_back(new Item_return_int("Skip_counter", 10,
+ MYSQL_TYPE_LONG));
+ field_list.push_back(new Item_return_int("Exec_master_log_pos", 10,
+ MYSQL_TYPE_LONGLONG));
+ field_list.push_back(new Item_return_int("Relay_log_space", 10,
+ MYSQL_TYPE_LONGLONG));
+ if (protocol->send_fields(&field_list, 1))
DBUG_RETURN(-1);
if (mi->host[0])
{
String *packet= &thd->packet;
- packet->length(0);
+ protocol->prepare_for_resend();
pthread_mutex_lock(&mi->data_lock);
pthread_mutex_lock(&mi->rli.data_lock);
- net_store_data(packet, mi->host);
- net_store_data(packet, mi->user);
- net_store_data(packet, (uint32) mi->port);
- net_store_data(packet, (uint32) mi->connect_retry);
- net_store_data(packet, mi->master_log_name);
- net_store_data(packet, (longlong) mi->master_log_pos);
- net_store_data(packet, mi->rli.relay_log_name +
+ protocol->store(mi->host);
+ protocol->store(mi->user);
+ protocol->store((uint32) mi->port);
+ protocol->store((uint32) mi->connect_retry);
+ protocol->store(mi->master_log_name);
+ protocol->store((ulonglong) mi->master_log_pos);
+ protocol->store(mi->rli.relay_log_name +
dirname_length(mi->rli.relay_log_name));
- net_store_data(packet, (longlong) mi->rli.relay_log_pos);
- net_store_data(packet, mi->rli.master_log_name);
- net_store_data(packet, mi->slave_running ? "Yes":"No");
- net_store_data(packet, mi->rli.slave_running ? "Yes":"No");
- net_store_data(packet, &replicate_do_db);
- net_store_data(packet, &replicate_ignore_db);
- net_store_data(packet, (uint32)mi->rli.last_slave_errno);
- net_store_data(packet, mi->rli.last_slave_error);
- net_store_data(packet, mi->rli.slave_skip_counter);
- net_store_data(packet, (longlong) mi->rli.master_log_pos);
- net_store_data(packet, (longlong) mi->rli.log_space_total);
+ protocol->store((ulonglong) mi->rli.relay_log_pos);
+ protocol->store(mi->rli.master_log_name);
+ protocol->store(mi->slave_running ? "Yes":"No");
+ protocol->store(mi->rli.slave_running ? "Yes":"No");
+ protocol->store(&replicate_do_db);
+ protocol->store(&replicate_ignore_db);
+ protocol->store((uint32) mi->rli.last_slave_errno);
+ protocol->store(mi->rli.last_slave_error);
+ protocol->store((uint32) mi->rli.slave_skip_counter);
+ protocol->store((ulonglong) mi->rli.master_log_pos);
+ protocol->store((ulonglong) mi->rli.log_space_total);
pthread_mutex_unlock(&mi->rli.data_lock);
pthread_mutex_unlock(&mi->data_lock);
@@ -1640,8 +1645,7 @@ bool flush_master_info(MASTER_INFO* mi)
my_b_printf(file, "%s\n%s\n%s\n%s\n%s\n%d\n%d\n",
mi->master_log_name, llstr(mi->master_log_pos, lbuf),
mi->host, mi->user,
- mi->password, mi->port, mi->connect_retry
- );
+ mi->password, mi->port, mi->connect_retry);
flush_io_cache(file);
DBUG_RETURN(0);
}
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 6438e39cb6e..e2ddd2cba81 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -2780,6 +2780,7 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
int error = 0;
ACL_USER *acl_user; ACL_DB *acl_db;
char buff[1024];
+ Protocol *protocol= thd->protocol;
DBUG_ENTER("mysql_show_grants");
LINT_INIT(acl_user);
@@ -2826,7 +2827,7 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
strxmov(buff,"Grants for ",lex_user->user.str,"@",
lex_user->host.str,NullS);
field_list.push_back(field);
- if (send_fields(thd,field_list,1))
+ if (protocol->send_fields(&field_list,1))
DBUG_RETURN(-1);
rw_wrlock(&LOCK_grant);
@@ -2935,12 +2936,12 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
global.append(buff,p-buff);
}
}
- thd->packet.length(0);
- net_store_data(&thd->packet,global.ptr(),global.length());
- if (SEND_ROW(thd, field_list.elements, (char*) thd->packet.ptr(),
- thd->packet.length()))
+ protocol->prepare_for_resend();
+ protocol->store(global.ptr(),global.length());
+ if (protocol->write())
{
- error=-1; goto end;
+ error=-1;
+ goto end;
}
}
@@ -2991,10 +2992,9 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
db.append ('\'');
if (want_access & GRANT_ACL)
db.append(" WITH GRANT OPTION",18);
- thd->packet.length(0);
- net_store_data(&thd->packet,db.ptr(),db.length());
- if (SEND_ROW(thd, field_list.elements, (char*) thd->packet.ptr(),
- thd->packet.length()))
+ protocol->prepare_for_resend();
+ protocol->store(db.ptr(),db.length());
+ if (protocol->write())
{
error=-1;
goto end;
@@ -3079,10 +3079,9 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
global.append('\'');
if (want_access & GRANT_ACL)
global.append(" WITH GRANT OPTION",18);
- thd->packet.length(0);
- net_store_data(&thd->packet,global.ptr(),global.length());
- if (SEND_ROW(thd, field_list.elements, (char*) thd->packet.ptr(),
- thd->packet.length()))
+ protocol->prepare_for_resend();
+ protocol->store(global.ptr(),global.length());
+ if (protocol->write())
{
error= -1;
break;
diff --git a/sql/sql_analyse.cc b/sql/sql_analyse.cc
index ecd9f635060..acd67ad66d7 100644
--- a/sql/sql_analyse.cc
+++ b/sql/sql_analyse.cc
@@ -310,30 +310,7 @@ void field_str::add()
was_maybe_zerofill = num_info.maybe_zerofill;
}
- if (room_in_tree)
- {
- if (res != &s)
- s.copy(*res);
- if (!tree_search(&tree, (void*) &s, tree.custom_arg)) // If not in tree
- {
- s.copy(); // slow, when SAFE_MALLOC is in use
- if (!tree_insert(&tree, (void*) &s, 0, tree.custom_arg))
- {
- room_in_tree = 0; // Remove tree, out of RAM ?
- delete_tree(&tree);
- }
- else
- {
- bzero((char*) &s, sizeof(s)); // Let tree handle free of this
- if ((treemem += length) > pc->max_treemem)
- {
- room_in_tree = 0; // Remove tree, too big tree
- delete_tree(&tree);
- }
- }
- }
- }
-
+ /* Update min and max arguments */
if (!found)
{
found = 1;
@@ -364,6 +341,31 @@ void field_str::add()
max_arg.copy(*res);
}
}
+
+ if (room_in_tree)
+ {
+ if (res != &s)
+ s.copy(*res);
+ if (!tree_search(&tree, (void*) &s, tree.custom_arg)) // If not in tree
+ {
+ s.copy(); // slow, when SAFE_MALLOC is in use
+ if (!tree_insert(&tree, (void*) &s, 0, tree.custom_arg))
+ {
+ room_in_tree = 0; // Remove tree, out of RAM ?
+ delete_tree(&tree);
+ }
+ else
+ {
+ bzero((char*) &s, sizeof(s)); // Let tree handle free of this
+ if ((treemem += length) > pc->max_treemem)
+ {
+ room_in_tree = 0; // Remove tree, too big tree
+ delete_tree(&tree);
+ }
+ }
+ }
+ }
+
if ((num_info.zerofill && (max_length != min_length)) ||
(was_zero_fill && (max_length != min_length)))
can_be_still_num = 0; // zerofilled numbers must be of same length
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 8d77a6355bb..f7a0c6960d4 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -195,253 +195,6 @@ OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *wild)
DBUG_RETURN(open_list);
}
-/*
- Send name and type of result to client converted to a given char set
-
- SYNOPSIS
- send_convert_fields()
- THD Thread data object
- list List of items to send to client
- convert object used to convertation to another character set
- flag Bit mask with the following functions:
- 2 send default values
- 4 Don't convert field names
-
- DESCRIPTION
- Sum fields has table name empty and field_name.
-
- RETURN VALUES
- 0 ok
- 1 Error (Note that in this case the error is not sent to the client)
-*/
-
-#ifndef EMBEDDED_LIBRARY
-
-bool
-send_convert_fields(THD *thd,List<Item> &list,CONVERT *convert,uint flag)
-{
- List_iterator_fast<Item> it(list);
- Item *item;
- char buff[80];
- String tmp((char*) buff,sizeof(buff),default_charset_info);
- String *res,*packet= &thd->packet;
- DBUG_ENTER("send_convert_fields");
-
- while ((item=it++))
- {
- char *pos;
- Send_field field;
- item->make_field(&field);
- packet->length(0);
-
- if (thd->client_capabilities & CLIENT_PROTOCOL_41)
- {
- if (convert->store(packet,field.db_name,
- (uint) strlen(field.db_name)) ||
- convert->store(packet,field.table_name,
- (uint) strlen(field.table_name)) ||
- convert->store(packet,field.org_table_name,
- (uint) strlen(field.org_table_name)) ||
- convert->store(packet,field.col_name,
- (uint) strlen(field.col_name)) ||
- convert->store(packet,field.org_col_name,
- (uint) strlen(field.org_col_name)) ||
- packet->realloc(packet->length()+10))
- goto err;
- }
- else
- {
- if (convert->store(packet,field.table_name,
- (uint) strlen(field.table_name)) ||
- convert->store(packet,field.col_name,
- (uint) strlen(field.col_name)) ||
- packet->realloc(packet->length()+10))
- goto err;
- }
- pos= (char*) packet->ptr()+packet->length();
-
- if (!(thd->client_capabilities & CLIENT_LONG_FLAG))
- {
- packet->length(packet->length()+9);
- pos[0]=3; int3store(pos+1,field.length);
- pos[4]=1; pos[5]=field.type;
- pos[6]=2; pos[7]=(char) field.flags; pos[8]= (char) field.decimals;
- }
- else
- {
- packet->length(packet->length()+10);
- pos[0]=3; int3store(pos+1,field.length);
- pos[4]=1; pos[5]=field.type;
- pos[6]=3; int2store(pos+7,field.flags); pos[9]= (char) field.decimals;
- }
- if (flag & 2)
- { // Send default value
- if (!(res=item->val_str(&tmp)))
- {
- if (net_store_null(packet))
- goto err;
- }
- else if (convert->store(packet,res->ptr(),res->length()))
- goto err;
- }
- if (my_net_write(&thd->net, (char*) packet->ptr(),packet->length()))
- break; /* purecov: inspected */
- }
- DBUG_RETURN(0);
-
-err:
- DBUG_RETURN(1);
-}
-
-
-/*
- Send name and type of result to client.
-
- SYNOPSIS
- send_non_convert_fields()
- THD Thread data object
- list List of items to send to client
- flag Bit mask with the following functions:
- 2 send default values
- 4 Don't convert field names
-
- DESCRIPTION
- Sum fields has table name empty and field_name.
-
- RETURN VALUES
- 0 ok
- 1 Error
-*/
-
-bool
-send_non_convert_fields(THD *thd,List<Item> &list,uint flag)
-{
- List_iterator_fast<Item> it(list);
- Item *item;
- char buff[80];
-
- String tmp((char*) buff,sizeof(buff),default_charset_info);
- String *res,*packet= &thd->packet;
-
- while ((item=it++))
- {
- char *pos;
- Send_field field;
- item->make_field(&field);
- packet->length(0);
-
- if (thd->client_capabilities & CLIENT_PROTOCOL_41)
- {
- if (net_store_data(packet,field.db_name) ||
- net_store_data(packet,field.table_name) ||
- net_store_data(packet,field.org_table_name) ||
- net_store_data(packet,field.col_name) ||
- net_store_data(packet,field.org_col_name) ||
- packet->realloc(packet->length()+10))
- return 1;
- }
- else
- {
- if (net_store_data(packet,field.table_name) ||
- net_store_data(packet,field.col_name) ||
- packet->realloc(packet->length()+10))
- return 1;
- }
-
- pos= (char*) packet->ptr()+packet->length();
-
- if (!(thd->client_capabilities & CLIENT_LONG_FLAG))
- {
- packet->length(packet->length()+9);
- pos[0]=3; int3store(pos+1,field.length);
- pos[4]=1; pos[5]=field.type;
- pos[6]=2; pos[7]=(char) field.flags; pos[8]= (char) field.decimals;
- }
- else
- {
- packet->length(packet->length()+10);
- pos[0]=3; int3store(pos+1,field.length);
- pos[4]=1; pos[5]=field.type;
- pos[6]=3; int2store(pos+7,field.flags); pos[9]= (char) field.decimals;
- }
- if (flag & 2)
- { // Send default value
- if (!(res=item->val_str(&tmp)))
- {
- if (net_store_null(packet))
- return 1;
- }
- else if (net_store_data(packet,res->ptr(),res->length()))
- return 1;
- }
- if (my_net_write(&thd->net, (char*) packet->ptr(),packet->length()))
- break;
- }
- return 0;
-}
-
-
-/*
- Send name and type of result to client.
-
- SYNOPSIS
- send_fields()
- THD Thread data object
- list List of items to send to client
- convert object used to convertation to another character set
- flag Bit mask with the following functions:
- 1 send number of rows
- 2 send default values
- 4 Don't convert field names
-
- DESCRIPTION
- Sum fields has table name empty and field_name.
- Uses send_fields_convert() and send_fields() depending on
- if we have an active character set convert or not.
-
- RETURN VALUES
- 0 ok
- 1 Error (Note that in this case the error is not sent to the client)
-*/
-
-bool
-send_fields(THD *thd, List<Item> &list, uint flag)
-{
- char buff[9]; // Big enough for store_length
- CONVERT *convert= (flag & 4) ? (CONVERT*) 0 : thd->variables.convert_set;
- DBUG_ENTER("send_fields");
-
- if (thd->fatal_error) // We have got an error
- goto err;
-
- if (flag & 1)
- { // Packet with number of elements
- char *pos=net_store_length(buff, (uint) list.elements);
- (void) my_net_write(&thd->net, buff,(uint) (pos-buff));
- }
-
- /*
- Avoid check conditions on convert() for each field
- by having two different functions
- */
- if (convert)
- {
- if (send_convert_fields(thd, list, convert, flag))
- goto err;
- }
- else if (send_non_convert_fields(thd, list, flag))
- goto err;
-
- send_eof(thd);
- DBUG_RETURN(0);
-
-err:
- send_error(thd,ER_OUT_OF_RESOURCES); /* purecov: inspected */
- DBUG_RETURN(1); /* purecov: inspected */
-}
-
-#endif /* EMBEDDED_LIBRARY */
-
/*****************************************************************************
* Functions to free open table cache
****************************************************************************/
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index ed09421e66b..a4cd34e7856 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -154,6 +154,11 @@ THD::THD():user_time(0), fatal_error(0),
(qsort_cmp2) compare_prep_stmt, 1,
(tree_element_free) free_prep_stmt, 0);
+ /* Protocol */
+ protocol= &protocol_simple; // Default protocol
+ protocol_simple.init(this);
+ protocol_prep.init(this);
+
#ifdef USING_TRANSACTIONS
bzero((char*) &transaction,sizeof(transaction));
if (opt_using_transactions)
@@ -442,7 +447,7 @@ int THD::send_explain_fields(select_result *result)
{
List<Item> field_list;
Item *item;
- field_list.push_back(new Item_int("id",0,3));
+ field_list.push_back(new Item_return_int("id",3, MYSQL_TYPE_LONGLONG));
field_list.push_back(new Item_empty_string("select_type",19));
field_list.push_back(new Item_empty_string("table",NAME_LEN));
field_list.push_back(new Item_empty_string("type",10));
@@ -451,12 +456,13 @@ int THD::send_explain_fields(select_result *result)
item->maybe_null=1;
field_list.push_back(item=new Item_empty_string("key",NAME_LEN));
item->maybe_null=1;
- field_list.push_back(item=new Item_int("key_len",0,3));
+ field_list.push_back(item=new Item_return_int("key_len",3,
+ MYSQL_TYPE_LONGLONG));
item->maybe_null=1;
field_list.push_back(item=new Item_empty_string("ref",
NAME_LEN*MAX_REF_PARTS));
item->maybe_null=1;
- field_list.push_back(new Item_real("rows",0.0,0,10));
+ field_list.push_back(new Item_return_int("rows",10, MYSQL_TYPE_LONGLONG));
field_list.push_back(new Item_empty_string("Extra",255));
return (result->send_fields(field_list,1));
}
@@ -507,7 +513,7 @@ sql_exchange::sql_exchange(char *name,bool flag)
bool select_send::send_fields(List<Item> &list,uint flag)
{
- return ::send_fields(thd,list,flag);
+ return thd->protocol->send_fields(&list,flag);
}
@@ -517,35 +523,33 @@ bool select_send::send_fields(List<Item> &list,uint flag)
bool select_send::send_data(List<Item> &items)
{
- List_iterator_fast<Item> li(items);
- String *packet= &thd->packet;
- DBUG_ENTER("send_data");
-
if (unit->offset_limit_cnt)
{ // using limit offset,count
unit->offset_limit_cnt--;
- DBUG_RETURN(0);
+ return 0;
}
- packet->length(0); // Reset packet
+
+ List_iterator_fast<Item> li(items);
+ Protocol *protocol= thd->protocol;
+ char buff[MAX_FIELD_WIDTH];
+ String buffer(buff, sizeof(buff), system_charset_info);
+ DBUG_ENTER("send_data");
+
+ protocol->prepare_for_resend();
Item *item;
while ((item=li++))
{
- if (item->send(thd, packet))
+ if (item->send(protocol, &buffer))
{
- packet->free(); // Free used
+ protocol->free(); // Free used buffer
my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
- DBUG_RETURN(1);
+ break;
}
}
thd->sent_row_count++;
if (!thd->net.report_error)
- {
- DBUG_RETURN(my_net_write(&thd->net,
- (char*) packet->ptr(),
- packet->length()));
- }
- else
- DBUG_RETURN(1);
+ DBUG_RETURN(protocol->write());
+ DBUG_RETURN(1);
}
#endif /* EMBEDDED_LIBRARY */
@@ -940,9 +944,9 @@ bool select_singleval_subselect::send_data(List<Item> &items)
calculate value on it & determinate "is it NULL?".
*/
it->real_value= val_item->val_result();
- if ((it->null_value= val_item->is_null_result()))
+ if ((it->null_value= val_item->null_value))
{
- it->assign_null();
+ it->reset();
}
else
{
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 39efba28f5f..1d5a00682b8 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -398,6 +398,9 @@ public:
MEM_ROOT mem_root; // 1 command-life memory pool
MEM_ROOT con_root; // connection-life memory
MEM_ROOT warn_root; // For warnings and errors
+ Protocol *protocol; // Current protocol
+ Protocol_simple protocol_simple; // Normal protocol
+ Protocol_prep protocol_prep; // Binary protocol
HASH user_vars; // hash for user variables
TREE prepared_statements;
String packet; // dynamic buffer for network I/O
diff --git a/sql/sql_db.cc b/sql/sql_db.cc
index f8929f207bc..bca133bd63a 100644
--- a/sql/sql_db.cc
+++ b/sql/sql_db.cc
@@ -604,7 +604,8 @@ bool mysql_change_db(THD *thd, const char *name)
}
-int mysqld_show_create_db(THD *thd, const char *dbname, HA_CREATE_INFO *create_info)
+int mysqld_show_create_db(THD *thd, const char *dbname,
+ HA_CREATE_INFO *create_info)
{
int length;
char path[FN_REFLEN], *to;
@@ -613,7 +614,7 @@ int mysqld_show_create_db(THD *thd, const char *dbname, HA_CREATE_INFO *create_i
HA_CREATE_INFO create;
CONVERT *convert=thd->variables.convert_set;
uint create_options = create_info ? create_info->options : 0;
-
+ Protocol *protocol=thd->protocol;
DBUG_ENTER("mysql_show_create_db");
if (check_db_name(dbname))
@@ -663,12 +664,11 @@ int mysqld_show_create_db(THD *thd, const char *dbname, HA_CREATE_INFO *create_i
field_list.push_back(new Item_empty_string("Database",NAME_LEN));
field_list.push_back(new Item_empty_string("Create Database",1024));
- if (send_fields(thd,field_list,1))
+ if (protocol->send_fields(&field_list,1))
DBUG_RETURN(1);
- String *packet = &thd->packet;
- packet->length(0);
- net_store_data(packet, convert, dbname);
+ protocol->prepare_for_resend();
+ protocol->store(dbname, strlen(dbname));
to= strxmov(path, "CREATE DATABASE ", NullS);
if (create_options & HA_LEX_CREATE_IF_NOT_EXISTS)
to= strxmov(to,"/*!32312 IF NOT EXISTS*/ ", NullS);
@@ -678,11 +678,10 @@ int mysqld_show_create_db(THD *thd, const char *dbname, HA_CREATE_INFO *create_i
to= strxmov(to," /*!40100 DEFAULT CHARACTER SET ",
create.table_charset->name,"*/",NullS);
- net_store_data(packet, convert, path, (uint) (to-path));
+ protocol->store(path, (uint) (to-path));
- if (SEND_ROW(thd, field_list.elements, (char*) packet->ptr(), packet->length()))
+ if (protocol->write())
DBUG_RETURN(1);
-
send_eof(thd);
DBUG_RETURN(0);
}
diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc
index f0df6811133..f7d845e9e36 100644
--- a/sql/sql_derived.cc
+++ b/sql/sql_derived.cc
@@ -27,13 +27,33 @@
static const char *any_db="*any*"; // Special symbol for check_access
+/*
+ Resolve derived tables in all queries
+
+ SYNOPSIS
+ mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
+ thd Thread handle
+ lex LEX for this thread
+ unit node that contains all SELECT's for derived tables
+ t TABLE_LIST for the upper SELECT
+
+ IMPLEMENTATION
+
+ Derived table is resolved with temporary table. It is created based on the
+ queries defined. After temporary table is created, if this is not EXPLAIN,
+ then the entire unit / node is deleted. unit is deleted if UNION is used
+ for derived table and node is deleted is it is a simple SELECT.
+
+ After table creation, the above TABLE_LIST is updated with a new table.
+
+ This function is called before any command containing derived table is executed.
+
+ TODO: To move creation of derived tables IN open_and_lock_tables()
+*/
+
int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
{
- /*
- TODO: make derived tables with union inside (now only 1 SELECT may be
- procesed)
- */
SELECT_LEX *sl= unit->first_select();
List<Item> item_list;
TABLE *table;
@@ -41,8 +61,19 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
select_union *derived_result;
TABLE_LIST *tables= (TABLE_LIST *)sl->table_list.first;
TMP_TABLE_PARAM tmp_table_param;
+ bool is_union=sl->next_select() && sl->next_select()->linkage == UNION_TYPE;
DBUG_ENTER("mysql_derived");
+
+/*
+ In create_total_list, derived tables have to be treated in case of EXPLAIN,
+ This is because unit/node is not deleted in that case. Current code in this
+ function has to be improved to recognize better when this function is called
+ from derived tables and when from other functions.
+*/
+ if (is_union && unit->create_total_list(thd, lex, &tables))
+ DBUG_RETURN(-1);
+
if (tables)
res= check_table_access(thd,SELECT_ACL, tables);
else
@@ -58,6 +89,28 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
if (!(res=open_and_lock_tables(thd,tables)))
{
+ if (is_union)
+ {
+/*
+ The following code is a re-do of fix_tables_pointers() found in sql_select.cc
+ for UNION's within derived tables. The only difference is in navigation, as in
+ derived tables we care for this level only.
+
+ fix_tables_pointers makes sure that in UNION's we do not open single table twice
+ if found in different SELECT's.
+
+*/
+ for (SELECT_LEX *sel= sl;
+ sel;
+ sel= sel->next_select())
+ {
+ for (TABLE_LIST *cursor= (TABLE_LIST *)sel->table_list.first;
+ cursor;
+ cursor=cursor->next)
+ cursor->table= cursor->table_list->table;
+ }
+ }
+
if (setup_fields(thd,tables,item_list,0,0,1))
{
res=-1;
@@ -66,7 +119,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
bzero((char*) &tmp_table_param,sizeof(tmp_table_param));
tmp_table_param.field_count=item_list.elements;
if (!(table=create_tmp_table(thd, &tmp_table_param, item_list,
- (ORDER*) 0, 0, 1,
+ (ORDER*) 0, is_union && !unit->union_option, 1,
(sl->options | thd->options |
TMP_TABLE_ALL_COLUMNS),
HA_POS_ERROR)))
@@ -87,11 +140,14 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
SELECT_LEX_NODE *save_current_select= lex->current_select;
lex->current_select= sl;
- res= mysql_select(thd, tables, sl->item_list,
+ if (is_union)
+ res=mysql_union(thd,lex,derived_result,unit);
+ else
+ res= mysql_select(thd, tables, sl->item_list,
sl->where, (ORDER *) sl->order_list.first,
(ORDER*) sl->group_list.first,
sl->having, (ORDER*) NULL,
- sl->options | thd->options | SELECT_NO_UNLOCK,
+ sl->options | thd->options | SELECT_NO_UNLOCK,
derived_result, unit, sl, 0);
lex->current_select= save_current_select;
@@ -112,7 +168,12 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
tables->table_list->table=tables->table; // to fix a problem in EXPLAIN
}
else
- sl->exclude();
+ {
+ if (is_union)
+ unit->exclude();
+ else
+ sl->exclude();
+ }
t->db=(char *)"";
t->derived=(SELECT_LEX *)0; // just in case ...
table->file->info(HA_STATUS_VARIABLE);
diff --git a/sql/sql_error.cc b/sql/sql_error.cc
index dc9fbe8468d..c9684855b86 100644
--- a/sql/sql_error.cc
+++ b/sql/sql_error.cc
@@ -150,7 +150,7 @@ void store_warning(THD *thd, uint errcode, ...)
*/
static const char *warning_level_names[]= {"Note", "Warning", "Error", "?"};
-
+static int warning_level_length[]= { 4, 7, 5, 1 };
my_bool mysqld_show_warnings(THD *thd, ulong levels_to_show)
{
@@ -158,15 +158,16 @@ my_bool mysqld_show_warnings(THD *thd, ulong levels_to_show)
DBUG_ENTER("mysqld_show_warnings");
field_list.push_back(new Item_empty_string("Level", 7));
- field_list.push_back(new Item_int("Code",0,4));
+ field_list.push_back(new Item_return_int("Code",4, MYSQL_TYPE_LONG));
field_list.push_back(new Item_empty_string("Message",MYSQL_ERRMSG_SIZE));
- if (send_fields(thd,field_list,1))
+ if (thd->protocol->send_fields(&field_list,1))
DBUG_RETURN(1);
MYSQL_ERROR *err;
SELECT_LEX *sel= &thd->lex.select_lex;
ha_rows offset= sel->offset_limit, limit= sel->select_limit;
+ Protocol *protocol=thd->protocol;
List_iterator_fast<MYSQL_ERROR> it(thd->warn_list);
while ((err= it++))
@@ -179,11 +180,12 @@ my_bool mysqld_show_warnings(THD *thd, ulong levels_to_show)
offset--;
continue;
}
- thd->packet.length(0);
- net_store_data(&thd->packet,warning_level_names[err->level]);
- net_store_data(&thd->packet,(uint32) err->code);
- net_store_data(&thd->packet,err->msg);
- if (SEND_ROW(thd, field_list.elements, (char*)thd->packet.ptr(),thd->packet.length()))
+ protocol->prepare_for_resend();
+ protocol->store(warning_level_names[err->level],
+ warning_level_length[err->level]);
+ protocol->store((uint32) err->code);
+ protocol->store(err->msg, strlen(err->msg));
+ if (protocol->write())
DBUG_RETURN(1);
if (!--limit)
break;
diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc
index 2e979a948e6..97703cd6b20 100644
--- a/sql/sql_handler.cc
+++ b/sql/sql_handler.cc
@@ -123,6 +123,9 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
List<Item> list;
list.push_front(new Item_field(NULL,NULL,"*"));
List_iterator<Item> it(list);
+ Protocol *protocol= thd->protocol;
+ char buff[MAX_FIELD_WIDTH];
+ String buffer(buff, sizeof(buff), system_charset_info);
uint num_rows;
it++;
@@ -131,7 +134,7 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
table->file->init_table_handle_for_HANDLER(); // Only InnoDB requires it
select_limit+=offset_limit;
- send_fields(thd,list,1);
+ protocol->send_fields(&list,1);
HANDLER_TABLES_HACK(thd);
MYSQL_LOCK *lock=mysql_lock_tables(thd,&tables->table,1);
@@ -141,7 +144,7 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
for (num_rows=0; num_rows < select_limit; )
{
- switch(mode) {
+ switch (mode) {
case RFIRST:
err=keyname ?
table->file->index_first(table->record[0]) :
@@ -216,24 +219,24 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
if (!cond->val_int())
continue;
}
- if (num_rows>=offset_limit)
+ if (num_rows >= offset_limit)
{
if (!err)
{
String *packet = &thd->packet;
Item *item;
- packet->length(0);
+ protocol->prepare_for_resend();
it.rewind();
while ((item=it++))
{
- if (item->send(thd,packet))
+ if (item->send(thd->protocol, &buffer))
{
- packet->free(); // Free used
+ protocol->free(); // Free used
my_error(ER_OUT_OF_RESOURCES,MYF(0));
goto err;
}
}
- SEND_ROW(thd, list.elements, (char*)packet->ptr(), packet->length());
+ protocol->write();
}
}
num_rows++;
@@ -249,26 +252,26 @@ err0:
}
/**************************************************************************
- 2Monty: It could easily happen, that the following service functions are
+ Monty: It could easily happen, that the following service functions are
already defined somewhere in the code, but I failed to find them.
If this is the case, just say a word and I'll use old functions here.
**************************************************************************/
-/* Note: this function differs from find_locked_table() because we're looking
- here for alias, not real table name
- */
+/*
+ Note: this function differs from find_locked_table() because we're looking
+ here for alias, not real table name
+*/
+
static TABLE **find_table_ptr_by_name(THD *thd, const char *db,
const char *alias)
{
int dblen;
TABLE **ptr;
- if (!db || ! *db)
- db= thd->db ? thd->db : "";
dblen=strlen(db)+1;
- ptr=&(thd->handler_tables);
+ ptr= &(thd->handler_tables);
- for (TABLE *table=*ptr; table ; table=*ptr)
+ for (TABLE *table= *ptr; table ; table= *ptr)
{
if (!memcmp(table->table_cache_key, db, dblen) &&
!my_strcasecmp(system_charset_info,table->table_name,alias))
diff --git a/sql/sql_help.cc b/sql/sql_help.cc
index 03a435670c4..db28823a43d 100644
--- a/sql/sql_help.cc
+++ b/sql/sql_help.cc
@@ -219,22 +219,21 @@ int search_categories(THD *thd,
DBUG_RETURN(count);
}
-int send_variant_2_list(THD *thd, List<String> *names, my_bool is_category)
+int send_variant_2_list(Protocol *protocol, List<String> *names,
+ my_bool is_category)
{
DBUG_ENTER("send_names");
List_iterator<String> it(*names);
String *cur_name;
- String *packet= &thd->packet;
while ((cur_name = it++))
{
- packet->length(0);
- net_store_data(packet, cur_name->ptr());
- net_store_data(packet, is_category ? "Y" : "N");
- if (SEND_ROW(thd,2,(char*) packet->ptr(),packet->length()))
+ protocol->prepare_for_resend();
+ protocol->store(cur_name->ptr());
+ protocol->store(is_category ? "Y" : "N");
+ if (protocol->write())
DBUG_RETURN(-1);
}
-
DBUG_RETURN(0);
}
@@ -296,43 +295,44 @@ int get_all_names_for_category(THD *thd,MI_INFO *file_leafs,
DBUG_RETURN(0);
}
-int send_answer_1(THD *thd, const char *s1, const char *s2,
+int send_answer_1(Protocol *protocol, const char *s1, const char *s2,
const char *s3, const char *s4)
{
DBUG_ENTER("send_answer_1");
List<Item> field_list;
- field_list.push_back(new Item_empty_string("name",64));
- field_list.push_back(new Item_empty_string("is_category",1));
- field_list.push_back(new Item_empty_string("description",1000));
- field_list.push_back(new Item_empty_string("example",1000));
+ field_list.push_back(new Item_empty_string("Name",64));
+ field_list.push_back(new Item_empty_string("Category",1));
+ field_list.push_back(new Item_empty_string("Description",1000));
+ field_list.push_back(new Item_empty_string("Example",1000));
- if (send_fields(thd,field_list,1))
+ if (protocol->send_fields(&field_list,1))
DBUG_RETURN(1);
- String *packet= &thd->packet;
- packet->length(0);
- net_store_data(packet, s1);
- net_store_data(packet, s2);
- net_store_data(packet, s3);
- net_store_data(packet, s4);
-
- if (SEND_ROW(thd,field_list.elements,(char*) packet->ptr(),packet->length()))
+ protocol->prepare_for_resend();
+ protocol->store(s1);
+ protocol->store(s2);
+ protocol->store(s3);
+ protocol->store(s4);
+ if (protocol->write())
DBUG_RETURN(-1);
DBUG_RETURN(0);
}
-int send_header_2(THD *thd)
+
+int send_header_2(Protocol *protocol)
{
DBUG_ENTER("send_header2");
List<Item> field_list;
- field_list.push_back(new Item_empty_string("name",64));
- field_list.push_back(new Item_empty_string("is_category",1));
- DBUG_RETURN(send_fields(thd,field_list,1));
+ field_list.push_back(new Item_empty_string("Name",64));
+ field_list.push_back(new Item_empty_string("Category",1));
+ DBUG_RETURN(protocol->send_fields(&field_list,1));
}
-int mysqld_help (THD *thd, const char *mask)
+
+int mysqld_help(THD *thd, const char *mask)
{
+ Protocol *protocol= thd->protocol;
DBUG_ENTER("mysqld_help");
MI_INFO *file_leafs= 0;
@@ -345,7 +345,7 @@ int mysqld_help (THD *thd, const char *mask)
int count= search_functions(file_leafs, mask,
&function_list,&name,&description,&example);
- if (count<0)
+ if (count < 0)
{
res= 1;
goto end;
@@ -371,31 +371,31 @@ int mysqld_help (THD *thd, const char *mask)
example.append(*cur_leaf);
example.append("\n",1);
}
- if ((res= send_answer_1(thd, categories_list.head()->ptr(),
- "Y","",example.ptr())))
+ if ((res= send_answer_1(protocol, categories_list.head()->ptr(),
+ "Y","",example.ptr())))
goto end;
}
else
{
- if ((res= send_header_2(thd)) ||
+ if ((res= send_header_2(protocol)) ||
(count==0 &&
(search_categories(thd, 0, &categories_list, 0)<0 &&
(res= 1))) ||
- (res= send_variant_2_list(thd,&categories_list,true)))
+ (res= send_variant_2_list(protocol,&categories_list,true)))
goto end;
}
}
else if (count==1)
{
- if ((res= send_answer_1(thd,name->ptr(),"N",
- description->ptr(), example->ptr())))
+ if ((res= send_answer_1(protocol,name->ptr(),"N",
+ description->ptr(), example->ptr())))
goto end;
}
- else if((res= send_header_2(thd)) ||
- (res= send_variant_2_list(thd,&function_list,false)) ||
+ else if((res= send_header_2(protocol)) ||
+ (res= send_variant_2_list(protocol,&function_list,false)) ||
(search_categories(thd, mask, &categories_list, 0)<0 &&
(res=1)) ||
- (res= send_variant_2_list(thd,&categories_list,true)))
+ (res= send_variant_2_list(protocol,&categories_list,true)))
{
goto end;
}
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 833f36dbe9f..99e465f79c0 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -941,8 +941,6 @@ int yylex(void *arg, void *yythd)
void st_select_lex_node::init_query()
{
- next= master= slave= link_next= 0;
- prev= link_prev= 0;
dependent= 0;
}
@@ -995,7 +993,8 @@ void st_select_lex::init_select()
use_index.empty();
ftfunc_list_alloc.empty();
ftfunc_list= &ftfunc_list_alloc;
- linkage= UNSPECIFIED_TYPE;
+ if (linkage != UNION_TYPE)
+ linkage= UNSPECIFIED_TYPE;
}
/*
@@ -1010,6 +1009,7 @@ void st_select_lex_node::include_down(st_select_lex_node *upper)
prev= &upper->slave;
upper->slave= this;
master= upper;
+ slave= 0;
}
/* include neighbour (on same level) */
@@ -1020,6 +1020,7 @@ void st_select_lex_node::include_neighbour(st_select_lex_node *before)
prev= &before->next;
before->next= this;
master= before->master;
+ slave= 0;
}
/* including in global SELECT_LEX list */
@@ -1206,7 +1207,7 @@ bool st_select_lex_unit::create_total_list_n_last_return(THD *thd, st_lex *lex,
net_printf(thd,ER_WRONG_USAGE,"UNION","ORDER BY");
return 1;
}
- if (sl->linkage == DERIVED_TABLE_TYPE)
+ if (sl->linkage == DERIVED_TABLE_TYPE && !sl->next_select())
continue;
for (SELECT_LEX_UNIT *inner= sl->first_inner_unit();
inner;
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 0c761baffa3..927b806a082 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -194,6 +194,7 @@ enum olap_type
Base class for st_select_lex (SELECT_LEX) &
st_select_lex_unit (SELECT_LEX_UNIT)
*/
+struct st_lex;
class st_select_lex;
class st_select_lex_unit;
class st_select_lex_node {
@@ -252,6 +253,7 @@ public:
void mark_as_dependent(st_select_lex *last);
friend class st_select_lex_unit;
+ friend bool mysql_new_select(struct st_lex *lex, bool move_down);
private:
void fast_exclude();
};
diff --git a/sql/sql_list.h b/sql/sql_list.h
index 56e6528f214..1711a340cae 100644
--- a/sql/sql_list.h
+++ b/sql/sql_list.h
@@ -25,8 +25,16 @@
class Sql_alloc
{
public:
- static void *operator new(size_t size) {return (void*) sql_alloc((uint) size); }
+ static void *operator new(size_t size)
+ {
+ return (void*) sql_alloc((uint) size);
+ }
+ static void *operator new[](size_t size)
+ {
+ return (void*) sql_alloc((uint) size);
+ }
static void operator delete(void *ptr, size_t size) {} /*lint -e715 */
+ static void operator delete[](void *ptr, size_t size) {}
#ifdef HAVE_purify
bool dummy;
inline Sql_alloc() :dummy(0) {}
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 97804a0312f..b3e44fe10b3 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -3030,11 +3030,13 @@ mysql_init_query(THD *thd)
lex->select_lex.init_query();
lex->value_list.empty();
lex->param_list.empty();
+ lex->unit.next= lex->unit.master= lex->unit.link_next= 0;
+ lex->unit.prev= lex->unit.link_prev= 0;
lex->unit.global_parameters= lex->unit.slave= lex->current_select=
lex->all_selects_list= &lex->select_lex;
lex->select_lex.master= &lex->unit;
lex->select_lex.prev= &lex->unit.slave;
- lex->select_lex.link_next= 0;
+ lex->select_lex.link_next= lex->select_lex.slave= lex->select_lex.next= 0;
lex->select_lex.link_prev= (st_select_lex_node**)&(lex->all_selects_list);
lex->olap=lex->describe=0;
lex->derived_tables= false;
@@ -3049,11 +3051,11 @@ mysql_init_query(THD *thd)
DBUG_VOID_RETURN;
}
+
void
mysql_init_select(LEX *lex)
{
SELECT_LEX *select_lex= lex->current_select->select_lex();
- DBUG_ASSERT(select_lex->linkage != GLOBAL_OPTIONS_TYPE);
select_lex->init_select();
select_lex->master_unit()->select_limit= select_lex->select_limit=
lex->thd->variables.select_limit;
@@ -3084,6 +3086,8 @@ mysql_new_select(LEX *lex, bool move_down)
unit->init_query();
unit->init_select();
unit->include_down(lex->current_select);
+ unit->link_next= 0;
+ unit->link_prev= 0;
select_lex->include_down(unit);
}
else
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 00c88752619..0c21ffe3f95 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -520,7 +520,8 @@ static bool mysql_test_select_fields(PREP_STMT *stmt, TABLE_LIST *tables,
sending any info on where clause.
*/
if (send_prep_stmt(stmt, fields.elements) ||
- send_fields(thd,fields,0) || send_item_params(stmt))
+ thd->protocol_prep.send_fields(&fields,0) ||
+ send_item_params(stmt))
DBUG_RETURN(1);
DBUG_RETURN(0);
}
@@ -734,7 +735,9 @@ void mysql_stmt_execute(THD *thd, char *packet)
mysql_delete(), mysql_update() and mysql_select() to not to
have re-check on setup_* and other things ..
*/
+ thd->protocol= &thd->protocol_prep; // Switch to binary protocol
mysql_execute_command(stmt->thd);
+ thd->protocol= &thd->protocol_simple; // Use normal protocol
if (!(specialflag & SPECIAL_NO_PRIOR))
my_pthread_setprio(pthread_self(), WAIT_PRIOR);
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index 54a7bdb8dc8..3bffeaccb15 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -930,14 +930,15 @@ int cmp_master_pos(const char* log_file_name1, ulonglong log_pos1,
int show_binlog_events(THD* thd)
{
+ Protocol *protocol= thd->protocol;
DBUG_ENTER("show_binlog_events");
List<Item> field_list;
- const char* errmsg = 0;
+ const char *errmsg = 0;
IO_CACHE log;
File file = -1;
Log_event::init_show_field_list(&field_list);
- if (send_fields(thd, field_list, 1))
+ if (protocol-> send_fields(&field_list, 1))
DBUG_RETURN(-1);
if (mysql_bin_log.is_open())
@@ -985,7 +986,7 @@ int show_binlog_events(THD* thd)
(ev = Log_event::read_log_event(&log,(pthread_mutex_t*)0,0)); )
{
if (event_count >= limit_start &&
- ev->net_send(thd, linfo.log_file_name, pos))
+ ev->net_send(protocol, linfo.log_file_name, pos))
{
errmsg = "Net error";
delete ev;
@@ -1031,28 +1032,29 @@ err:
int show_binlog_info(THD* thd)
{
+ Protocol *protocol= thd->protocol;
DBUG_ENTER("show_binlog_info");
List<Item> field_list;
field_list.push_back(new Item_empty_string("File", FN_REFLEN));
- field_list.push_back(new Item_empty_string("Position",20));
- field_list.push_back(new Item_empty_string("Binlog_do_db",20));
- field_list.push_back(new Item_empty_string("Binlog_ignore_db",20));
+ field_list.push_back(new Item_return_int("Position",20,
+ MYSQL_TYPE_LONGLONG));
+ field_list.push_back(new Item_empty_string("Binlog_do_db",255));
+ field_list.push_back(new Item_empty_string("Binlog_ignore_db",255));
- if (send_fields(thd, field_list, 1))
+ if (protocol->send_fields(&field_list, 1))
DBUG_RETURN(-1);
- String* packet = &thd->packet;
- packet->length(0);
+ protocol->prepare_for_resend();
if (mysql_bin_log.is_open())
{
LOG_INFO li;
mysql_bin_log.get_current_log(&li);
int dir_len = dirname_length(li.log_file_name);
- net_store_data(packet, li.log_file_name + dir_len);
- net_store_data(packet, (longlong)li.pos);
- net_store_data(packet, &binlog_do_db);
- net_store_data(packet, &binlog_ignore_db);
- if (my_net_write(&thd->net, (char*)thd->packet.ptr(), packet->length()))
+ protocol->store(li.log_file_name + dir_len);
+ protocol->store((ulonglong) li.pos);
+ protocol->store(&binlog_do_db);
+ protocol->store(&binlog_ignore_db);
+ if (protocol->write())
DBUG_RETURN(-1);
}
send_eof(thd);
@@ -1081,6 +1083,8 @@ int show_binlogs(THD* thd)
List<Item> field_list;
String *packet = &thd->packet;
uint length;
+ Protocol *protocol= thd->protocol;
+ DBUG_ENTER("show_binlogs");
if (!mysql_bin_log.is_open())
{
@@ -1090,8 +1094,8 @@ int show_binlogs(THD* thd)
}
field_list.push_back(new Item_empty_string("Log_name", 255));
- if (send_fields(thd, field_list, 1))
- return 1;
+ if (protocol->send_fields(&field_list, 1))
+ DBUG_RETURN(1);
mysql_bin_log.lock_index();
index_file=mysql_bin_log.get_index_file();
@@ -1100,22 +1104,22 @@ int show_binlogs(THD* thd)
/* The file ends with EOF or empty line */
while ((length=my_b_gets(index_file, fname, sizeof(fname))) > 1)
{
+ protocol->prepare_for_resend();
int dir_len = dirname_length(fname);
- packet->length(0);
/* The -1 is for removing newline from fname */
- net_store_data(packet, fname + dir_len, length-1-dir_len);
- if (my_net_write(net, (char*) packet->ptr(), packet->length()))
+ protocol->store(fname + dir_len, length-1-dir_len);
+ if (protocol->write())
goto err;
}
mysql_bin_log.unlock_index();
send_eof(thd);
- return 0;
+ DBUG_RETURN(0);
err_with_msg:
send_error(thd, ER_UNKNOWN_ERROR, errmsg);
err:
mysql_bin_log.unlock_index();
- return 1;
+ DBUG_RETURN(1);
}
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index a0751e16be9..c7ab438ba97 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -162,7 +162,7 @@ int handle_select(THD *thd, LEX *lex, select_result *result)
register SELECT_LEX *select_lex = &lex->select_lex;
fix_tables_pointers(lex->all_selects_list);
if (select_lex->next_select())
- res=mysql_union(thd,lex,result);
+ res=mysql_union(thd,lex,result,&lex->unit);
else
res=mysql_select(thd,(TABLE_LIST*) select_lex->table_list.first,
select_lex->item_list,
@@ -761,6 +761,8 @@ JOIN::exec()
test_if_skip_sort_order(&join_tab[const_tables], order,
select_limit, 0))))
order=0;
+ if (procedure)
+ (void)result->prepare(fields_list, unit);
select_describe(this, need_tmp,
order != 0 && !skip_sort_order,
select_distinct);
@@ -791,6 +793,16 @@ JOIN::exec()
HA_POS_ERROR)))
DBUG_VOID_RETURN;
+ /*
+ We don't have to store rows in temp table that doesn't match HAVING if:
+ - we are sorting the table and writing complete group rows to the
+ temp table.
+ - We are using DISTINCT without resolving the distinct as a GROUP BY
+ on all columns.
+
+ If having is not handled here, it will be checked before the row
+ is sent to the client.
+ */
if (having_list &&
(sort_and_group || (exec_tmp_table->distinct && !group_list)))
having=having_list;
@@ -3047,6 +3059,7 @@ join_free(JOIN *join, bool full)
if (join->tables > join->const_tables) // Test for not-const tables
free_io_cache(join->table[join->const_tables]);
if (join->select_lex->dependent && !full)
+ {
for (tab=join->join_tab,end=tab+join->tables ; tab != end ; tab++)
{
if (tab->table)
@@ -3061,6 +3074,7 @@ join_free(JOIN *join, bool full)
tab->table->file->index_end();
}
}
+ }
else
{
for (tab=join->join_tab,end=tab+join->tables ; tab != end ; tab++)
@@ -3078,6 +3092,11 @@ join_free(JOIN *join, bool full)
/* Don't free index if we are using read_record */
if (!tab->read_record.table)
tab->table->file->index_end();
+ /*
+ We need to reset this for next select
+ (Tested in part_of_refkey)
+ */
+ tab->table->reginfo.join_tab= 0;
}
end_read_record(&tab->read_record);
}
@@ -3775,13 +3794,14 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
else
return new Field_double(item_sum->max_length,maybe_null,
item->name, table, item_sum->decimals);
- case Item_sum::STD_FUNC: /* Place for sum & count */
+ case Item_sum::VARIANCE_FUNC: /* Place for sum & count */
+ case Item_sum::STD_FUNC:
if (group)
return new Field_string(sizeof(double)*2+sizeof(longlong),
maybe_null, item->name,table,my_charset_bin);
else
return new Field_double(item_sum->max_length, maybe_null,
- item->name,table,item_sum->decimals);
+ item->name,table,item_sum->decimals);
case Item_sum::UNIQUE_USERS_FUNC:
return new Field_long(9,maybe_null,item->name,table,1);
default:
@@ -7492,9 +7512,8 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
item_list.push_back(new Item_string(join->select_lex->type,
strlen(join->select_lex->type),
default_charset_info));
- Item *empty= new Item_empty_string("",0);
for (uint i=0 ; i < 7; i++)
- item_list.push_back(empty);
+ item_list.push_back(item_null);
item_list.push_back(new Item_string(message,strlen(message),
default_charset_info));
if (result->send_data(item_list))
@@ -7534,7 +7553,9 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
item_list.push_back(new Item_string(table->table_name,
strlen(table->table_name),
default_charset_info));
- item_list.push_back(new Item_string(join_type_str[tab->type],strlen(join_type_str[tab->type]),default_charset_info));
+ item_list.push_back(new Item_string(join_type_str[tab->type],
+ strlen(join_type_str[tab->type]),
+ default_charset_info));
key_map bits;
uint j;
for (j=0,bits=tab->keys ; bits ; j++,bits>>=1)
@@ -7592,9 +7613,9 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
item_list.push_back(item_null);
item_list.push_back(item_null);
}
- sprintf(buff3,"%.0f",join->best_positions[i].records_read);
- item_list.push_back(new Item_string(buff3,strlen(buff3),
- default_charset_info));
+ item_list.push_back(new Item_int((longlong) (ulonglong)
+ join->best_positions[i]. records_read,
+ 21));
my_bool key_read=table->key_read;
if (tab->type == JT_NEXT &&
((table->used_keys & ((key_map) 1 << tab->index))))
@@ -7650,6 +7671,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
DBUG_VOID_RETURN;
}
+
int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result)
{
DBUG_ENTER("mysql_explain_union");
@@ -7680,6 +7702,7 @@ int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result)
DBUG_RETURN(res);
}
+
int mysql_explain_select(THD *thd, SELECT_LEX *select_lex, char const *type,
select_result *result)
{
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index fb457ea28a1..1ecb5e817d7 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -60,6 +60,7 @@ mysqld_show_dbs(THD *thd,const char *wild)
char *end;
List<char> files;
char *file_name;
+ Protocol *protocol= thd->protocol;
DBUG_ENTER("mysqld_show_dbs");
field->name=(char*) thd->alloc(20+ (wild ? (uint) strlen(wild)+4: 0));
@@ -69,13 +70,12 @@ mysqld_show_dbs(THD *thd,const char *wild)
strxmov(end," (",wild,")",NullS);
field_list.push_back(field);
- if (send_fields(thd,field_list,1))
+ if (protocol->send_fields(&field_list,1))
DBUG_RETURN(1);
if (mysql_find_files(thd,&files,NullS,mysql_data_home,wild,1))
DBUG_RETURN(1);
List_iterator_fast<char> it(files);
- String *packet= &thd->packet;
while ((file_name=it++))
{
if (thd->master_access & (DB_ACLS | SHOW_DB_ACL) ||
@@ -83,10 +83,9 @@ mysqld_show_dbs(THD *thd,const char *wild)
thd->priv_user, file_name) ||
(grant_option && !check_grant_db(thd, file_name)))
{
- packet->length(0);
- net_store_data(packet, thd->variables.convert_set, file_name);
- if (SEND_ROW(thd, field_list.elements,
- (char *)packet->ptr(), packet->length()))
+ protocol->prepare_for_resend();
+ protocol->store(file_name);
+ if (protocol->write())
DBUG_RETURN(-1);
}
}
@@ -103,30 +102,28 @@ int mysqld_show_open_tables(THD *thd,const char *wild)
{
List<Item> field_list;
OPEN_TABLE_LIST *open_list;
- CONVERT *convert=thd->variables.convert_set;
+ Protocol *protocol= thd->protocol;
DBUG_ENTER("mysqld_show_open_tables");
field_list.push_back(new Item_empty_string("Database",NAME_LEN));
field_list.push_back(new Item_empty_string("Table",NAME_LEN));
- field_list.push_back(new Item_int("In_use",0, 4));
- field_list.push_back(new Item_int("Name_locked",0, 4));
+ field_list.push_back(new Item_return_int("In_use", 1, MYSQL_TYPE_TINY));
+ field_list.push_back(new Item_return_int("Name_locked", 4, MYSQL_TYPE_TINY));
- if (send_fields(thd,field_list,1))
+ if (protocol->send_fields(&field_list,1))
DBUG_RETURN(1);
if (!(open_list=list_open_tables(thd,wild)) && thd->fatal_error)
DBUG_RETURN(-1);
- String *packet= &thd->packet;
for (; open_list ; open_list=open_list->next)
{
- packet->length(0);
- net_store_data(packet,convert, open_list->db);
- net_store_data(packet,convert, open_list->table);
- net_store_data(packet,open_list->in_use);
- net_store_data(packet,open_list->locked);
- if (SEND_ROW(thd, field_list.elements,
- (char *)packet->ptr(), packet->length()))
+ protocol->prepare_for_resend();
+ protocol->store(open_list->db);
+ protocol->store(open_list->table);
+ protocol->store_tiny((longlong) open_list->in_use);
+ protocol->store_tiny((longlong) open_list->locked);
+ if (protocol->write())
{
DBUG_RETURN(-1);
}
@@ -148,9 +145,11 @@ int mysqld_show_tables(THD *thd,const char *db,const char *wild)
char path[FN_LEN],*end;
List<char> files;
char *file_name;
+ Protocol *protocol= thd->protocol;
DBUG_ENTER("mysqld_show_tables");
- field->name=(char*) thd->alloc(20+(uint) strlen(db)+(wild ? (uint) strlen(wild)+4:0));
+ field->name=(char*) thd->alloc(20+(uint) strlen(db)+
+ (wild ? (uint) strlen(wild)+4:0));
end=strxmov(field->name,"Tables_in_",db,NullS);
if (wild && wild[0])
strxmov(end," (",wild,")",NullS);
@@ -158,18 +157,16 @@ int mysqld_show_tables(THD *thd,const char *db,const char *wild)
(void) sprintf(path,"%s/%s",mysql_data_home,db);
(void) unpack_dirname(path,path);
field_list.push_back(field);
- if (send_fields(thd,field_list,1))
+ if (protocol->send_fields(&field_list,1))
DBUG_RETURN(1);
if (mysql_find_files(thd,&files,db,path,wild,0))
DBUG_RETURN(-1);
List_iterator_fast<char> it(files);
- String *packet= &thd->packet;
while ((file_name=it++))
{
- packet->length(0);
- net_store_data(packet, thd->variables.convert_set, file_name);
- if (SEND_ROW(thd, field_list.elements,
- (char *)packet->ptr(), packet->length()))
+ protocol->prepare_for_resend();
+ protocol->store(file_name);
+ if (protocol->write())
DBUG_RETURN(-1);
}
send_eof(thd);
@@ -210,31 +207,32 @@ static struct show_table_type_st sys_table_types[]=
int mysqld_show_table_types(THD *thd)
{
List<Item> field_list;
+ Protocol *protocol= thd->protocol;
DBUG_ENTER("mysqld_show_table_types");
field_list.push_back(new Item_empty_string("Type",10));
field_list.push_back(new Item_empty_string("Support",10));
field_list.push_back(new Item_empty_string("Comment",80));
- if (send_fields(thd,field_list,1))
+ if (protocol->send_fields(&field_list,1))
DBUG_RETURN(1);
- const char *default_type_name= ha_table_typelib.type_names[thd->variables.table_type];
+ const char *default_type_name=
+ ha_table_typelib.type_names[thd->variables.table_type];
show_table_type_st *types;
- String *packet= &thd->packet;
for (types= sys_table_types; types->type; types++)
{
- packet->length(0);
- net_store_data(packet, types->type);
+ protocol->prepare_for_resend();
+ protocol->store(types->type);
const char *option_name= show_comp_option_name[(int) *types->value];
if (*types->value == SHOW_OPTION_YES &&
!my_strcasecmp(system_charset_info, default_type_name, types->type))
option_name= "DEFAULT";
- net_store_data(packet, option_name);
- net_store_data(packet, types->comment);
- if (SEND_ROW(thd, field_list.elements, (char*) packet->ptr(), packet->length()))
+ protocol->store(option_name);
+ protocol->store(types->comment);
+ if (protocol->write())
DBUG_RETURN(-1);
}
send_eof(thd);
@@ -279,24 +277,24 @@ static struct show_privileges_st sys_privileges[]=
int mysqld_show_privileges(THD *thd)
{
List<Item> field_list;
+ Protocol *protocol= thd->protocol;
DBUG_ENTER("mysqld_show_privileges");
field_list.push_back(new Item_empty_string("Privilege",10));
field_list.push_back(new Item_empty_string("Context",15));
field_list.push_back(new Item_empty_string("Comment",NAME_LEN));
- if (send_fields(thd,field_list,1))
+ if (protocol->send_fields(&field_list,1))
DBUG_RETURN(1);
show_privileges_st *privilege= sys_privileges;
- String *packet= &thd->packet;
for (privilege= sys_privileges; privilege->privilege ; privilege++)
{
- packet->length(0);
- net_store_data(packet,privilege->privilege);
- net_store_data(packet,privilege->context);
- net_store_data(packet,privilege->comment);
- if (SEND_ROW(thd,field_list.elements,(char*) packet->ptr(),packet->length()))
+ protocol->prepare_for_resend();
+ protocol->store(privilege->privilege);
+ protocol->store(privilege->context);
+ protocol->store(privilege->comment);
+ if (protocol->write())
DBUG_RETURN(-1);
}
send_eof(thd);
@@ -343,14 +341,15 @@ static struct show_column_type_st sys_column_types[]=
int mysqld_show_column_types(THD *thd)
{
List<Item> field_list;
+ Protocol *protocol= thd->protocol;
DBUG_ENTER("mysqld_show_column_types");
field_list.push_back(new Item_empty_string("Type",30));
field_list.push_back(new Item_int("Size",(longlong) 1,21));
field_list.push_back(new Item_empty_string("Min_Value",20));
field_list.push_back(new Item_empty_string("Max_Value",20));
- field_list.push_back(new Item_int("Prec", 0,4));
- field_list.push_back(new Item_int("Scale", 0,4));
+ field_list.push_back(new Item_return_int("Prec", 4, MYSQL_TYPE_SHORT));
+ field_list.push_back(new Item_return_int("Scale", 4, MYSQL_TYPE_SHORT));
field_list.push_back(new Item_empty_string("Nullable",4));
field_list.push_back(new Item_empty_string("Auto_Increment",4));
field_list.push_back(new Item_empty_string("Unsigned",4));
@@ -360,29 +359,28 @@ int mysqld_show_column_types(THD *thd)
field_list.push_back(new Item_empty_string("Default",NAME_LEN));
field_list.push_back(new Item_empty_string("Comment",NAME_LEN));
- if (send_fields(thd,field_list,1))
+ if (protocol->send_fields(&field_list,1))
DBUG_RETURN(1);
/* TODO: Change the loop to not use 'i' */
- String *packet= &thd->packet;
for (uint i=0; i < sizeof(sys_column_types)/sizeof(sys_column_types[0]); i++)
{
- packet->length(0);
- net_store_data(packet,sys_column_types[i].type);
- net_store_data(packet,(longlong)sys_column_types[i].size);
- net_store_data(packet,sys_column_types[i].min_value);
- net_store_data(packet,sys_column_types[i].max_value);
- net_store_data(packet,(uint32)sys_column_types[i].precision);
- net_store_data(packet,(uint32)sys_column_types[i].scale);
- net_store_data(packet,sys_column_types[i].nullable);
- net_store_data(packet,sys_column_types[i].auto_increment);
- net_store_data(packet,sys_column_types[i].unsigned_attr);
- net_store_data(packet,sys_column_types[i].zerofill);
- net_store_data(packet,sys_column_types[i].searchable);
- net_store_data(packet,sys_column_types[i].case_sensitivity);
- net_store_data(packet,sys_column_types[i].default_value);
- net_store_data(packet,sys_column_types[i].comment);
- if (SEND_ROW(thd,field_list.elements,(char*) packet->ptr(),packet->length()))
+ protocol->prepare_for_resend();
+ protocol->store(sys_column_types[i].type);
+ protocol->store((ulonglong) sys_column_types[i].size);
+ protocol->store(sys_column_types[i].min_value);
+ protocol->store(sys_column_types[i].max_value);
+ protocol->store_short((longlong) sys_column_types[i].precision);
+ protocol->store_short((longlong) sys_column_types[i].scale);
+ protocol->store(sys_column_types[i].nullable);
+ protocol->store(sys_column_types[i].auto_increment);
+ protocol->store(sys_column_types[i].unsigned_attr);
+ protocol->store(sys_column_types[i].zerofill);
+ protocol->store(sys_column_types[i].searchable);
+ protocol->store(sys_column_types[i].case_sensitivity);
+ protocol->store(sys_column_types[i].default_value);
+ protocol->store(sys_column_types[i].comment);
+ if (protocol->write())
DBUG_RETURN(-1);
}
send_eof(thd);
@@ -477,8 +475,8 @@ int mysqld_extend_show_tables(THD *thd,const char *db,const char *wild)
char path[FN_LEN];
char *file_name;
TABLE *table;
- String *packet= &thd->packet;
- CONVERT *convert=thd->variables.convert_set;
+ Protocol *protocol= thd->protocol;
+ TIME time;
DBUG_ENTER("mysqld_extend_show_tables");
(void) sprintf(path,"%s/%s",mysql_data_home,db);
@@ -514,7 +512,7 @@ int mysqld_extend_show_tables(THD *thd,const char *db,const char *wild)
field_list.push_back(item=new Item_empty_string("Create_options",255));
item->maybe_null=1;
field_list.push_back(item=new Item_empty_string("Comment",80));
- if (send_fields(thd,field_list,1))
+ if (protocol->send_fields(&field_list,1))
DBUG_RETURN(1);
if (mysql_find_files(thd,&files,db,path,wild,0))
@@ -524,70 +522,74 @@ int mysqld_extend_show_tables(THD *thd,const char *db,const char *wild)
{
TABLE_LIST table_list;
bzero((char*) &table_list,sizeof(table_list));
- packet->length(0);
- net_store_data(packet,convert, file_name);
+ protocol->prepare_for_resend();
+ protocol->store(file_name);
table_list.db=(char*) db;
table_list.real_name= table_list.alias= file_name;
if (!(table = open_ltable(thd, &table_list, TL_READ)))
{
for (uint i=0 ; i < field_list.elements ; i++)
- net_store_null(packet);
- net_store_data(packet,convert, thd->net.last_error);
+ protocol->store_null();
+ protocol->store(thd->net.last_error);
thd->net.last_error[0]=0;
}
else
{
struct tm tm_tmp;
+ const char *str;
handler *file=table->file;
file->info(HA_STATUS_VARIABLE | HA_STATUS_TIME | HA_STATUS_NO_LOCK);
- net_store_data(packet, convert, file->table_type());
- net_store_data(packet, convert,
- (table->db_options_in_use & HA_OPTION_COMPRESS_RECORD) ?
- "Compressed" :
- (table->db_options_in_use & HA_OPTION_PACK_RECORD) ?
- "Dynamic" : "Fixed");
- net_store_data(packet, (longlong) file->records);
- net_store_data(packet, (uint32) file->mean_rec_length);
- net_store_data(packet, (longlong) file->data_file_length);
+ protocol->store(file->table_type());
+ str= ((table->db_options_in_use & HA_OPTION_COMPRESS_RECORD) ?
+ "Compressed" :
+ (table->db_options_in_use & HA_OPTION_PACK_RECORD) ?
+ "Dynamic" : "Fixed");
+ protocol->store(str);
+ protocol->store((ulonglong) file->records);
+ protocol->store((ulonglong) file->mean_rec_length);
+ protocol->store((ulonglong) file->data_file_length);
if (file->max_data_file_length)
- net_store_data(packet, (longlong) file->max_data_file_length);
+ protocol->store((ulonglong) file->max_data_file_length);
else
- net_store_null(packet);
- net_store_data(packet, (longlong) file->index_file_length);
- net_store_data(packet, (longlong) file->delete_length);
+ protocol->store_null();
+ protocol->store((ulonglong) file->index_file_length);
+ protocol->store((ulonglong) file->delete_length);
if (table->found_next_number_field)
{
table->next_number_field=table->found_next_number_field;
table->next_number_field->reset();
file->update_auto_increment();
- net_store_data(packet, table->next_number_field->val_int());
+ protocol->store(table->next_number_field->val_int());
table->next_number_field=0;
}
else
- net_store_null(packet);
+ protocol->store_null();
if (!file->create_time)
- net_store_null(packet);
+ protocol->store_null();
else
{
localtime_r(&file->create_time,&tm_tmp);
- net_store_data(packet, &tm_tmp);
+ localtime_to_TIME(&time, &tm_tmp);
+ protocol->store(&time);
}
if (!file->update_time)
- net_store_null(packet);
+ protocol->store_null();
else
{
localtime_r(&file->update_time,&tm_tmp);
- net_store_data(packet, &tm_tmp);
+ localtime_to_TIME(&time, &tm_tmp);
+ protocol->store(&time);
}
if (!file->check_time)
- net_store_null(packet);
+ protocol->store_null();
else
{
localtime_r(&file->check_time,&tm_tmp);
- net_store_data(packet, &tm_tmp);
+ localtime_to_TIME(&time, &tm_tmp);
+ protocol->store(&time);
}
- net_store_data(packet, convert, table->table_charset ?
- table->table_charset->name : "default");
+ str= (table->table_charset ? table->table_charset->name : "default");
+ protocol->store(str);
{
char option_buff[350],*ptr;
ptr=option_buff;
@@ -624,20 +626,19 @@ int mysqld_extend_show_tables(THD *thd,const char *db,const char *wild)
my_raid_type(file->raid_type), file->raid_chunks, file->raid_chunksize/RAID_BLOCK_SIZE);
ptr=strmov(ptr,buff);
}
- net_store_data(packet, convert, option_buff+1,
- (ptr == option_buff ? 0 : (uint) (ptr-option_buff)-1));
+ protocol->store(option_buff+1,
+ (ptr == option_buff ? 0 : (uint) (ptr-option_buff)-1));
}
{
char *comment=table->file->update_table_comment(table->comment);
- net_store_data(packet, comment);
+ protocol->store(comment);
if (comment != table->comment)
my_free(comment,MYF(0));
}
close_thread_tables(thd,0);
}
- if (SEND_ROW(thd, field_list.elements,
- (char *)packet->ptr(), packet->length()))
- DBUG_RETURN(-1);
+ if (protocol->write())
+ DBUG_RETURN(-1);
}
send_eof(thd);
DBUG_RETURN(0);
@@ -655,7 +656,7 @@ mysqld_show_fields(THD *thd, TABLE_LIST *table_list,const char *wild,
handler *file;
char tmp[MAX_FIELD_WIDTH];
Item *item;
- CONVERT *convert=thd->variables.convert_set;
+ Protocol *protocol= thd->protocol;
DBUG_ENTER("mysqld_show_fields");
DBUG_PRINT("enter",("db: %s table: %s",table_list->db,
table_list->real_name));
@@ -691,7 +692,7 @@ mysqld_show_fields(THD *thd, TABLE_LIST *table_list,const char *wild,
(void) my_net_write(&thd->net,tmp,(uint) (pos-tmp));
}
#endif
- if (send_fields(thd,field_list,0))
+ if (protocol->send_fields(&field_list,0))
DBUG_RETURN(1);
restore_record(table,2); // Get empty record
@@ -714,19 +715,19 @@ mysqld_show_fields(THD *thd, TABLE_LIST *table_list,const char *wild,
uint col_access;
bool null_default_value=0;
- packet->length(0);
- net_store_data(packet,convert,field->field_name);
+ protocol->prepare_for_resend();
+ protocol->store(field->field_name);
field->sql_type(type);
- net_store_data(packet,convert,type.ptr(),type.length());
+ protocol->store(type.ptr(), type.length());
pos=(byte*) ((flags & NOT_NULL_FLAG) &&
field->type() != FIELD_TYPE_TIMESTAMP ?
"" : "YES");
- net_store_data(packet,convert,(const char*) pos);
+ protocol->store((const char*) pos);
pos=(byte*) ((field->flags & PRI_KEY_FLAG) ? "PRI" :
(field->flags & UNIQUE_KEY_FLAG) ? "UNI" :
(field->flags & MULTIPLE_KEY_FLAG) ? "MUL":"");
- net_store_data(packet,convert,(char*) pos);
+ protocol->store((char*) pos);
if (field->type() == FIELD_TYPE_TIMESTAMP ||
field->unireg_check == Field::NEXT_NUMBER)
@@ -735,17 +736,17 @@ mysqld_show_fields(THD *thd, TABLE_LIST *table_list,const char *wild,
{ // Not null by default
type.set(tmp,sizeof(tmp),default_charset_info);
field->val_str(&type,&type);
- net_store_data(packet,convert,type.ptr(),type.length());
+ protocol->store(type.ptr(),type.length());
}
else if (field->maybe_null() || null_default_value)
- net_store_null(packet); // Null as default
+ protocol->store_null(); // Null as default
else
- net_store_data(packet,convert,tmp,0);
+ protocol->store("",0); // empty string
char *end=tmp;
if (field->unireg_check == Field::NEXT_NUMBER)
end=strmov(tmp,"auto_increment");
- net_store_data(packet,convert,tmp,(uint) (end-tmp));
+ protocol->store(tmp,(uint) (end-tmp));
if (verbose)
{
@@ -760,12 +761,11 @@ mysqld_show_fields(THD *thd, TABLE_LIST *table_list,const char *wild,
end=strmov(end,grant_types.type_names[bitnr]);
}
}
- net_store_data(packet,convert, tmp+1,end == tmp ? 0 : (uint) (end-tmp-1));
- net_store_data(packet, field->comment.str,field->comment.length);
+ protocol->store(tmp+1,end == tmp ? 0 : (uint) (end-tmp-1));
+ protocol->store(field->comment.str, field->comment.length);
}
- if (SEND_ROW(thd, field_list.elements,
- (char *)packet->ptr(), packet->length()))
- DBUG_RETURN(-1);
+ if (protocol->write())
+ DBUG_RETURN(1);
}
}
}
@@ -778,7 +778,9 @@ int
mysqld_show_create(THD *thd, TABLE_LIST *table_list)
{
TABLE *table;
- CONVERT *convert=thd->variables.convert_set;
+ Protocol *protocol= thd->protocol;
+ char buff[2048];
+ String buffer(buff, sizeof(buff), system_charset_info);
DBUG_ENTER("mysqld_show_create");
DBUG_PRINT("enter",("db: %s table: %s",table_list->db,
table_list->real_name));
@@ -792,52 +794,18 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list)
List<Item> field_list;
field_list.push_back(new Item_empty_string("Table",NAME_LEN));
- field_list.push_back(new Item_empty_string("Create Table",1024));
+ field_list.push_back(new Item_empty_string("Create Table", MAX_BLOB_WIDTH));
- if (send_fields(thd,field_list,1))
+ if (protocol->send_fields(&field_list, 1))
+ DBUG_RETURN(1);
+ protocol->prepare_for_resend();
+ protocol->store(table->table_name);
+ buffer.length(0);
+ if (store_create_info(thd, table, &buffer))
+ DBUG_RETURN(-1);
+ protocol->store(buffer.ptr(), buffer.length());
+ if (protocol->write())
DBUG_RETURN(1);
-
- String *packet = &thd->packet;
- {
- packet->length(0);
- net_store_data(packet,convert, table->table_name);
- /*
- A hack - we need to reserve some space for the length before
- we know what it is - let's assume that the length of create table
- statement will fit into 3 bytes ( 16 MB max :-) )
- */
- ulong store_len_offset = packet->length();
- packet->length(store_len_offset + 4);
- if (store_create_info(thd, table, packet))
- DBUG_RETURN(-1);
- ulong create_len = packet->length() - store_len_offset - 4;
- /*
- Just in case somebody manages to create a table
- with *that* much stuff in the definition
- */
- if (create_len > 0x00ffffff) // better readable in HEX ...
- {
- /*
- Just in case somebody manages to create a table
- with *that* much stuff in the definition
- */
- DBUG_RETURN(1);
- }
-
- /*
- Now we have to store the length in three bytes, even if it would fit
- into fewer bytes, so we cannot use net_store_data() anymore,
- and do it ourselves
- */
- char* p = (char*)packet->ptr() + store_len_offset;
- *p++ = (char) 253; // The client the length is stored using 3-bytes
- int3store(p, create_len);
-
- // now we are in business :-)
- if (SEND_ROW(thd, field_list.elements,
- (char *)packet->ptr(), packet->length()))
- DBUG_RETURN(-1);
- }
send_eof(thd);
DBUG_RETURN(0);
}
@@ -846,18 +814,19 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list)
int
mysqld_show_logs(THD *thd)
{
+ List<Item> field_list;
+ Protocol *protocol= thd->protocol;
DBUG_ENTER("mysqld_show_logs");
- List<Item> field_list;
field_list.push_back(new Item_empty_string("File",FN_REFLEN));
field_list.push_back(new Item_empty_string("Type",10));
field_list.push_back(new Item_empty_string("Status",10));
- if (send_fields(thd,field_list,1))
+ if (protocol->send_fields(&field_list,1))
DBUG_RETURN(1);
#ifdef HAVE_BERKELEY_DB
- if (!berkeley_skip && berkeley_show_logs(thd))
+ if (!berkeley_skip && berkeley_show_logs(protocol))
DBUG_RETURN(-1);
#endif
@@ -871,7 +840,7 @@ mysqld_show_keys(THD *thd, TABLE_LIST *table_list)
{
TABLE *table;
char buff[256];
- CONVERT *convert=thd->variables.convert_set;
+ Protocol *protocol= thd->protocol;
DBUG_ENTER("mysqld_show_keys");
DBUG_PRINT("enter",("db: %s table: %s",table_list->db,
table_list->real_name));
@@ -885,15 +854,16 @@ mysqld_show_keys(THD *thd, TABLE_LIST *table_list)
List<Item> field_list;
Item *item;
field_list.push_back(new Item_empty_string("Table",NAME_LEN));
- field_list.push_back(new Item_int("Non_unique",0,1));
+ field_list.push_back(new Item_return_int("Non_unique",1, MYSQL_TYPE_TINY));
field_list.push_back(new Item_empty_string("Key_name",NAME_LEN));
- field_list.push_back(new Item_int("Seq_in_index",0,2));
+ field_list.push_back(new Item_return_int("Seq_in_index",2, MYSQL_TYPE_TINY));
field_list.push_back(new Item_empty_string("Column_name",NAME_LEN));
field_list.push_back(item=new Item_empty_string("Collation",1));
item->maybe_null=1;
field_list.push_back(item=new Item_int("Cardinality",0,21));
item->maybe_null=1;
- field_list.push_back(item=new Item_int("Sub_part",0,3));
+ field_list.push_back(item=new Item_return_int("Sub_part",3,
+ MYSQL_TYPE_TINY));
item->maybe_null=1;
field_list.push_back(item=new Item_empty_string("Packed",10));
item->maybe_null=1;
@@ -902,7 +872,7 @@ mysqld_show_keys(THD *thd, TABLE_LIST *table_list)
field_list.push_back(new Item_empty_string("Comment",255));
item->maybe_null=1;
- if (send_fields(thd,field_list,1))
+ if (protocol->send_fields(&field_list,1))
DBUG_RETURN(1);
String *packet= &thd->packet;
@@ -911,56 +881,49 @@ mysqld_show_keys(THD *thd, TABLE_LIST *table_list)
for (uint i=0 ; i < table->keys ; i++,key_info++)
{
KEY_PART_INFO *key_part= key_info->key_part;
- char *end;
+ const char *str;
for (uint j=0 ; j < key_info->key_parts ; j++,key_part++)
{
- packet->length(0);
- net_store_data(packet,convert,table->table_name);
- net_store_data(packet,convert,((key_info->flags & HA_NOSAME) ? "0" :"1"), 1);
- net_store_data(packet,convert,key_info->name);
- end=int10_to_str((long) (j+1),(char*) buff,10);
- net_store_data(packet,convert,buff,(uint) (end-buff));
- net_store_data(packet,convert,
- key_part->field ? key_part->field->field_name :
- "?unknown field?");
+ protocol->prepare_for_resend();
+ protocol->store(table->table_name);
+ protocol->store_tiny((longlong) ((key_info->flags & HA_NOSAME) ? 0 :1));
+ protocol->store(key_info->name);
+ protocol->store_tiny((longlong) (j+1));
+ str=(key_part->field ? key_part->field->field_name :
+ "?unknown field?");
+ protocol->store(str);
if (table->file->index_flags(i) & HA_READ_ORDER)
- net_store_data(packet,convert,
- ((key_part->key_part_flag & HA_REVERSE_SORT) ?
- "D" : "A"), 1);
+ protocol->store(((key_part->key_part_flag & HA_REVERSE_SORT) ?
+ "D" : "A"), 1);
else
- net_store_null(packet); /* purecov: inspected */
+ protocol->store_null(); /* purecov: inspected */
KEY *key=table->key_info+i;
if (key->rec_per_key[j])
{
ha_rows records=(table->file->records / key->rec_per_key[j]);
- end=longlong10_to_str((longlong) records, buff, 10);
- net_store_data(packet,convert,buff,(uint) (end-buff));
+ protocol->store((ulonglong) records);
}
else
- net_store_null(packet);
+ protocol->store_null();
/* Check if we have a key part that only uses part of the field */
if (!key_part->field ||
key_part->length !=
table->field[key_part->fieldnr-1]->key_length())
- {
- end=int10_to_str((long) key_part->length, buff,10); /* purecov: inspected */
- net_store_data(packet,convert,buff,(uint) (end-buff)); /* purecov: inspected */
- }
+ protocol->store_tiny((longlong) key_part->length);
else
- net_store_null(packet);
- net_store_null(packet); // No pack_information yet
+ protocol->store_null();
+ protocol->store_null(); // No pack_information yet
/* Null flag */
uint flags= key_part->field ? key_part->field->flags : 0;
char *pos=(char*) ((flags & NOT_NULL_FLAG) ? "" : "YES");
- net_store_data(packet,convert,(const char*) pos);
- net_store_data(packet,convert,table->file->index_type(i));
+ protocol->store((const char*) pos);
+ protocol->store(table->file->index_type(i));
/* Comment */
- net_store_data(packet,convert,"");
- if (SEND_ROW(thd, field_list.elements,
- (char *)packet->ptr(), packet->length()))
- DBUG_RETURN(-1);
+ protocol->store("", 0);
+ if (protocol->write())
+ DBUG_RETURN(1); /* purecov: inspected */
}
}
send_eof(thd);
@@ -995,7 +958,7 @@ mysqld_list_fields(THD *thd, TABLE_LIST *table_list, const char *wild)
field_list.push_back(new Item_field(field));
}
restore_record(table,2); // Get empty record
- if (send_fields(thd,field_list,2))
+ if (thd->protocol->send_fields(&field_list,2))
DBUG_VOID_RETURN;
#ifndef EMBEDDED_LIBRARY
VOID(net_flush(&thd->net));
@@ -1007,21 +970,21 @@ mysqld_list_fields(THD *thd, TABLE_LIST *table_list, const char *wild)
int
mysqld_dump_create_info(THD *thd, TABLE *table, int fd)
{
- CONVERT *convert=thd->variables.convert_set;
+ Protocol *protocol= thd->protocol;
+ String *packet= protocol->storage_packet();
DBUG_ENTER("mysqld_dump_create_info");
DBUG_PRINT("enter",("table: %s",table->real_name));
- String *packet = &thd->packet;
- packet->length(0);
- if (store_create_info(thd,table,packet))
+ protocol->prepare_for_resend();
+ if (store_create_info(thd, table, packet))
DBUG_RETURN(-1);
- if (convert)
- convert->convert((char*) packet->ptr(), packet->length());
#ifndef EMBEDDED_LIBRARY
+ if (protocol->convert)
+ protocol->convert->convert((char*) packet->ptr(), packet->length());
if (fd < 0)
{
- if (my_net_write(&thd->net, (char*)packet->ptr(), packet->length()))
+ if (protocol->write())
DBUG_RETURN(-1);
VOID(net_flush(&thd->net));
}
@@ -1285,21 +1248,21 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose)
I_List<thread_info> thread_infos;
ulong max_query_length= (verbose ? thd->variables.max_allowed_packet :
PROCESS_LIST_WIDTH);
- CONVERT *convert=thd->variables.convert_set;
+ Protocol *protocol= thd->protocol;
DBUG_ENTER("mysqld_list_processes");
- field_list.push_back(new Item_int("Id",0,7));
+ field_list.push_back(new Item_int("Id",0,11));
field_list.push_back(new Item_empty_string("User",16));
field_list.push_back(new Item_empty_string("Host",64));
field_list.push_back(field=new Item_empty_string("db",NAME_LEN));
field->maybe_null=1;
field_list.push_back(new Item_empty_string("Command",16));
- field_list.push_back(new Item_empty_string("Time",7));
+ field_list.push_back(new Item_return_int("Time",7, FIELD_TYPE_LONG));
field_list.push_back(field=new Item_empty_string("State",30));
field->maybe_null=1;
field_list.push_back(field=new Item_empty_string("Info",max_query_length));
field->maybe_null=1;
- if (send_fields(thd,field_list,1))
+ if (protocol->send_fields(&field_list,1))
DBUG_VOID_RETURN;
VOID(pthread_mutex_lock(&LOCK_thread_count)); // For unlink from list
@@ -1365,39 +1328,27 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose)
VOID(pthread_mutex_unlock(&LOCK_thread_count));
thread_info *thd_info;
- String *packet= &thd->packet;
+ time_t now= time(0);
while ((thd_info=thread_infos.get()))
{
char buff[20],*end;
- packet->length(0);
- end=int10_to_str((long) thd_info->thread_id, buff,10);
- net_store_data(packet,convert,buff,(uint) (end-buff));
- net_store_data(packet,convert,thd_info->user);
- net_store_data(packet,convert,thd_info->host);
- if (thd_info->db)
- net_store_data(packet,convert,thd_info->db);
- else
- net_store_null(packet);
+ protocol->prepare_for_resend();
+ protocol->store((ulonglong) thd_info->thread_id);
+ protocol->store(thd_info->user);
+ protocol->store(thd_info->host);
+ protocol->store(thd_info->db);
if (thd_info->proc_info)
- net_store_data(packet,convert,thd_info->proc_info);
+ protocol->store(thd_info->proc_info);
else
- net_store_data(packet,convert,command_name[thd_info->command]);
+ protocol->store(command_name[thd_info->command]);
if (thd_info->start_time)
- net_store_data(packet,
- (uint32) (time((time_t*) 0) - thd_info->start_time));
- else
- net_store_null(packet);
- if (thd_info->state_info)
- net_store_data(packet,convert,thd_info->state_info);
+ protocol->store((uint32) (now - thd_info->start_time));
else
- net_store_null(packet);
- if (thd_info->query)
- net_store_data(packet,convert,thd_info->query);
- else
- net_store_null(packet);
- if (SEND_ROW(thd, field_list.elements,
- (char *)packet->ptr(), packet->length()))
- break;
+ protocol->store_null();
+ protocol->store(thd_info->state_info);
+ protocol->store(thd_info->query);
+ if (protocol->write())
+ break; /* purecov: inspected */
}
send_eof(thd);
DBUG_VOID_RETURN;
@@ -1418,16 +1369,16 @@ int mysqld_show_charsets(THD *thd, const char *wild)
char buff[8192];
String packet2(buff,sizeof(buff),default_charset_info);
List<Item> field_list;
- CONVERT *convert=thd->variables.convert_set;
CHARSET_INFO **cs;
+ Protocol *protocol= thd->protocol;
DBUG_ENTER("mysqld_show_charsets");
field_list.push_back(new Item_empty_string("Name",30));
- field_list.push_back(new Item_int("Id",0,7));
- field_list.push_back(new Item_int("strx_maxlen",0,7));
- field_list.push_back(new Item_int("mb_maxlen",0,7));
+ field_list.push_back(new Item_return_int("Id",11, FIELD_TYPE_SHORT));
+ field_list.push_back(new Item_return_int("strx_maxlen",3, FIELD_TYPE_TINY));
+ field_list.push_back(new Item_return_int("mb_maxlen",3, FIELD_TYPE_TINY));
- if (send_fields(thd,field_list,1))
+ if (protocol->send_fields(&field_list, 1))
DBUG_RETURN(1);
for (cs=all_charsets ; cs < all_charsets+255 ; cs++ )
@@ -1437,14 +1388,13 @@ int mysqld_show_charsets(THD *thd, const char *wild)
if (!(wild && wild[0] &&
wild_case_compare(system_charset_info,cs[0]->name,wild)))
{
- packet2.length(0);
- net_store_data(&packet2,convert,cs[0]->name);
- net_store_data(&packet2,(uint32) cs[0]->number);
- net_store_data(&packet2,(uint32) cs[0]->strxfrm_multiply);
- net_store_data(&packet2,(uint32) (cs[0]->mbmaxlen));
-
- if (SEND_ROW(thd, field_list.elements, (char*) packet2.ptr(),packet2.length()))
- goto err;
+ protocol->prepare_for_resend();
+ protocol->store(cs[0]->name);
+ protocol->store_short((longlong) cs[0]->number);
+ protocol->store_tiny((longlong) cs[0]->strxfrm_multiply);
+ protocol->store_tiny((longlong) cs[0]->mbmaxlen);
+ if (protocol->write())
+ goto err;
}
}
send_eof(thd);
@@ -1458,15 +1408,14 @@ err:
int mysqld_show(THD *thd, const char *wild, show_var_st *variables,
enum enum_var_type value_type)
{
- char buff[8192];
- String packet2(buff,sizeof(buff), system_charset_info);
+ char buff[1024];
List<Item> field_list;
- CONVERT *convert=thd->variables.convert_set;
+ Protocol *protocol= thd->protocol;
DBUG_ENTER("mysqld_show");
field_list.push_back(new Item_empty_string("Variable_name",30));
field_list.push_back(new Item_empty_string("Value",256));
- if (send_fields(thd,field_list,1))
+ if (protocol->send_fields(&field_list,1))
DBUG_RETURN(1); /* purecov: inspected */
/* pthread_mutex_lock(&THR_LOCK_keycache); */
@@ -1476,236 +1425,251 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables,
if (!(wild && wild[0] && wild_case_compare(system_charset_info,
variables->name,wild)))
{
- packet2.length(0);
- net_store_data(&packet2,convert,variables->name);
+ protocol->prepare_for_resend();
+ protocol->store(variables->name);
SHOW_TYPE show_type=variables->type;
char *value=variables->value;
+ const char *pos, *end;
+ long nr;
+
if (show_type == SHOW_SYS)
{
show_type= ((sys_var*) value)->type();
value= (char*) ((sys_var*) value)->value_ptr(thd, value_type);
}
+ pos= end= buff;
switch (show_type) {
case SHOW_LONG:
case SHOW_LONG_CONST:
- net_store_data(&packet2,(uint32) *(ulong*) value);
+ end= int10_to_str(*(long*) value, buff, 10);
break;
case SHOW_LONGLONG:
- net_store_data(&packet2,(longlong) *(longlong*) value);
+ end= longlong10_to_str(*(longlong*) value, buff, 10);
break;
case SHOW_BOOL:
- net_store_data(&packet2,(ulong) *(bool*) value ? "ON" : "OFF");
+ end= strmov(buff, *(bool*) value ? "ON" : "OFF");
break;
case SHOW_MY_BOOL:
- net_store_data(&packet2,(ulong) *(my_bool*) value ? "ON" : "OFF");
+ end= strmov(buff, *(my_bool*) value ? "ON" : "OFF");
break;
case SHOW_INT_CONST:
case SHOW_INT:
- net_store_data(&packet2,(uint32) *(int*) value);
+ end= int10_to_str((long) *(uint32*) value, buff, 10);
break;
case SHOW_HAVE:
{
SHOW_COMP_OPTION tmp= *(SHOW_COMP_OPTION*) value;
- net_store_data(&packet2, show_comp_option_name[(int) tmp]);
+ pos= show_comp_option_name[(int) tmp];
+ end= strend(pos);
break;
}
case SHOW_CHAR:
- net_store_data(&packet2,convert, value);
+ pos= value;
+ end= strend(pos);
break;
case SHOW_STARTTIME:
- net_store_data(&packet2,(uint32) (thd->query_start() - start_time));
+ nr= (long) (thd->query_start() - start_time);
+ end= int10_to_str(nr, buff, 10);
break;
case SHOW_QUESTION:
- net_store_data(&packet2,(uint32) thd->query_id);
+ end= int10_to_str((long) thd->query_id, buff, 10);
break;
#ifndef EMBEDDED_LIBRARY
case SHOW_RPL_STATUS:
- net_store_data(&packet2, rpl_status_type[(int)rpl_status]);
+ end= int10_to_str((long) rpl_status_type[(int)rpl_status], buff, 10);
break;
case SHOW_SLAVE_RUNNING:
{
LOCK_ACTIVE_MI;
- net_store_data(&packet2, (active_mi->slave_running &&
- active_mi->rli.slave_running)
- ? "ON" : "OFF");
+ end= strmov(buff, (active_mi->slave_running &&
+ active_mi->rli.slave_running) ? "ON" : "OFF");
UNLOCK_ACTIVE_MI;
break;
}
#endif /* EMBEDDED_LIBRARY */
case SHOW_OPENTABLES:
- net_store_data(&packet2,(uint32) cached_tables());
+ end= int10_to_str((long) cached_tables(), buff, 10);
break;
case SHOW_CHAR_PTR:
{
- value= *(char**) value;
- net_store_data(&packet2,convert, value ? value : "");
+ if (!(pos= *(char**) value))
+ pos= "";
+ end= strend(pos);
break;
}
#ifdef HAVE_OPENSSL
/* First group - functions relying on CTX */
case SHOW_SSL_CTX_SESS_ACCEPT:
- net_store_data(&packet2,(uint32)
- (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_accept(ssl_acceptor_fd->ssl_context_)));
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_accept(ssl_acceptor_fd->
+ ssl_context_)),
+ buff, 10);
break;
case SHOW_SSL_CTX_SESS_ACCEPT_GOOD:
- net_store_data(&packet2,(uint32)
- (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_accept_good(ssl_acceptor_fd->ssl_context_)));
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_accept_good(ssl_acceptor_fd->
+ ssl_context_)),
+ buff, 10);
break;
case SHOW_SSL_CTX_SESS_CONNECT_GOOD:
- net_store_data(&packet2,(uint32)
- (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_connect_good(ssl_acceptor_fd->ssl_context_)));
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_connect_good(ssl_acceptor_fd->
+ ssl_context_)),
+ buff, 10);
break;
case SHOW_SSL_CTX_SESS_ACCEPT_RENEGOTIATE:
- net_store_data(&packet2,(uint32)
- (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_accept_renegotiate(ssl_acceptor_fd->ssl_context_)));
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_accept_renegotiate(ssl_acceptor_fd->ssl_context_)),
+ buff, 10);
break;
case SHOW_SSL_CTX_SESS_CONNECT_RENEGOTIATE:
- net_store_data(&packet2,(uint32)
- (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_connect_renegotiate(ssl_acceptor_fd->ssl_context_)));
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_connect_renegotiate(ssl_acceptor_fd-> ssl_context_)),
+ buff, 10);
break;
case SHOW_SSL_CTX_SESS_CB_HITS:
- net_store_data(&packet2,(uint32)
- (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_cb_hits(ssl_acceptor_fd->ssl_context_)));
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_cb_hits(ssl_acceptor_fd->
+ ssl_context_)),
+ buff, 10);
break;
case SHOW_SSL_CTX_SESS_HITS:
- net_store_data(&packet2,(uint32)
- (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_hits(ssl_acceptor_fd->ssl_context_)));
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_hits(ssl_acceptor_fd->
+ ssl_context_)),
+ buff, 10);
break;
case SHOW_SSL_CTX_SESS_CACHE_FULL:
- net_store_data(&packet2,(uint32)
- (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_cache_full(ssl_acceptor_fd->ssl_context_)));
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_cache_full(ssl_acceptor_fd->
+ ssl_context_)),
+ buff, 10);
break;
case SHOW_SSL_CTX_SESS_MISSES:
- net_store_data(&packet2,(uint32)
- (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_misses(ssl_acceptor_fd->ssl_context_)));
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_misses(ssl_acceptor_fd->
+ ssl_context_)),
+ buff, 10);
break;
case SHOW_SSL_CTX_SESS_TIMEOUTS:
- net_store_data(&packet2,(uint32)
- (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_timeouts(ssl_acceptor_fd->ssl_context_)));
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_timeouts(ssl_acceptor_fd->ssl_context_)),
+ buff,10);
break;
case SHOW_SSL_CTX_SESS_NUMBER:
- net_store_data(&packet2,(uint32)
- (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_number(ssl_acceptor_fd->ssl_context_)));
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_number(ssl_acceptor_fd->ssl_context_)),
+ buff,10);
break;
case SHOW_SSL_CTX_SESS_CONNECT:
- net_store_data(&packet2,(uint32)
- (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_connect(ssl_acceptor_fd->ssl_context_)));
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_connect(ssl_acceptor_fd->ssl_context_)),
+ buff,10);
break;
case SHOW_SSL_CTX_SESS_GET_CACHE_SIZE:
- net_store_data(&packet2,(uint32)
- (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_get_cache_size(ssl_acceptor_fd->ssl_context_)));
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_get_cache_size(ssl_acceptor_fd->ssl_context_)),
+ buff,10);
break;
case SHOW_SSL_CTX_GET_VERIFY_MODE:
- net_store_data(&packet2,(uint32)
- (!ssl_acceptor_fd ? 0 :
- SSL_CTX_get_verify_mode(ssl_acceptor_fd->ssl_context_)));
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_get_verify_mode(ssl_acceptor_fd->ssl_context_)),
+ buff,10);
break;
case SHOW_SSL_CTX_GET_VERIFY_DEPTH:
- net_store_data(&packet2,(uint32)
- (!ssl_acceptor_fd ? 0 :
- SSL_CTX_get_verify_depth(ssl_acceptor_fd->ssl_context_)));
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_get_verify_depth(ssl_acceptor_fd->ssl_context_)),
+ buff,10);
break;
case SHOW_SSL_CTX_GET_SESSION_CACHE_MODE:
if (!ssl_acceptor_fd)
{
- net_store_data(&packet2,"NONE" );
+ pos= "NONE";
+ end= pos+4;
break;
}
switch (SSL_CTX_get_session_cache_mode(ssl_acceptor_fd->ssl_context_))
{
case SSL_SESS_CACHE_OFF:
- net_store_data(&packet2,"OFF" );
+ pos= "OFF";
break;
case SSL_SESS_CACHE_CLIENT:
- net_store_data(&packet2,"CLIENT" );
+ pos= "CLIENT";
break;
case SSL_SESS_CACHE_SERVER:
- net_store_data(&packet2,"SERVER" );
+ pos= "SERVER";
break;
case SSL_SESS_CACHE_BOTH:
- net_store_data(&packet2,"BOTH" );
+ pos= "BOTH";
break;
case SSL_SESS_CACHE_NO_AUTO_CLEAR:
- net_store_data(&packet2,"NO_AUTO_CLEAR" );
+ pos= "NO_AUTO_CLEAR";
break;
case SSL_SESS_CACHE_NO_INTERNAL_LOOKUP:
- net_store_data(&packet2,"NO_INTERNAL_LOOKUP" );
+ pos= "NO_INTERNAL_LOOKUP";
break;
default:
- net_store_data(&packet2,"Unknown");
+ pos= "Unknown";
break;
}
+ pos= strend(pos);
break;
/* First group - functions relying on SSL */
case SHOW_SSL_GET_VERSION:
- net_store_data(&packet2, thd->net.vio->ssl_ ?
- SSL_get_version(thd->net.vio->ssl_) : "");
+ pos= thd->net.vio->ssl_ ? SSL_get_version(thd->net.vio->ssl_) : "";
+ end= strend(pos);
break;
case SHOW_SSL_SESSION_REUSED:
- net_store_data(&packet2,(uint32) (thd->net.vio->ssl_ ?
- SSL_session_reused(thd->net.vio->ssl_) : 0));
+ end= int10_to_str((long) (thd->net.vio->ssl_ ?
+ SSL_session_reused(thd->net.vio->ssl_):
+ 0), buff, 10);
break;
case SHOW_SSL_GET_DEFAULT_TIMEOUT:
- net_store_data(&packet2,(uint32) (thd->net.vio->ssl_ ?
- SSL_get_default_timeout(thd->net.vio->ssl_):0));
+ end= int10_to_str((long) (thd->net.vio->ssl_ ?
+ SSL_get_default_timeout(thd->net.vio->ssl_):
+ 0), buff, 10);
break;
case SHOW_SSL_GET_VERIFY_MODE:
- net_store_data(&packet2,(uint32) (thd->net.vio->ssl_ ?
- SSL_get_verify_mode(thd->net.vio->ssl_):0));
+ end= int10_to_str((long) (thd->net.vio->ssl_ ?
+ SSL_get_verify_mode(thd->net.vio->ssl_):
+ 0), buff, 10);
break;
case SHOW_SSL_GET_VERIFY_DEPTH:
- net_store_data(&packet2,(uint32) (thd->net.vio->ssl_ ?
- SSL_get_verify_depth(thd->net.vio->ssl_):0));
+ end= int10_to_str((long) (thd->net.vio->ssl_ ?
+ SSL_get_verify_depth(thd->net.vio->ssl_):
+ 0), buff, 10);
break;
case SHOW_SSL_GET_CIPHER:
- net_store_data(&packet2, thd->net.vio->ssl_ ?
- SSL_get_cipher(thd->net.vio->ssl_) : "");
+ pos= thd->net.vio->ssl_ ? SSL_get_cipher(thd->net.vio->ssl_) : "";
+ end= strend(pos);
break;
case SHOW_SSL_GET_CIPHER_LIST:
if (thd->net.vio->ssl_)
{
- char buf[1024], *pos;
- pos=buf;
+ char *to= buff;
for (int i=0 ; i++ ;)
{
- const char *p=SSL_get_cipher_list(thd->net.vio->ssl_,i);
+ const char *p= SSL_get_cipher_list(thd->net.vio->ssl_,i);
if (p == NULL)
break;
- pos=strmov(pos, p);
- *pos++= ':';
+ to= strmov(to, p);
+ *to++= ':';
}
- if (pos != buf)
- pos--; // Remove last ':'
- *pos=0;
- net_store_data(&packet2, buf);
+ if (to != buff)
+ to--; // Remove last ':'
+ end= to;
}
- else
- net_store_data(&packet2, "");
break;
#endif /* HAVE_OPENSSL */
case SHOW_UNDEF: // Show never happen
case SHOW_SYS:
- net_store_data(&packet2, ""); // Safety
- break;
+ break; // Return empty string
}
- if (SEND_ROW(thd, field_list.elements,
- (char *)packet2.ptr(), packet2.length()))
- goto err;
+ if (protocol->store(pos, (uint32) (end - pos)) ||
+ protocol->write())
+ goto err; /* purecov: inspected */
}
}
pthread_mutex_unlock(&LOCK_status);
diff --git a/sql/sql_string.h b/sql/sql_string.h
index dde67b11d50..d7447dd6ed6 100644
--- a/sql/sql_string.h
+++ b/sql/sql_string.h
@@ -255,4 +255,29 @@ public:
void qs_append(double d);
void qs_append(double *d);
void qs_append(const char &c);
+
+ /* 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;
+ }
};
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 3c643584785..49e84db62c9 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -1027,19 +1027,18 @@ bool close_cached_table(THD *thd,TABLE *table)
DBUG_RETURN(result);
}
-static int send_check_errmsg(THD* thd, TABLE_LIST* table,
+static int send_check_errmsg(THD *thd, TABLE_LIST* table,
const char* operator_name, const char* errmsg)
{
-
- String* packet = &thd->packet;
- packet->length(0);
- net_store_data(packet, table->alias);
- net_store_data(packet, (char*)operator_name);
- net_store_data(packet, "error");
- net_store_data(packet, errmsg);
+ Protocol *protocol= thd->protocol;
+ protocol->prepare_for_resend();
+ protocol->store(table->alias);
+ protocol->store((char*) operator_name);
+ protocol->store("error", 5);
+ protocol->store(errmsg);
thd->net.last_error[0]=0;
- if (SEND_ROW(thd, 4, (char*) thd->packet.ptr(), packet->length()))
+ if (protocol->write())
return -1;
return 1;
}
@@ -1185,8 +1184,8 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
{
TABLE_LIST *table;
List<Item> field_list;
- Item* item;
- String* packet = &thd->packet;
+ Item *item;
+ Protocol *protocol= thd->protocol;
DBUG_ENTER("mysql_admin_table");
field_list.push_back(item = new Item_empty_string("Table", NAME_LEN*2));
@@ -1197,7 +1196,7 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
item->maybe_null = 1;
field_list.push_back(item = new Item_empty_string("Msg_text", 255));
item->maybe_null = 1;
- if (send_fields(thd, field_list, 1))
+ if (protocol->send_fields(&field_list, 1))
DBUG_RETURN(-1);
for (table = tables; table; table = table->next)
@@ -1213,7 +1212,8 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
thd->net.last_errno= 0; // these errors shouldn't get client
#endif
thd->open_options&= ~extra_open_options;
- packet->length(0);
+ protocol->prepare_for_resend();
+
if (prepare_func)
{
switch ((*prepare_func)(thd, table, check_opt)) {
@@ -1226,30 +1226,30 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
if (!table->table)
{
const char *err_msg;
- net_store_data(packet, table_name);
- net_store_data(packet, operator_name);
- net_store_data(packet, "error");
+ protocol->prepare_for_resend();
+ protocol->store(table_name);
+ protocol->store(operator_name);
+ protocol->store("error",5);
if (!(err_msg=thd->net.last_error))
err_msg=ER(ER_CHECK_NO_SUCH_TABLE);
- net_store_data(packet, err_msg);
+ protocol->store(err_msg);
thd->net.last_error[0]=0;
- if (SEND_ROW(thd, field_list.elements, (char*) thd->packet.ptr(),
- packet->length()))
+ if (protocol->write())
goto err;
continue;
}
if ((table->table->db_stat & HA_READ_ONLY) && open_for_modify)
{
char buff[FN_REFLEN + MYSQL_ERRMSG_SIZE];
- net_store_data(packet, table_name);
- net_store_data(packet, operator_name);
- net_store_data(packet, "error");
+ protocol->prepare_for_resend();
+ protocol->store(table_name);
+ protocol->store(operator_name);
+ protocol->store("error", 5);
sprintf(buff, ER(ER_OPEN_AS_READONLY), table_name);
- net_store_data(packet, buff);
+ protocol->store(buff);
close_thread_tables(thd);
table->table=0; // For query cache
- if (SEND_ROW(thd, field_list.elements, (char*) thd->packet.ptr(),
- packet->length()))
+ if (protocol->write())
goto err;
continue;
}
@@ -1280,50 +1280,50 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
#ifdef EMBEDDED_LIBRARY
thd->net.last_errno= 0; // these errors shouldn't get client
#endif
- packet->length(0);
- net_store_data(packet, table_name);
- net_store_data(packet, operator_name);
+ protocol->prepare_for_resend();
+ protocol->store(table_name);
+ protocol->store(operator_name);
switch (result_code) {
case HA_ADMIN_NOT_IMPLEMENTED:
{
char buf[ERRMSGSIZE+20];
- my_snprintf(buf, ERRMSGSIZE,
- ER(ER_CHECK_NOT_IMPLEMENTED), operator_name);
- net_store_data(packet, "error");
- net_store_data(packet, buf);
+ uint length=my_snprintf(buf, ERRMSGSIZE,
+ ER(ER_CHECK_NOT_IMPLEMENTED), operator_name);
+ protocol->store("error", 5);
+ protocol->store(buf, length);
}
break;
case HA_ADMIN_OK:
- net_store_data(packet, "status");
- net_store_data(packet, "OK");
+ protocol->store("status", 6);
+ protocol->store("OK",2);
break;
case HA_ADMIN_FAILED:
- net_store_data(packet, "status");
- net_store_data(packet, "Operation failed");
+ protocol->store("status", 6);
+ protocol->store("Operation failed",16);
break;
case HA_ADMIN_ALREADY_DONE:
- net_store_data(packet, "status");
- net_store_data(packet, "Table is already up to date");
+ protocol->store("status", 6);
+ protocol->store("Table is already up to date", 27);
break;
case HA_ADMIN_CORRUPT:
- net_store_data(packet, "error");
- net_store_data(packet, "Corrupt");
+ protocol->store("error", 5);
+ protocol->store("Corrupt", 8);
fatal_error=1;
break;
case HA_ADMIN_INVALID:
- net_store_data(packet, "error");
- net_store_data(packet, "Invalid argument");
+ protocol->store("error", 5);
+ protocol->store("Invalid argument",16);
break;
default: // Probably HA_ADMIN_INTERNAL_ERROR
- net_store_data(packet, "error");
- net_store_data(packet, "Unknown - internal error during operation");
+ protocol->store("error", 5);
+ protocol->store("Unknown - internal error during operation", 41);
fatal_error=1;
break;
}
@@ -1340,8 +1340,7 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
}
close_thread_tables(thd);
table->table=0; // For query cache
- if (SEND_ROW(thd, field_list.elements,
- (char *)thd->packet.ptr(), thd->packet.length()))
+ if (protocol->write())
goto err;
}
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index 6e8c2ebdb5c..10175bfe345 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -24,10 +24,9 @@
#include "mysql_priv.h"
#include "sql_select.h"
-int mysql_union(THD *thd, LEX *lex, select_result *result)
+int mysql_union(THD *thd, LEX *lex, select_result *result,SELECT_LEX_UNIT *unit)
{
DBUG_ENTER("mysql_union");
- SELECT_LEX_UNIT *unit= &lex->unit;
int res= 0;
if (!(res= unit->prepare(thd, result)))
res= unit->exec();
@@ -125,6 +124,7 @@ int st_select_lex_unit::prepare(THD *thd, select_result *result)
SELECT_LEX_NODE *lex_select_save= thd->lex.current_select;
SELECT_LEX *sl;
+ thd->lex.current_select=first_select();
/* Global option */
if (((void*)(global_parameters)) == ((void*)this))
{
@@ -216,7 +216,7 @@ int st_select_lex_unit::exec()
if (optimized && item && item->assigned())
{
item->assigned(0); // We will reinit & rexecute unit
- item->assign_null();
+ item->reset();
table->file->delete_all_rows();
}
for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index ed8e8f0fb51..8e947ec7587 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -100,6 +100,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token DIV_SYM
%token EQ
%token EQUAL_SYM
+%token SOUNDS_SYM
%token GE
%token GT_SYM
%token LE
@@ -158,6 +159,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token SQL_THREAD
%token START_SYM
%token STD_SYM
+%token VARIANCE_SYM
%token STOP_SYM
%token SUM_SYM
%token SUPER_SYM
@@ -1833,6 +1835,7 @@ expr_expr:
| expr OR expr { $$= new Item_cond_or($1,$3); }
| expr XOR expr { $$= new Item_cond_xor($1,$3); }
| expr AND expr { $$= new Item_cond_and($1,$3); }
+ | expr SOUNDS_SYM LIKE expr { $$= Item_bool_func2::eq_creator(new Item_func_soundex($1), new Item_func_soundex($4));}
| expr LIKE simple_expr opt_escape { $$= new Item_func_like($1,$3,$4); }
| expr NOT LIKE simple_expr opt_escape { $$= new Item_func_not(new Item_func_like($1,$4,$5));}
| expr REGEXP expr { $$= new Item_func_regex($1,$3); }
@@ -1879,6 +1882,7 @@ no_in_expr:
| no_in_expr OR expr { $$= new Item_cond_or($1,$3); }
| no_in_expr XOR expr { $$= new Item_cond_xor($1,$3); }
| no_in_expr AND expr { $$= new Item_cond_and($1,$3); }
+ | no_in_expr SOUNDS_SYM LIKE expr { $$= Item_bool_func2::eq_creator(new Item_func_soundex($1), new Item_func_soundex($4));}
| no_in_expr LIKE simple_expr opt_escape { $$= new Item_func_like($1,$3,$4); }
| no_in_expr NOT LIKE simple_expr opt_escape { $$= new Item_func_not(new Item_func_like($1,$4,$5)); }
| no_in_expr REGEXP expr { $$= new Item_func_regex($1,$3); }
@@ -1933,6 +1937,7 @@ no_and_expr:
| no_and_expr OR_OR_CONCAT expr { $$= or_or_concat(YYTHD, $1,$3); }
| no_and_expr OR expr { $$= new Item_cond_or($1,$3); }
| no_and_expr XOR expr { $$= new Item_cond_xor($1,$3); }
+ | no_and_expr SOUNDS_SYM LIKE expr { $$= Item_bool_func2::eq_creator(new Item_func_soundex($1), new Item_func_soundex($4));}
| no_and_expr LIKE simple_expr opt_escape { $$= new Item_func_like($1,$3,$4); }
| no_and_expr NOT LIKE simple_expr opt_escape { $$= new Item_func_not(new Item_func_like($1,$4,$5)); }
| no_and_expr REGEXP expr { $$= new Item_func_regex($1,$3); }
@@ -2335,6 +2340,8 @@ sum_expr:
{ $$=new Item_sum_max($3); }
| STD_SYM '(' in_sum_expr ')'
{ $$=new Item_sum_std($3); }
+ | VARIANCE_SYM '(' in_sum_expr ')'
+ { $$=new Item_sum_variance($3); }
| SUM_SYM '(' in_sum_expr ')'
{ $$=new Item_sum_sum($3); };
@@ -2504,7 +2511,7 @@ select_derived:
mysql_init_select(lex);
lex->current_select->linkage= DERIVED_TABLE_TYPE;
}
- select_options select_item_list opt_select_from
+ select_options select_item_list opt_select_from union_opt
;
opt_outer:
@@ -3870,6 +3877,7 @@ keyword:
| VALUE_SYM {}
| WORK_SYM {}
| YEAR_SYM {}
+ | SOUNDS_SYM {}
;
/* Option functions */
diff --git a/sql/structs.h b/sql/structs.h
index 7873de4db63..604be6fcc6e 100644
--- a/sql/structs.h
+++ b/sql/structs.h
@@ -113,7 +113,8 @@ enum timestamp_type { TIMESTAMP_NONE, TIMESTAMP_DATE, TIMESTAMP_FULL,
TIMESTAMP_TIME };
typedef struct st_time {
- uint year,month,day,hour,minute,second,second_part;
+ uint year,month,day,hour,minute,second;
+ ulong second_part;
bool neg;
timestamp_type time_type;
} TIME;
diff --git a/sql/time.cc b/sql/time.cc
index 0811b896bfc..282075df9eb 100644
--- a/sql/time.cc
+++ b/sql/time.cc
@@ -724,3 +724,20 @@ bool str_to_time(const char *str,uint length,TIME *l_time)
}
return 0;
}
+
+
+/*
+ Convert a system time structure to TIME
+*/
+
+void localtime_to_TIME(TIME *to, struct tm *from)
+{
+ to->neg=0;
+ to->second_part=0;
+ to->year= (int) ((from->tm_year+1900) % 10000);
+ to->month= (int) from->tm_mon+1;
+ to->day= (int) from->tm_mday;
+ to->hour= (int) from->tm_hour;
+ to->minute= (int) from->tm_min;
+ to->second= (int) from->tm_sec;
+}