mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 20:12:31 +01:00
rename of net_pkg.cc to protocol.cc
Class for sending data from server to client (Protocol) This handles both the old ( <= 4.0 ) protocol and then new binary protocol that is used for prepared statements.
This commit is contained in:
parent
8762e83485
commit
d3eb993a27
48 changed files with 2877 additions and 1659 deletions
|
@ -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;
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 \
|
||||
|
|
103
sql/field.cc
103
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());
|
||||
}
|
||||
|
||||
|
||||
|
@ -1071,6 +1066,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)
|
||||
{
|
||||
|
@ -1283,6 +1282,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)))
|
||||
{
|
||||
|
@ -1308,6 +1308,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;
|
||||
|
@ -1533,6 +1539,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;
|
||||
|
@ -1767,6 +1779,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;
|
||||
|
@ -1979,6 +1996,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;
|
||||
|
@ -2293,6 +2316,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)
|
||||
|
@ -2490,6 +2519,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)
|
||||
{
|
||||
|
@ -2812,6 +2846,7 @@ String *Field_timestamp::val_str(String *val_buffer,
|
|||
return val_buffer;
|
||||
}
|
||||
|
||||
|
||||
bool Field_timestamp::get_date(TIME *ltime, bool fuzzydate)
|
||||
{
|
||||
long temp;
|
||||
|
@ -2851,6 +2886,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;
|
||||
|
@ -2869,6 +2913,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
|
||||
|
@ -3059,6 +3104,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;
|
||||
|
@ -3961,19 +4017,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;
|
||||
}
|
||||
|
||||
|
@ -4178,6 +4230,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
|
||||
|
@ -4453,7 +4527,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
|
||||
|
|
37
sql/field.h
37
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; }
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
178
sql/item.cc
178
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,6 +625,18 @@ void Item::init_make_field(Send_field *tmp_field,
|
|||
tmp_field->flags |= UNSIGNED_FLAG;
|
||||
}
|
||||
|
||||
void Item::make_field(Send_field *tmp_field)
|
||||
{
|
||||
init_make_field(tmp_field, field_type());
|
||||
}
|
||||
|
||||
enum_field_types Item::field_type() const
|
||||
{
|
||||
return ((result_type() == STRING_RESULT) ? FIELD_TYPE_VAR_STRING :
|
||||
(result_type() == INT_RESULT) ? FIELD_TYPE_LONGLONG :
|
||||
FIELD_TYPE_DOUBLE);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
void Item_field::make_field(Send_field *tmp_field)
|
||||
{
|
||||
|
@ -638,58 +645,6 @@ void Item_field::make_field(Send_field *tmp_field)
|
|||
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)
|
||||
{
|
||||
init_make_field(tmp_field,FIELD_TYPE_DATETIME);
|
||||
}
|
||||
|
||||
|
||||
void Item_null::make_field(Send_field *tmp_field)
|
||||
{
|
||||
init_make_field(tmp_field,FIELD_TYPE_NULL);
|
||||
tmp_field->length=4;
|
||||
}
|
||||
|
||||
|
||||
void Item_func::make_field(Send_field *tmp_field)
|
||||
{
|
||||
init_make_field(tmp_field, ((result_type() == STRING_RESULT) ?
|
||||
FIELD_TYPE_VAR_STRING :
|
||||
(result_type() == INT_RESULT) ?
|
||||
FIELD_TYPE_LONGLONG : FIELD_TYPE_DOUBLE));
|
||||
}
|
||||
|
||||
void Item_avg_field::make_field(Send_field *tmp_field)
|
||||
{
|
||||
init_make_field(tmp_field,FIELD_TYPE_DOUBLE);
|
||||
}
|
||||
|
||||
void Item_std_field::make_field(Send_field *tmp_field)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
72
sql/item.h
72
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); }
|
||||
};
|
||||
|
@ -374,8 +387,8 @@ public:
|
|||
longlong val_int() { return strtoll(str_value.ptr(),(char**) 0,10); }
|
||||
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); }
|
||||
|
@ -392,7 +405,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();
|
||||
|
@ -412,7 +424,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
|
||||
|
@ -422,6 +434,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:
|
||||
|
@ -432,8 +458,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; }
|
||||
};
|
||||
|
||||
|
||||
|
@ -488,13 +514,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);
|
||||
};
|
||||
|
@ -544,6 +571,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()
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
492
sql/net_pkg.cc
492
sql/net_pkg.cc
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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 __attribute__((unused)))
|
||||
|
@ -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 __attribute__((unused)))
|
||||
|
@ -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) { str_value.copy(str,length, thd_charset()); }
|
||||
|
|
983
sql/protocol.cc
Normal file
983
sql/protocol.cc
Normal file
|
@ -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);
|
||||
}
|
131
sql/protocol.h
Normal file
131
sql/protocol.h
Normal file
|
@ -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);
|
|
@ -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);
|
||||
|
|
118
sql/slave.cc
118
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);
|
||||
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
|
||||
|
||||
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);
|
||||
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*)packet.ptr(),
|
||||
packet.length(), 0))
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
244
sql/sql_base.cc
244
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
|
||||
****************************************************************************/
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -3012,11 +3012,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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
642
sql/sql_show.cc
642
sql/sql_show.cc
File diff suppressed because it is too large
Load diff
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
17
sql/time.cc
17
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;
|
||||
}
|
||||
|
|
705
tests/fork_big2.pl
Normal file
705
tests/fork_big2.pl
Normal file
|
@ -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;
|
||||
}
|
Loading…
Reference in a new issue