summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libmysql/libmysql.c4
-rw-r--r--libmysqld/Makefile.am2
-rw-r--r--mysql-test/r/case.result4
-rw-r--r--mysql-test/r/cast.result4
-rw-r--r--sql/Makefile.am2
-rw-r--r--sql/field.cc103
-rw-r--r--sql/field.h37
-rw-r--r--sql/ha_berkeley.cc38
-rw-r--r--sql/ha_berkeley.h2
-rw-r--r--sql/ha_innodb.cc22
-rw-r--r--sql/ha_myisam.cc23
-rw-r--r--sql/item.cc176
-rw-r--r--sql/item.h72
-rw-r--r--sql/item_func.cc2
-rw-r--r--sql/item_func.h5
-rw-r--r--sql/item_subselect.cc14
-rw-r--r--sql/item_subselect.h1
-rw-r--r--sql/item_sum.cc27
-rw-r--r--sql/item_sum.h6
-rw-r--r--sql/item_timefunc.h35
-rw-r--r--sql/log_event.cc76
-rw-r--r--sql/log_event.h26
-rw-r--r--sql/mysql_priv.h27
-rw-r--r--sql/net_pkg.cc492
-rw-r--r--sql/opt_range.cc45
-rw-r--r--sql/procedure.h6
-rw-r--r--sql/protocol.cc983
-rw-r--r--sql/protocol.h131
-rw-r--r--sql/repl_failsafe.cc48
-rw-r--r--sql/slave.cc122
-rw-r--r--sql/sql_acl.cc27
-rw-r--r--sql/sql_base.cc244
-rw-r--r--sql/sql_class.cc43
-rw-r--r--sql/sql_class.h3
-rw-r--r--sql/sql_db.cc17
-rw-r--r--sql/sql_error.cc16
-rw-r--r--sql/sql_handler.cc33
-rw-r--r--sql/sql_help.cc72
-rw-r--r--sql/sql_parse.cc2
-rw-r--r--sql/sql_prepare.cc5
-rw-r--r--sql/sql_repl.cc45
-rw-r--r--sql/sql_select.cc12
-rw-r--r--sql/sql_show.cc642
-rw-r--r--sql/sql_string.h25
-rw-r--r--sql/sql_table.cc92
-rw-r--r--sql/structs.h3
-rw-r--r--sql/time.cc17
-rw-r--r--tests/fork_big2.pl705
48 files changed, 2878 insertions, 1660 deletions
diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c
index ad97d5b1442..d73b28863ba 100644
--- a/libmysql/libmysql.c
+++ b/libmysql/libmysql.c
@@ -4502,8 +4502,8 @@ stmt_fetch_row(MYSQL_STMT *stmt, uchar **row)
MYSQL_BIND *bind, *end;
uchar *null_ptr= (uchar*) *row, bit;
- *row+= (stmt->field_count+7)/8;
- bit=1;
+ row+= (stmt->field_count+9)/8;
+ bit= 4; /* First 2 bits are reserved */
/* Copy complete row to application buffers */
for (bind= stmt->bind, end= (MYSQL_BIND *) bind + stmt->field_count;
diff --git a/libmysqld/Makefile.am b/libmysqld/Makefile.am
index ea47126a4d5..daf65cb2f80 100644
--- a/libmysqld/Makefile.am
+++ b/libmysqld/Makefile.am
@@ -44,7 +44,7 @@ sqlsources = convert.cc derror.cc field.cc field_conv.cc filesort.cc \
item_func.cc item_strfunc.cc item_sum.cc item_timefunc.cc \
item_uniq.cc item_subselect.cc item_row.cc\
key.cc lock.cc log.cc log_event.cc mf_iocache.cc\
- mini_client.cc net_pkg.cc net_serv.cc opt_ft.cc opt_range.cc \
+ mini_client.cc protocol.cc net_serv.cc opt_ft.cc opt_range.cc \
opt_sum.cc procedure.cc records.cc sql_acl.cc \
repl_failsafe.cc slave.cc sql_load.cc sql_olap.cc \
sql_analyse.cc sql_base.cc sql_cache.cc sql_class.cc \
diff --git a/mysql-test/r/case.result b/mysql-test/r/case.result
index ec37c9a5763..18241a8fcc1 100644
--- a/mysql-test/r/case.result
+++ b/mysql-test/r/case.result
@@ -10,10 +10,10 @@ CASE "c" when "a" then 1 when "b" then 2 ELSE 3 END
3
select CASE BINARY "b" when "a" then 1 when "B" then 2 WHEN "b" then "ok" END;
CASE BINARY "b" when "a" then 1 when "B" then 2 WHEN "b" then "ok" END
-ok
+0
select CASE "b" when "a" then 1 when binary "B" then 2 WHEN "b" then "ok" END;
CASE "b" when "a" then 1 when binary "B" then 2 WHEN "b" then "ok" END
-ok
+0
select CASE concat("a","b") when concat("ab","") then "a" when "b" then "b" end;
CASE concat("a","b") when concat("ab","") then "a" when "b" then "b" end
a
diff --git a/mysql-test/r/cast.result b/mysql-test/r/cast.result
index 572b32c171c..2309de2354b 100644
--- a/mysql-test/r/cast.result
+++ b/mysql-test/r/cast.result
@@ -24,10 +24,10 @@ cast("A" as binary) = "a" cast(BINARY "a" as CHAR) = "A"
0 1
select cast("2001-1-1" as DATE), cast("2001-1-1" as DATETIME);
cast("2001-1-1" as DATE) cast("2001-1-1" as DATETIME)
-2001-1-1 2001-1-1
+2001-01-01 2001-01-01 00:00:00
select cast("1:2:3" as TIME);
cast("1:2:3" as TIME)
-1:2:3
+1:02:03
select cast("2001-1-1" as date) = "2001-01-01";
cast("2001-1-1" as date) = "2001-01-01"
0
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 bc795e3d5cb..a412c2cb146 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -192,17 +192,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());
}
@@ -1066,6 +1061,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)
{
@@ -1277,6 +1276,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)))
{
@@ -1302,6 +1302,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;
@@ -1526,6 +1532,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;
@@ -1759,6 +1771,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;
@@ -1971,6 +1988,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;
@@ -2285,6 +2308,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)
@@ -2482,6 +2511,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)
{
@@ -2804,6 +2838,7 @@ String *Field_timestamp::val_str(String *val_buffer,
return val_buffer;
}
+
bool Field_timestamp::get_date(TIME *ltime, bool fuzzydate)
{
long temp;
@@ -2843,6 +2878,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;
@@ -2861,6 +2905,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
@@ -3051,6 +3096,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;
@@ -3946,19 +4002,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;
}
@@ -4155,6 +4207,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
@@ -4422,7 +4496,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
diff --git a/sql/field.h b/sql/field.h
index 16929a363dd..49f75a3d471 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); }
@@ -567,6 +576,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; }
@@ -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);
@@ -957,6 +977,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/ha_berkeley.cc b/sql/ha_berkeley.cc
index 8edb63b23d6..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,18 +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 (my_net_write(&thd->net,(char*) packet->ptr(),packet->length()))
+ if (protocol->write())
{
error=1;
goto err;
@@ -2065,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;
@@ -2074,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 14810bada31..8f933085066 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -3922,9 +3922,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) {
@@ -3945,22 +3944,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 (my_net_write(&thd->net, (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 ae71e362875..67fddf34d5c 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));
@@ -67,19 +65,20 @@ static void mi_check_print_msg(MI_CHECK *param, const char* msg_type,
sql_print_error(msgbuf);
return;
}
- 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 (my_net_write(&thd->net, (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 5e74820a3f8..2d90db0cc5d 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
@@ -372,12 +373,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) {
@@ -630,66 +625,26 @@ 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)
-{
- init_make_field(tmp_field,FIELD_TYPE_LONGLONG);
- tmp_field->flags|= UNSIGNED_FLAG;
- unsigned_flag=1;
-}
-
-void Item_real::make_field(Send_field *tmp_field)
-{
- init_make_field(tmp_field,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)
+void Item::make_field(Send_field *tmp_field)
{
- init_make_field(tmp_field,FIELD_TYPE_DATETIME);
+ init_make_field(tmp_field, field_type());
}
-
-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)
+enum_field_types Item::field_type() const
{
- init_make_field(tmp_field, ((result_type() == STRING_RESULT) ?
- FIELD_TYPE_VAR_STRING :
- (result_type() == INT_RESULT) ?
- FIELD_TYPE_LONGLONG : FIELD_TYPE_DOUBLE));
+ return ((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)
+/* 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
}
-void Item_std_field::make_field(Send_field *tmp_field)
-{
- init_make_field(tmp_field,FIELD_TYPE_DOUBLE);
-}
/*
** Set a field:s value from a item
@@ -897,30 +852,109 @@ 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:
+ DBUG_ASSERT(1);
+ /* If not assert on, send as a string */
+ 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_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:
+ {
+ 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);
}
/*
diff --git a/sql/item.h b/sql/item.h
index 4dff0591c09..63890ea3f64 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -19,6 +19,7 @@
#pragma interface /* gcc class implementation */
#endif
+class Protocol;
struct st_table_list;
void item_init(void); /* Init item functions */
@@ -53,20 +54,21 @@ 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);
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(); }
@@ -117,10 +119,10 @@ 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); }
};
@@ -189,12 +191,9 @@ public:
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);
- }
- void make_field(Send_field *field);
+ bool send(Protocol *protocol, String *str_arg);
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;
@@ -202,6 +201,10 @@ public:
{
return field->result_type();
}
+ enum_field_types field_type()
+ {
+ 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);
@@ -219,12 +222,17 @@ 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);
+ 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 send(Protocol *protocol, String *str);
bool basic_const_item() const { return 1; }
Item *new_item() { return new Item_null(name); }
bool is_null() { return 1; }
@@ -251,7 +259,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);
@@ -265,6 +272,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); }
};
@@ -285,11 +293,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); }
@@ -305,8 +313,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);
};
@@ -332,10 +345,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); }
};
@@ -380,8 +393,8 @@ 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); }
@@ -398,7 +411,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();
@@ -418,7 +430,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
@@ -428,6 +440,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:
@@ -438,8 +464,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; }
};
@@ -494,13 +520,14 @@ public:
{
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); }
void make_field(Send_field *field) { (*ref)->make_field(field); }
bool fix_fields(THD *, struct st_table_list *, Item **);
int save_in_field(Field *field, bool no_conversions)
{ 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);
};
@@ -550,6 +577,7 @@ public:
~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 MYSQL_TYPE_STRING; }
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_func.cc b/sql/item_func.cc
index c84b554b522..1ce5b038f3b 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -1945,8 +1945,6 @@ 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
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..5de493a5341 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);
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index e087664e060..87a1bfcd952 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -73,20 +73,6 @@ 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)
diff --git a/sql/item_subselect.h b/sql/item_subselect.h
index d323dab51f1..648a1885814 100644
--- a/sql/item_subselect.h
+++ b/sql/item_subselect.h
@@ -74,7 +74,6 @@ public:
void assigned(bool a) { value_assigned= a; }
enum Type type() const;
bool is_null() { return null_value; }
- void make_field (Send_field *);
bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref);
virtual void fix_length_and_dec();
table_map used_tables() const;
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index a1f772f4d46..6307c94ac4f 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());
@@ -170,6 +163,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;
}
diff --git a/sql/item_sum.h b/sql/item_sum.h
index 23b8482d41a..47c0b9284fc 100644
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@ -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() {}
};
@@ -247,7 +247,7 @@ public:
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() {}
};
@@ -281,6 +281,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 +308,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.h b/sql/item_timefunc.h
index 40397351c18..b4a0b517090 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 :
@@ -470,11 +461,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 :
@@ -566,10 +554,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 +568,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 +582,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/log_event.cc b/sql/log_event.cc
index 5050bba9965..1f4371d5919 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -306,9 +306,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);
}
/*****************************************************************************
@@ -319,10 +319,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));
}
@@ -333,23 +336,22 @@ void Log_event::init_show_field_list(List<Item>* field_list)
Only called by SHOW BINLOG EVENTS
****************************************************************************/
-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 my_net_write(&thd_arg->net, (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 // !MYSQL_CLIENT
@@ -671,7 +673,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);
@@ -685,7 +687,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
@@ -925,7 +927,7 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli)
****************************************************************************/
#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);
@@ -936,7 +938,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
@@ -1036,7 +1038,7 @@ int Start_log_event::exec_event(struct st_relay_log_info* rli)
****************************************************************************/
#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);
@@ -1109,7 +1111,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
@@ -1542,7 +1544,7 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli)
****************************************************************************/
#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);
@@ -1552,7 +1554,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
@@ -1680,7 +1682,7 @@ int Rotate_log_event::exec_event(struct st_relay_log_info* rli)
****************************************************************************/
#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);
@@ -1688,7 +1690,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
@@ -1801,14 +1803,14 @@ int Intvar_log_event::exec_event(struct st_relay_log_info* rli)
****************************************************************************/
#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
@@ -1888,7 +1890,7 @@ int Rand_log_event::exec_event(struct st_relay_log_info* rli)
****************************************************************************/
#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);
@@ -1902,7 +1904,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
@@ -2236,7 +2238,7 @@ void Create_file_log_event::print(FILE* file, bool short_form,
****************************************************************************/
#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);
@@ -2251,7 +2253,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
@@ -2395,14 +2397,14 @@ void Append_block_log_event::print(FILE* file, bool short_form,
****************************************************************************/
#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
@@ -2510,12 +2512,12 @@ void Delete_file_log_event::print(FILE* file, bool short_form,
****************************************************************************/
#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
@@ -2609,12 +2611,12 @@ void Execute_load_log_event::print(FILE* file, bool short_form,
****************************************************************************/
#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
diff --git a/sql/log_event.h b/sql/log_event.h
index 20a134ab3cc..c4f93c7a9b6 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -267,8 +267,8 @@ public:
static int read_log_event(IO_CACHE* file, String* packet,
pthread_mutex_t* log_lock);
void set_log_pos(MYSQL_LOG* log);
- virtual void pack_info(String* packet);
- int net_send(THD* thd, const char* log_name, my_off_t pos);
+ virtual void pack_info(Protocol *protocol);
+ int net_send(Protocol *protocol, const char* log_name, my_off_t pos);
static void init_show_field_list(List<Item>* field_list);
virtual int exec_event(struct st_relay_log_info* rli);
virtual const char* get_db()
@@ -355,7 +355,7 @@ public:
Query_log_event(THD* thd_arg, const char* query_arg, ulong query_length,
bool using_trans);
const char* get_db() { return db; }
- void pack_info(String* packet);
+ void pack_info(Protocol* protocol);
int exec_event(struct st_relay_log_info* rli);
#else
void print(FILE* file, bool short_form = 0, char* last_db = 0);
@@ -404,7 +404,7 @@ public:
#ifndef MYSQL_CLIENT
Slave_log_event(THD* thd_arg, struct st_relay_log_info* rli);
- void pack_info(String* packet);
+ void pack_info(Protocol* protocol);
int exec_event(struct st_relay_log_info* rli);
#else
void print(FILE* file, bool short_form = 0, char* last_db = 0);
@@ -454,7 +454,7 @@ public:
List<Item>& fields_arg, enum enum_duplicates handle_dup,
bool using_trans);
void set_fields(List<Item> &fields_arg);
- void pack_info(String* packet);
+ void pack_info(Protocol* protocol);
const char* get_db() { return db; }
int exec_event(struct st_relay_log_info* rli)
{
@@ -507,7 +507,7 @@ public:
created = (uint32) when;
memcpy(server_version, ::server_version, ST_SERVER_VER_LEN);
}
- void pack_info(String* packet);
+ void pack_info(Protocol* protocol);
int exec_event(struct st_relay_log_info* rli);
#else
void print(FILE* file, bool short_form = 0, char* last_db = 0);
@@ -542,7 +542,7 @@ public:
Intvar_log_event(THD* thd_arg,uchar type_arg, ulonglong val_arg)
:Log_event(),val(val_arg),type(type_arg)
{}
- void pack_info(String* packet);
+ void pack_info(Protocol* protocol);
int exec_event(struct st_relay_log_info* rli);
#else
void print(FILE* file, bool short_form = 0, char* last_db = 0);
@@ -574,7 +574,7 @@ class Rand_log_event: public Log_event
Rand_log_event(THD* thd_arg, ulonglong seed1_arg, ulonglong seed2_arg)
:Log_event(thd_arg,0,0),seed1(seed1_arg),seed2(seed2_arg)
{}
- void pack_info(String* packet);
+ void pack_info(Protocol* protocol);
int exec_event(struct st_relay_log_info* rli);
#else
void print(FILE* file, bool short_form = 0, char* last_db = 0);
@@ -636,7 +636,7 @@ public:
pos(pos_arg),ident_len(ident_len_arg ? ident_len_arg :
(uint) strlen(new_log_ident_arg)), alloced(0)
{}
- void pack_info(String* packet);
+ void pack_info(Protocol* protocol);
int exec_event(struct st_relay_log_info* rli);
#else
void print(FILE* file, bool short_form = 0, char* last_db = 0);
@@ -683,7 +683,7 @@ public:
enum enum_duplicates handle_dup,
char* block_arg, uint block_len_arg,
bool using_trans);
- void pack_info(String* packet);
+ void pack_info(Protocol* protocol);
int exec_event(struct st_relay_log_info* rli);
#else
void print(FILE* file, bool short_form = 0, char* last_db = 0);
@@ -734,7 +734,7 @@ public:
Append_block_log_event(THD* thd, char* block_arg,
uint block_len_arg, bool using_trans);
int exec_event(struct st_relay_log_info* rli);
- void pack_info(String* packet);
+ void pack_info(Protocol* protocol);
#else
void print(FILE* file, bool short_form = 0, char* last_db = 0);
#endif
@@ -759,7 +759,7 @@ public:
#ifndef MYSQL_CLIENT
Delete_file_log_event(THD* thd, bool using_trans);
- void pack_info(String* packet);
+ void pack_info(Protocol* protocol);
int exec_event(struct st_relay_log_info* rli);
#else
void print(FILE* file, bool short_form = 0, char* last_db = 0);
@@ -785,7 +785,7 @@ public:
#ifndef MYSQL_CLIENT
Execute_load_log_event(THD* thd, bool using_trans);
- void pack_info(String* packet);
+ void pack_info(Protocol* protocol);
int exec_event(struct st_relay_log_info* rli);
#else
void print(FILE* file, bool short_form = 0, char* last_db = 0);
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 771d105a1c7..e3ebf14dcbe 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);
@@ -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/net_pkg.cc b/sql/net_pkg.cc
deleted file mode 100644
index 1da625e776f..00000000000
--- a/sql/net_pkg.cc
+++ /dev/null
@@ -1,492 +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"));
-
- query_cache_abort(net);
- 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 */
- }
- }
- }
- 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));
- 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
-*/
-
-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;
-}
-
-
-/*
- 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,*text_pos;
- 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
- query_cache_abort(net); // Safety
- 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;
- text_pos=(char*) net->buff+head_length+offset+1;
- (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);
-
- 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));
- thd->fatal_error=0; // Error message is given
- DBUG_VOID_RETURN;
-}
-
-
-/*
- 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
-*/
-
-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;
-}
-
-
-/****************************************************************************
-** 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);
-}
-
-/*
- 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);
-}
-}
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..a7540f39f9e
--- /dev/null
+++ b/sql/protocol.cc
@@ -0,0 +1,983 @@
+/* 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"));
+
+ query_cache_abort(net);
+ 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 */
+ }
+ }
+ }
+ 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));
+ 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
+*/
+
+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;
+}
+
+
+/*
+ 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,*text_pos;
+ 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
+ query_cache_abort(net); // Safety
+ 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;
+ text_pos=(char*) net->buff+head_length+offset+1;
+ (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);
+
+ 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));
+ thd->fatal_error=0; // Error message is given
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ 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
+*/
+
+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;
+}
+
+
+/****************************************************************************
+ 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);
+ 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 store((char*) tmp.ptr(), tmp.length());
+}
+
+
+/****************************************************************************
+ 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_STRING ||
+ field_types[field_pos] == MYSQL_TYPE_VAR_STRING);
+ 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)
+{
+#ifndef DEBUG_OFF
+ field_pos++;
+#endif
+ if (field->is_null())
+ return store_null();
+ 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);
+#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%ld:%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_STRING ||
+ field_types[field_pos] == MYSQL_TYPE_VAR_STRING);
+#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);
+#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 785a253b1ac..16b2eedd3b2 100644
--- a/sql/repl_failsafe.cc
+++ b/sql/repl_failsafe.cc
@@ -416,6 +416,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];
@@ -431,15 +432,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);
@@ -580,21 +581,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);
@@ -602,18 +606,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/slave.cc b/sql/slave.cc
index f8acc592afa..7d3ec8d3dce 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 59f4d920304..0c68b5e92ef 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -2776,6 +2776,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);
@@ -2822,7 +2823,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);
@@ -2931,12 +2932,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 (my_net_write(&thd->net,(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;
}
}
@@ -2987,10 +2988,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 (my_net_write(&thd->net,(char*) thd->packet.ptr(),
- thd->packet.length()))
+ protocol->prepare_for_resend();
+ protocol->store(db.ptr(),db.length());
+ if (protocol->write())
{
error=-1;
goto end;
@@ -3075,10 +3075,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 (my_net_write(&thd->net,(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_base.cc b/sql/sql_base.cc
index e2b36106fb0..87cc0d616a9 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -196,250 +196,6 @@ OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *wild)
}
-/*
- 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)
-*/
-
-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 */
-}
-
-
/*****************************************************************************
* Functions to free open table cache
****************************************************************************/
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index ebd1d9d2b3c..dedf496db3c 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -152,6 +152,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)
@@ -438,7 +443,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));
@@ -447,12 +452,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));
}
@@ -503,7 +509,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);
}
@@ -511,35 +517,32 @@ 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);
}
- 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);
}
bool select_send::send_eof()
diff --git a/sql/sql_class.h b/sql/sql_class.h
index ca56d2dcdf5..50ab7919998 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -389,6 +389,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 85dfb38fa48..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 (my_net_write(&thd->net,(char*) packet->ptr(), packet->length()))
+ if (protocol->write())
DBUG_RETURN(1);
-
send_eof(thd);
DBUG_RETURN(0);
}
diff --git a/sql/sql_error.cc b/sql/sql_error.cc
index bba49cf818b..b208015a2bb 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)
{
@@ -161,12 +161,13 @@ my_bool mysqld_show_warnings(THD *thd, ulong levels_to_show)
field_list.push_back(new Item_int("Code",0,4));
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 (my_net_write(&thd->net,(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 6ea319a72e4..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;
}
}
- my_net_write(&thd->net, (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 d2bea9ba44b..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 (my_net_write(&thd->net,(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 (my_net_write(&thd->net,(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_parse.cc b/sql/sql_parse.cc
index 90568bfcc5e..f8c46c7cd41 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -3010,11 +3010,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;
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 9d6e6d75ade..704acc9c1c2 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -512,7 +512,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);
}
@@ -726,7 +727,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 23951cec29f..63cd192e539 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -928,14 +928,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())
@@ -983,7 +984,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;
@@ -1029,28 +1030,30 @@ 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);
@@ -1079,6 +1082,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())
{
@@ -1088,8 +1093,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();
@@ -1101,19 +1106,19 @@ int show_binlogs(THD* thd)
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 5b8e2085982..683cc0925b6 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -7529,7 +7529,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)
@@ -7587,9 +7589,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))))
@@ -7645,6 +7647,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");
@@ -7675,6 +7678,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 ebf5b210d6c..2826b44692e 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -62,6 +62,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));
@@ -71,13 +72,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) ||
@@ -85,10 +85,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 (my_net_write(&thd->net, (char*) packet->ptr(),
- packet->length()))
+ protocol->prepare_for_resend();
+ protocol->store(file_name);
+ if (protocol->write())
DBUG_RETURN(-1);
}
}
@@ -105,29 +104,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 (my_net_write(&thd->net,(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);
}
@@ -149,9 +147,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);
@@ -159,17 +159,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 (my_net_write(&thd->net,(char*) packet->ptr(),packet->length()))
+ protocol->prepare_for_resend();
+ protocol->store(file_name);
+ if (protocol->write())
DBUG_RETURN(-1);
}
send_eof(thd);
@@ -210,31 +209,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 (my_net_write(&thd->net, (char*) packet->ptr(), packet->length()))
+ protocol->store(option_name);
+ protocol->store(types->comment);
+ if (protocol->write())
DBUG_RETURN(-1);
}
send_eof(thd);
@@ -279,24 +279,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 (my_net_write(&thd->net,(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 +343,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 +361,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 (my_net_write(&thd->net,(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 +477,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 +514,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 +524,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,19 +628,18 @@ 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 (my_net_write(&thd->net,(char*) packet->ptr(),
- packet->length()))
+ if (protocol->write())
DBUG_RETURN(-1);
}
send_eof(thd);
@@ -656,7 +659,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 +694,7 @@ mysqld_show_fields(THD *thd, TABLE_LIST *table_list,const char *wild,
(void) my_net_write(&thd->net,tmp,(uint) (pos-tmp));
}
- 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 +717,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 +738,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,10 +763,10 @@ 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 (my_net_write(&thd->net,(char*) packet->ptr(),packet->length()))
+ if (protocol->write())
DBUG_RETURN(1);
}
}
@@ -777,7 +780,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));
@@ -791,51 +796,17 @@ 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);
+ 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 (my_net_write(&thd->net, (char*)packet->ptr(), packet->length()))
- DBUG_RETURN(1);
- }
send_eof(thd);
DBUG_RETURN(0);
}
@@ -844,18 +815,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
@@ -869,7 +841,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));
@@ -883,15 +855,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;
@@ -900,7 +873,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;
@@ -909,54 +882,48 @@ 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 (my_net_write(&thd->net,(char*) packet->ptr(),packet->length()))
+ protocol->store("", 0);
+ if (protocol->write())
DBUG_RETURN(1); /* purecov: inspected */
}
}
@@ -992,7 +959,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;
VOID(net_flush(&thd->net));
DBUG_VOID_RETURN;
@@ -1002,20 +969,20 @@ 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());
+ 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));
}
@@ -1278,21 +1245,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
@@ -1358,37 +1325,26 @@ 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);
- else
- net_store_null(packet);
- if (thd_info->query)
- net_store_data(packet,convert,thd_info->query);
+ protocol->store((uint32) (now - thd_info->start_time));
else
- net_store_null(packet);
- if (my_net_write(&thd->net,(char*) packet->ptr(),packet->length()))
+ protocol->store_null();
+ protocol->store(thd_info->state_info);
+ protocol->store(thd_info->query);
+ if (protocol->write())
break; /* purecov: inspected */
}
send_eof(thd);
@@ -1405,16 +1361,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++ )
@@ -1424,14 +1380,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 (my_net_write(&thd->net, (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);
@@ -1445,15 +1400,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); */
@@ -1463,232 +1417,248 @@ 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;
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;
}
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 (my_net_write(&thd->net, (char*) packet2.ptr(),packet2.length()))
+ if (protocol->store(pos, (uint32) (end - pos)) ||
+ protocol->write())
goto err; /* purecov: inspected */
}
}
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 d343ccd39f5..1ab84531e40 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -1017,20 +1017,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 (my_net_write(&thd->net, (char*) thd->packet.ptr(),
- packet->length()))
+ if (protocol->write())
return -1;
return 1;
}
@@ -1176,8 +1174,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));
@@ -1188,7 +1186,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)
@@ -1201,7 +1199,8 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
thd->open_options|= extra_open_options;
table->table = open_ltable(thd, table, lock_type);
thd->open_options&= ~extra_open_options;
- packet->length(0);
+ protocol->prepare_for_resend();
+
if (prepare_func)
{
switch ((*prepare_func)(thd, table, check_opt)) {
@@ -1214,30 +1213,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 (my_net_write(&thd->net, (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 (my_net_write(&thd->net, (char*) thd->packet.ptr(),
- packet->length()))
+ if (protocol->write())
goto err;
continue;
}
@@ -1265,50 +1264,50 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
}
int result_code = (table->table->file->*operator_func)(thd, check_opt);
- 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;
}
@@ -1325,8 +1324,7 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
}
close_thread_tables(thd);
table->table=0; // For query cache
- if (my_net_write(&thd->net, (char*) packet->ptr(),
- packet->length()))
+ if (protocol->write())
goto err;
}
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;
+}
diff --git a/tests/fork_big2.pl b/tests/fork_big2.pl
new file mode 100644
index 00000000000..b552b95ba6b
--- /dev/null
+++ b/tests/fork_big2.pl
@@ -0,0 +1,705 @@
+#!/usr/bin/perl -w
+#
+# This is a test with uses many processes to test a MySQL server.
+#
+# Tested a lot with: --threads=30
+
+$opt_loop_count=500000; # Change this to make test harder/easier
+
+##################### Standard benchmark inits ##############################
+
+use DBI;
+use Getopt::Long;
+use Benchmark;
+
+package main;
+
+$opt_skip_create=$opt_skip_in=$opt_verbose=$opt_fast_insert=
+$opt_lock_tables=$opt_debug=$opt_skip_drop=$opt_fast=$opt_force=0;
+$opt_thread_factor=1;
+$opt_insert=1;
+$opt_select=6;$opt_join=4;
+$opt_select_count=$opt_join_count=0;
+$opt_update=1;$opt_delete=0;
+$opt_flush=$opt_check=$opt_repair=$opt_alter=0;
+$opt_join_range=100;
+$opt_time=0;
+$opt_host=$opt_user=$opt_password=""; $opt_db="test";
+
+GetOptions("host=s","db=s","user=s","password=s","loop-count=i","skip-create","skip-in","skip-drop",
+ "verbose","fast-insert","lock-tables","debug","fast","force","thread-factor=i",
+ "insert=i", "select=i", "join=i", "select-count=i", "join-count=i", "update=i", "delete=i",
+ "flush=i", "check=i", "repair=i", "alter=i", "max-join_range=i", "time=i") || die "Aborted";
+$opt_verbose=$opt_debug=$opt_lock_tables=$opt_fast_insert=$opt_fast=$opt_skip_in=$opt_force=undef; # Ignore warnings from these
+
+print "Test of multiple connections that test the following things:\n";
+print "insert, select, delete, update, alter, check, repair and flush\n";
+
+@testtables = ( ["bench_f31", ""],
+ ["bench_f32", "row_format=fixed"],
+ ["bench_f33", "delay_key_write=1"],
+ ["bench_f34", "checksum=1"],
+ ["bench_f35", "delay_key_write=1"]);
+$abort_table="bench_f39";
+
+$numtables = $#testtables+1;
+srand 100; # Make random numbers repeatable
+
+####
+#### Start timeing and start test
+####
+
+$opt_insert*=$opt_thread_factor;
+$opt_select*=$opt_thread_factor;
+$opt_join*=$opt_thread_factor;
+$opt_select_count*=$opt_thread_factor;
+$opt_join_count*=$opt_thread_factor;
+$opt_update*=$opt_thread_factor;
+$opt_delete*=$opt_thread_factor;
+
+if ($opt_time == 0 && $opt_insert == 0)
+{
+ $opt_insert=1;
+}
+
+$start_time=new Benchmark;
+$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
+ $opt_user, $opt_password,
+ { PrintError => 0}) || die $DBI::errstr;
+if (!$opt_skip_create)
+{
+ my $table_def;
+ foreach $table_def (@testtables)
+ {
+ my ($table,$extra)= ($table_def->[0], $table_def->[1]);
+ print "Creating table $table in database $opt_db\n";
+ $dbh->do("drop table if exists $table");
+ $dbh->do("create table $table".
+ " (id int(6) not null auto_increment,".
+ " info varchar(32)," .
+ " marker timestamp," .
+ " flag int not null," .
+ " primary key(id)) $extra")
+
+ or die $DBI::errstr;
+ # One row in the table will make future tests easier
+ $dbh->do("insert into $table (id) values (null)")
+ or die $DBI::errstr;
+ }
+ # Create the table we use to signal that we should end the test
+ $dbh->do("drop table if exists $abort_table");
+ $dbh->do("create table $abort_table (id int(6) not null) type=heap") ||
+ die $DBI::errstr;
+}
+
+$dbh->do("delete from $abort_table");
+$dbh->disconnect; $dbh=0; # Close handler
+$|= 1; # Autoflush
+
+####
+#### Start the tests
+####
+if ($opt_time != 0)
+{
+ test_abort() if (($pid=fork()) == 0); $work{$pid}="abort";
+}
+for ($i=0 ; $i < $opt_insert ; $i ++)
+{
+ test_insert() if (($pid=fork()) == 0); $work{$pid}="insert";
+}
+$threads=$i;
+for ($i=0 ; $i < $opt_select ; $i ++)
+{
+ test_select() if (($pid=fork()) == 0); $work{$pid}="select";
+}
+$threads+=$i;
+for ($i=0 ; $i < $opt_join ; $i ++)
+{
+ test_join() if (($pid=fork()) == 0); $work{$pid}="join";
+}
+$threads+=$i;
+for ($i=0 ; $i < $opt_select_count ; $i ++)
+{
+ test_select_count() if (($pid=fork()) == 0); $work{$pid}="select_count";
+}
+$threads+=$i;
+for ($i=0 ; $i < $opt_join_count ; $i ++)
+{
+ test_join_count() if (($pid=fork()) == 0); $work{$pid}="join_count";
+}
+$threads+=$i;
+for ($i=0 ; $i < $opt_update ; $i ++)
+{
+ test_update() if (($pid=fork()) == 0); $work{$pid}="update";
+}
+$threads+=$i;
+for ($i=0 ; $i < $opt_delete ; $i ++)
+{
+ test_delete() if (($pid=fork()) == 0); $work{$pid}="delete";
+}
+$threads+=$i;
+for ($i=0 ; $i < $opt_flush ; $i ++)
+{
+ test_flush() if (($pid=fork()) == 0); $work{$pid}="flush";
+}
+$threads+=$i;
+for ($i=0 ; $i < $opt_check ; $i ++)
+{
+ test_check() if (($pid=fork()) == 0); $work{$pid}="check";
+}
+$threads+=$i;
+for ($i=0 ; $i < $opt_repair ; $i ++)
+{
+ test_repair() if (($pid=fork()) == 0); $work{$pid}="repair";
+}
+$threads+=$i;
+for ($i=0 ; $i < $opt_alter ; $i ++)
+{
+ test_alter() if (($pid=fork()) == 0); $work{$pid}="alter";
+}
+$threads+=$i;
+
+print "Started $threads threads\n";
+
+$errors=0;
+$running_insert_threads=$opt_insert;
+while (($pid=wait()) != -1)
+{
+ $ret=$?/256;
+ print "thread '" . $work{$pid} . "' finished with exit code $ret\n";
+ if ($opt_time == 0)
+ {
+ if ($work{$pid} =~ /^insert/)
+ {
+ if (!--$running_insert_threads)
+ {
+
+ # Time to stop other threads
+ signal_abort();
+ }
+ }
+ }
+ $errors++ if ($ret != 0);
+}
+
+#
+# Cleanup
+#
+
+if (!$opt_skip_drop && !$errors)
+{
+ my $table_def;
+ $dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
+ $opt_user, $opt_password,
+ { PrintError => 0}) || die $DBI::errstr;
+
+ $dbh->do("drop table $abort_table");
+ foreach $table_def (@testtables)
+ {
+ $dbh->do("drop table " . $table_def->[0]);
+ }
+ $dbh->disconnect; $dbh=0; # Close handler
+}
+
+print ($errors ? "Test failed\n" :"Test ok\n");
+$end_time=new Benchmark;
+print "Total time: " .
+ timestr(timediff($end_time, $start_time),"noc") . "\n";
+
+exit(0);
+
+#
+# Sleep and then abort other threads
+#
+
+sub test_abort
+{
+ sleep($opt_time);
+ signal_abort();
+ exit(0);
+}
+
+
+#
+# Insert records in the table
+#
+
+sub test_insert
+{
+ my ($from_table,$to_table)= @_;
+ my ($dbh,$i,$j,$count,$table_def,$table);
+
+ if (!defined($from_table))
+ {
+ $from_table=0; $to_table=$numtables-1;
+ }
+
+ $dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
+ $opt_user, $opt_password,
+ { PrintError => 0}) || die $DBI::errstr;
+
+ for ($i=$count=0 ; $i < $opt_loop_count; $i++)
+ {
+ for ($j= $from_table ; $j <= $to_table ; $j++)
+ {
+ my ($table)= ($testtables[$j]->[0]);
+ $dbh->do("insert into $table values (NULL,'This is entry $i','',0)") || die "Got error on insert: $DBI::errstr\n";
+ $count++;
+ }
+ }
+ $dbh->disconnect; $dbh=0;
+ print "Test_insert: Inserted $count rows\n";
+ exit(0);
+}
+
+
+#
+# select records
+# Do continously select over all tables as long as there is changed
+# rows in the table
+#
+
+sub test_select
+{
+ my ($dbh, $i, $j, $count, $loop);
+
+ $dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
+ $opt_user, $opt_password,
+ { PrintError => 0}) || die $DBI::errstr;
+
+ $count_query=make_count_query($numtables);
+ $count=0;
+ $loop=9999;
+
+ $i=0;
+ while (($i++ % 100) || !test_if_abort($dbh))
+ {
+ if ($loop++ >= 100)
+ {
+ $loop=0;
+ $row_counts=simple_query($dbh, $count_query);
+ }
+ for ($j=0 ; $j < $numtables ; $j++)
+ {
+ my ($id)= int rand $row_counts->[$j];
+ my ($table)= $testtables[$j]->[0];
+ simple_query($dbh, "select id,info from $table where id=$id");
+ $count++;
+ }
+ }
+ $dbh->disconnect; $dbh=0;
+ print "Test_select: Executed $count selects\n";
+ exit(0);
+}
+
+#
+# Do big select count(distinct..) over the table
+#
+
+sub test_select_count
+{
+ my ($dbh, $i, $j, $count, $loop);
+
+ $dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
+ $opt_user, $opt_password,
+ { PrintError => 0}) || die $DBI::errstr;
+
+ $count=0;
+ $i=0;
+ while (!test_if_abort($dbh))
+ {
+ for ($j=0 ; $j < $numtables ; $j++)
+ {
+ my ($table)= $testtables[$j]->[0];
+ simple_query($dbh, "select count(distinct marker),count(distinct id),count(distinct info) from $table");
+ $count++;
+ }
+ sleep(20); # This query is quite slow
+ }
+ $dbh->disconnect; $dbh=0;
+ print "Test_select: Executed $count select count(distinct) queries\n";
+ exit(0);
+}
+
+#
+# select records
+# Do continously joins between the first and second table
+#
+
+sub test_join
+{
+ my ($dbh, $i, $j, $count, $loop);
+
+ $dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
+ $opt_user, $opt_password,
+ { PrintError => 0}) || die $DBI::errstr;
+
+ $count_query=make_count_query($numtables);
+ $count=0;
+ $loop=9999;
+
+ $i=0;
+ while (($i++ % 100) || !test_if_abort($dbh))
+ {
+ if ($loop++ >= 100)
+ {
+ $loop=0;
+ $row_counts=simple_query($dbh, $count_query);
+ }
+ for ($j=0 ; $j < $numtables-1 ; $j++)
+ {
+ my ($id)= int rand $row_counts->[$j];
+ my ($t1,$t2)= ($testtables[$j]->[0],$testtables[$j+1]->[0]);
+ simple_query($dbh, "select $t1.id,$t2.info from $t1, $t2 where $t1.id=$t2.id and $t1.id=$id");
+ $count++;
+ }
+ }
+ $dbh->disconnect; $dbh=0;
+ print "Test_join: Executed $count joins\n";
+ exit(0);
+}
+
+#
+# select records
+# Do continously joins between the first and second for range and count selected rows
+#
+
+sub test_join_count
+{
+ my ($dbh, $i, $j, $count, $loop);
+
+ $dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
+ $opt_user, $opt_password,
+ { PrintError => 0}) || die $DBI::errstr;
+
+ $count_query=make_count_query($numtables);
+ $count=0;
+ $loop=9999;
+ $sum=0;
+
+ srand();
+
+ $i=0;
+ while (($i++ % 10) || !test_if_abort($dbh))
+ {
+ if ($loop++ >= 10)
+ {
+ $loop=0;
+ $row_counts=simple_query($dbh, $count_query);
+ }
+ for ($j=0 ; $j < $numtables-1 ; $j++)
+ {
+ my ($id1)= int rand $row_counts->[$j];
+ my ($id2)= int rand $row_counts->[$j];
+ if ($id1 > $id2)
+ {
+ my $id0=$id1; $id1=$id2; $id2=$id0;
+ if ($id2-$id1 > $opt_join_range)
+ {
+ $id2=$id1+$opt_join_range;
+ }
+ }
+ my ($t1,$t2)= ($testtables[$j]->[0],$testtables[$j+1]->[0]);
+ $row=simple_query($dbh, "select count(*) from $t1, $t2 where $t1.id=$t2.id and $t1.id between $id1 and $id2");
+ $sum+=$row->[0];
+ $count++;
+ }
+ }
+ $dbh->disconnect; $dbh=0;
+ print "Test_join_count: Executed $count joins: total $sum rows\n";
+ exit(0);
+}
+
+
+#
+# Delete 1-5 rows from the first 2 tables.
+# Test ends when the number of rows for table 3 didn't change during
+# one loop
+#
+
+sub test_delete
+{
+ my ($dbh, $i,$j, $row_counts, $count_query, $table_count, $count);
+
+ $table_count=2;
+ $count=0;
+ $dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
+ $opt_user, $opt_password,
+ { PrintError => 0}) || die $DBI::errstr;
+
+ $count_query=make_count_query($table_count+1);
+
+ sleep(5); # Give time to insert some rows
+ $i=0;
+ while (($i++ % 10) || !test_if_abort($dbh))
+ {
+ sleep(1);
+ $row_counts=simple_query($dbh, $count_query);
+
+ for ($j=0 ; $j < $table_count ; $j++)
+ {
+ my ($id)= int rand $row_counts->[$j];
+ my ($table)= $testtables[$j]->[0];
+ $dbh->do("delete from $table where id >= $id-2 and id <= $id +2") || die "Got error on delete from $table: $DBI::errstr\n";
+ $count++;
+ }
+ }
+ $dbh->disconnect; $dbh=0;
+ print "Test_delete: Executed $count deletes\n";
+ exit(0);
+}
+
+#
+# Update the flag for table 2 and 3
+# Will abort after a while when table1 doesn't change max value
+#
+
+sub test_update
+{
+ my ($dbh, $i, $j, $row_counts, $count_query, $count, $loop);
+ $dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
+ $opt_user, $opt_password,
+ { PrintError => 0}) || die $DBI::errstr;
+
+ $count_query=make_count_query(3);
+ $loop=9999;
+ $count=0;
+
+ sleep(5); # Give time to insert some rows
+ $i=0;
+ while (($i++ % 100) || !test_if_abort($dbh))
+ {
+ if ($loop++ >= 100)
+ {
+ $loop=0;
+ $row_counts=simple_query($dbh, $count_query);
+ }
+
+ for ($j=1 ; $j <= 2 ; $j++)
+ {
+ my ($id)= int rand $row_counts->[$j];
+ my ($table)= $testtables[$j]->[0];
+ # Fix to not change the same rows as the above delete
+ $id= ($id + $count) % $row_counts->[$j];
+
+ $dbh->do("update $table set flag=flag+1 where id >= $id-2 and id <= $id +2") || die "Got error on update of $table: $DBI::errstr\n";
+ $count++;
+ }
+ }
+ $dbh->disconnect; $dbh=0;
+ print "Test_update: Executed $count updates\n";
+ exit(0);
+}
+
+
+#
+# Run a check on all tables except the last one
+# (The last one is not checked to put pressure on the key cache)
+#
+
+sub test_check
+{
+ my ($dbh, $row, $i, $j, $type, $table);
+ $dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
+ $opt_user, $opt_password,
+ { PrintError => 0}) || die $DBI::errstr;
+
+ $type= "check";
+ for ($i=$j=0 ; !test_if_abort($dbh) ; $i++)
+ {
+ sleep(1000);
+ $table=$testtables[$j]->[0];
+ $sth=$dbh->prepare("$type table $table") || die "Got error on prepare: $DBI::errstr\n";
+ $sth->execute || die $DBI::errstr;
+
+ while (($row=$sth->fetchrow_arrayref))
+ {
+ if ($row->[3] ne "OK")
+ {
+ print "Got error " . $row->[3] . " when doing $type on $table\n";
+ exit(1);
+ }
+ }
+ if (++$j == $numtables-1)
+ {
+ $j=0;
+ }
+ }
+ $dbh->disconnect; $dbh=0;
+ print "test_check: Executed $i checks\n";
+ exit(0);
+}
+
+#
+# Do a repair on the first table once in a while
+#
+
+sub test_repair
+{
+ my ($dbh, $row, $i, $type, $table);
+ $dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
+ $opt_user, $opt_password,
+ { PrintError => 0}) || die $DBI::errstr;
+
+ $type= "repair";
+ for ($i=0 ; !test_if_abort($dbh) ; $i++)
+ {
+ sleep(2000);
+ $table=$testtables[0]->[0];
+ $sth=$dbh->prepare("$type table $table") || die "Got error on prepare: $DBI::errstr\n";
+ $sth->execute || die $DBI::errstr;
+
+ while (($row=$sth->fetchrow_arrayref))
+ {
+ if ($row->[3] ne "OK")
+ {
+ print "Got error " . $row->[3] . " when doing $type on $table\n";
+ exit(1);
+ }
+ }
+ }
+ $dbh->disconnect; $dbh=0;
+ print "test_repair: Executed $i repairs\n";
+ exit(0);
+}
+
+#
+# Do a flush tables on table 3 and 4 once in a while
+#
+
+sub test_flush
+{
+ my ($dbh,$count,$tables);
+
+ $dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
+ $opt_user, $opt_password,
+ { PrintError => 0}) || die $DBI::errstr;
+
+ $tables=$testtables[2]->[0] . "," . $testtables[3]->[0];
+
+ $count=0;
+ while (!test_if_abort($dbh))
+ {
+ sleep(3000);
+ $dbh->do("flush tables $tables") ||
+ die "Got error on flush $DBI::errstr\n";
+ $count++;
+ }
+ $dbh->disconnect; $dbh=0;
+ print "flush: Executed $count flushs\n";
+ exit(0);
+}
+
+
+#
+# Test all tables in a database
+#
+
+sub test_database
+{
+ my ($database) = @_;
+ my ($dbh, $row, $i, $type, $tables);
+ $dbh = DBI->connect("DBI:mysql:$database:$opt_host",
+ $opt_user, $opt_password,
+ { PrintError => 0}) || die $DBI::errstr;
+
+ $tables= join(',',$dbh->func('_ListTables'));
+ $type= "check";
+ for ($i=0 ; !test_if_abort($dbh) ; $i++)
+ {
+ sleep(120);
+ $sth=$dbh->prepare("$type table $tables") || die "Got error on prepare: $DBI::errstr\n";
+ $sth->execute || die $DBI::errstr;
+
+ while (($row=$sth->fetchrow_arrayref))
+ {
+ if ($row->[3] ne "OK")
+ {
+ print "Got error " . $row->[2] . " " . $row->[3] . " when doing $type on " . $row->[0] . "\n";
+ exit(1);
+ }
+ }
+ }
+ $dbh->disconnect; $dbh=0;
+ print "test_check: Executed $i checks\n";
+ exit(0);
+}
+
+#
+# Test ALTER TABLE on the second table
+#
+
+sub test_alter
+{
+ my ($dbh, $row, $i, $type, $table);
+ $dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
+ $opt_user, $opt_password,
+ { PrintError => 0}) || die $DBI::errstr;
+
+ for ($i=0 ; !test_if_abort($dbh) ; $i++)
+ {
+ sleep(100);
+ $table=$testtables[1]->[0];
+ $sth=$dbh->prepare("ALTER table $table modify info char(32)") || die "Got error on prepare: $DBI::errstr\n";
+ $sth->execute || die $DBI::errstr;
+ }
+ $dbh->disconnect; $dbh=0;
+ print "test_alter: Executed $i ALTER TABLE\n";
+ exit(0);
+}
+
+
+#
+# Help functions
+#
+
+sub signal_abort
+{
+ my ($dbh);
+ $dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
+ $opt_user, $opt_password,
+ { PrintError => 0}) || die $DBI::errstr;
+
+ $dbh->do("insert into $abort_table values(1)") || die $DBI::errstr;
+ $dbh->disconnect; $dbh=0;
+}
+
+
+sub test_if_abort()
+{
+ my ($dbh)=@_;
+ $row=simple_query($dbh,"select * from $opt_db.$abort_table");
+ return (defined($row) && defined($row->[0]) != 0) ? 1 : 0;
+}
+
+
+sub make_count_query
+{
+ my ($table_count)= @_;
+ my ($tables, $count_query, $i, $tables_def);
+ $tables="";
+ $count_query="select high_priority ";
+ $table_count--;
+ for ($i=0 ; $i < $table_count ; $i++)
+ {
+ my ($table_def)= $testtables[$i];
+ $tables.=$table_def->[0] . ",";
+ $count_query.= "max(" . $table_def->[0] . ".id),";
+ }
+ $table_def=$testtables[$table_count];
+ $tables.=$table_def->[0];
+ $count_query.= "max(" . $table_def->[0] . ".id) from $tables";
+ return $count_query;
+}
+
+sub simple_query()
+{
+ my ($dbh, $query)= @_;
+ my ($sth,$row);
+
+ $sth=$dbh->prepare($query) || die "Got error on '$query': " . $dbh->errstr . "\n";
+ $sth->execute || die "Got error on '$query': " . $dbh->errstr . "\n";
+ $row= $sth->fetchrow_arrayref();
+ $sth=0;
+ return $row;
+}