Commit 5a33842a authored by venu@myvenu.com's avatar venu@myvenu.com

sql_error.cc, sql_prepare.cc:

  new file

  Client-server protocol 4.1 changes - Server side:

 * Enhanced metadata information:
    - SHOW [COUNT(*)] ERRORS [LIMIT [offset,] rows]
    - SHOW [COUNT(*)] WARNING [LIMIT [offset,] rows]
    - SHOW TABLE TYPES
    - SHOW PRIVILEGES
    - SHOW COLUMN TYPES (Not fully implemented)

 * Prepared execution
 * Long data handling in pieces
 * And other misc changes
parent 75959e6e
...@@ -67,6 +67,7 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc \ ...@@ -67,6 +67,7 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc \
mysqld.cc password.c hash_filo.cc hostname.cc \ mysqld.cc password.c hash_filo.cc hostname.cc \
convert.cc sql_parse.cc sql_yacc.yy \ convert.cc sql_parse.cc sql_yacc.yy \
sql_base.cc table.cc sql_select.cc sql_insert.cc \ sql_base.cc table.cc sql_select.cc sql_insert.cc \
sql_prepare.cc sql_error.cc \
sql_update.cc sql_delete.cc uniques.cc sql_do.cc \ sql_update.cc sql_delete.cc uniques.cc sql_do.cc \
procedure.cc item_uniq.cc sql_test.cc \ procedure.cc item_uniq.cc sql_test.cc \
log.cc log_event.cc init.cc derror.cc sql_acl.cc \ log.cc log_event.cc init.cc derror.cc sql_acl.cc \
......
...@@ -279,8 +279,10 @@ void Field_num::add_zerofill_and_unsigned(String &res) const ...@@ -279,8 +279,10 @@ void Field_num::add_zerofill_and_unsigned(String &res) const
void Field_num::make_field(Send_field *field) void Field_num::make_field(Send_field *field)
{ {
field->db_name=table->table_cache_key ? table->table_cache_key : "";
field->org_table_name=table->real_name;
field->table_name=table_name; field->table_name=table_name;
field->col_name=field_name; field->col_name=field->org_col_name=field_name;
field->length=field_length; field->length=field_length;
field->type=type(); field->type=type();
field->flags=table->maybe_null ? (flags & ~NOT_NULL_FLAG) : flags; field->flags=table->maybe_null ? (flags & ~NOT_NULL_FLAG) : flags;
...@@ -290,8 +292,10 @@ void Field_num::make_field(Send_field *field) ...@@ -290,8 +292,10 @@ void Field_num::make_field(Send_field *field)
void Field_str::make_field(Send_field *field) void Field_str::make_field(Send_field *field)
{ {
field->db_name=table->table_cache_key ? table->table_cache_key : "";
field->org_table_name=table->real_name;
field->table_name=table_name; field->table_name=table_name;
field->col_name=field_name; field->col_name=field->org_col_name=field_name;
field->length=field_length; field->length=field_length;
field->type=type(); field->type=type();
field->flags=table->maybe_null ? (flags & ~NOT_NULL_FLAG) : flags; field->flags=table->maybe_null ? (flags & ~NOT_NULL_FLAG) : flags;
......
...@@ -1038,7 +1038,9 @@ public: ...@@ -1038,7 +1038,9 @@ public:
class Send_field { class Send_field {
public: public:
const char *table_name,*col_name; const char *db_name;
const char *table_name,*org_table_name;
const char *col_name,*org_col_name;
uint length,flags,decimals; uint length,flags,decimals;
enum_field_types type; enum_field_types type;
Send_field() {} Send_field() {}
......
...@@ -287,6 +287,140 @@ String *Item_null::val_str(String *str) ...@@ -287,6 +287,140 @@ String *Item_null::val_str(String *str)
{ null_value=1; return 0;} { null_value=1; return 0;}
/* Item_param related */
void Item_param::set_null()
{
maybe_null=null_value=1;
}
void Item_param::set_int(longlong i)
{
int_value=(longlong)i;
item_result_type = INT_RESULT;
item_type = INT_ITEM;
}
void Item_param::set_double(double i)
{
double value = (double)i;
real_value=value;
item_result_type = REAL_RESULT;
item_type = REAL_ITEM;
}
void Item_param::set_double(float i)
{
float value = (float)i;
real_value=(double)value;
item_result_type = REAL_RESULT;
item_type = REAL_ITEM;
}
void Item_param::set_value(const char *str, uint length)
{
str_value.set(str,length,default_charset_info);
item_result_type = STRING_RESULT;
item_type = STRING_ITEM;
}
void Item_param::set_longdata(const char *str, ulong length)
{
/* TODO: Fix this for binary handling by making use of
buffer_type..
*/
str_value.append(str,length);
}
void Item_param::set_long_end()
{
long_data_supplied = true;
item_result_type = STRING_RESULT;
};
bool Item_param::save_in_field(Field *field)
{
if (null_value)
return set_field_to_null(field);
field->set_notnull();
if (item_result_type == INT_RESULT)
{
longlong nr=val_int();
field->store(nr);
return 0;
}
if (item_result_type == REAL_RESULT)
{
double nr=val();
field->store(nr);
return 0;
}
String *result;
CHARSET_INFO *cs=default_charset_info;//fix this
result=val_str(&str_value);
field->store(result->ptr(),result->length(),cs);
return 0;
}
void Item_param::make_field(Send_field *tmp_field)
{
init_make_field(tmp_field,FIELD_TYPE_STRING);
}
double Item_param::val()
{
/* Cross check whether we need need this conversions ? or direct
return(real_value) is enough ?
*/
switch(item_result_type) {
case STRING_RESULT:
return (double)atof(str_value.ptr());
case INT_RESULT:
return (double)int_value;
default:
return real_value;
}
}
longlong Item_param::val_int()
{
/* Cross check whether we need need this conversions ? or direct
return(int_value) is enough ?
*/
switch(item_result_type) {
case STRING_RESULT:
return (longlong)strtoll(str_value.ptr(),(char**) 0,10);
case REAL_RESULT:
return (longlong) (real_value+(real_value > 0 ? 0.5 : -0.5));
default:
return int_value;
}
}
String *Item_param::val_str(String* str)
{
/* Cross check whether we need need this conversions ? or direct
return(&str_value) is enough ?
*/
switch(item_result_type) {
case INT_RESULT:
str->set(int_value);
return str;
case REAL_RESULT:
str->set(real_value);
return str;
default:
return (String*) &str_value;
}
}
/* End of Item_param related */
void Item_copy_string::copy() void Item_copy_string::copy()
{ {
String *res=item->val_str(&str_value); String *res=item->val_str(&str_value);
...@@ -374,6 +508,9 @@ bool Item_field::fix_fields(THD *thd,TABLE_LIST *tables) ...@@ -374,6 +508,9 @@ bool Item_field::fix_fields(THD *thd,TABLE_LIST *tables)
void Item::init_make_field(Send_field *tmp_field, void Item::init_make_field(Send_field *tmp_field,
enum enum_field_types field_type) enum enum_field_types field_type)
{ {
tmp_field->db_name=(char*) "";
tmp_field->org_table_name=(char*) "";
tmp_field->org_col_name=(char*) "";
tmp_field->table_name=(char*) ""; tmp_field->table_name=(char*) "";
tmp_field->col_name=name; tmp_field->col_name=name;
tmp_field->flags=maybe_null ? 0 : NOT_NULL_FLAG; tmp_field->flags=maybe_null ? 0 : NOT_NULL_FLAG;
......
...@@ -155,6 +155,40 @@ public: ...@@ -155,6 +155,40 @@ public:
bool is_null() { return 1; } bool is_null() { return 1; }
}; };
class Item_param :public Item
{
public:
longlong int_value;
double real_value;
enum Item_result item_result_type;
enum Type item_type;
enum enum_field_types buffer_type;
my_bool long_data_supplied;
Item_param(char *name_par=0){
name= name_par ? name_par : (char*) "?";
long_data_supplied = false;
item_type = STRING_ITEM; item_result_type = STRING_RESULT;
}
enum Type type() const { return item_type; }
double val();
longlong val_int();
String *val_str(String*);
void make_field(Send_field *field);
bool save_in_field(Field *field);
void set_null();
void set_int(longlong i);
void set_double(float i);
void set_double(double i);
void set_value(const char *str, uint length);
void set_long_str(const char *str, ulong length);
void set_long_binary(const char *str, ulong length);
void set_longdata(const char *str, ulong length);
void set_long_end();
enum Item_result result_type () const
{ return item_result_type; }
Item *new_item() { return new Item_param(name); }
};
class Item_int :public Item class Item_int :public Item
{ {
......
...@@ -60,8 +60,9 @@ void Item_sum::make_field(Send_field *tmp_field) ...@@ -60,8 +60,9 @@ void Item_sum::make_field(Send_field *tmp_field)
result_type() == REAL_RESULT ? FIELD_TYPE_DOUBLE : result_type() == REAL_RESULT ? FIELD_TYPE_DOUBLE :
FIELD_TYPE_VAR_STRING); FIELD_TYPE_VAR_STRING);
} }
tmp_field->table_name=(char*)""; tmp_field->db_name=(char*)"";
tmp_field->col_name=name; tmp_field->org_table_name=tmp_field->table_name=(char*)"";
tmp_field->org_col_name=tmp_field->col_name=name;
} }
void Item_sum::print(String *str) void Item_sum::print(String *str)
......
...@@ -129,6 +129,7 @@ static SYMBOL symbols[] = { ...@@ -129,6 +129,7 @@ static SYMBOL symbols[] = {
{ "DROP", SYM(DROP),0,0}, { "DROP", SYM(DROP),0,0},
{ "DUMPFILE", SYM(DUMPFILE),0,0}, { "DUMPFILE", SYM(DUMPFILE),0,0},
{ "DYNAMIC", SYM(DYNAMIC_SYM),0,0}, { "DYNAMIC", SYM(DYNAMIC_SYM),0,0},
{ "ERRORS", SYM(ERRORS),0,0},
{ "END", SYM(END),0,0}, { "END", SYM(END),0,0},
{ "ELSE", SYM(ELSE),0,0}, { "ELSE", SYM(ELSE),0,0},
{ "ESCAPE", SYM(ESCAPE_SYM),0,0}, { "ESCAPE", SYM(ESCAPE_SYM),0,0},
...@@ -327,6 +328,7 @@ static SYMBOL symbols[] = { ...@@ -327,6 +328,7 @@ static SYMBOL symbols[] = {
{ "SQL_BUFFER_RESULT", SYM(SQL_BUFFER_RESULT),0,0}, { "SQL_BUFFER_RESULT", SYM(SQL_BUFFER_RESULT),0,0},
{ "SQL_CACHE", SYM(SQL_CACHE_SYM), 0, 0}, { "SQL_CACHE", SYM(SQL_CACHE_SYM), 0, 0},
{ "SQL_CALC_FOUND_ROWS", SYM(SQL_CALC_FOUND_ROWS),0,0}, { "SQL_CALC_FOUND_ROWS", SYM(SQL_CALC_FOUND_ROWS),0,0},
{ "SQL_ERROR_COUNT", SYM(SQL_ERROR_COUNT),0,0},
{ "SQL_LOG_BIN", SYM(SQL_LOG_BIN),0,0}, { "SQL_LOG_BIN", SYM(SQL_LOG_BIN),0,0},
{ "SQL_LOG_OFF", SYM(SQL_LOG_OFF),0,0}, { "SQL_LOG_OFF", SYM(SQL_LOG_OFF),0,0},
{ "SQL_LOG_UPDATE", SYM(SQL_LOG_UPDATE),0,0}, { "SQL_LOG_UPDATE", SYM(SQL_LOG_UPDATE),0,0},
...@@ -366,6 +368,7 @@ static SYMBOL symbols[] = { ...@@ -366,6 +368,7 @@ static SYMBOL symbols[] = {
{ "TRUNCATE", SYM(TRUNCATE_SYM),0,0}, { "TRUNCATE", SYM(TRUNCATE_SYM),0,0},
{ "TO", SYM(TO_SYM),0,0}, { "TO", SYM(TO_SYM),0,0},
{ "TYPE", SYM(TYPE_SYM),0,0}, { "TYPE", SYM(TYPE_SYM),0,0},
{ "TYPES", SYM(TYPES_SYM),0,0},
{ "UNCOMMITTED", SYM(UNCOMMITTED_SYM),0,0}, { "UNCOMMITTED", SYM(UNCOMMITTED_SYM),0,0},
{ "UNION", SYM(UNION_SYM),0,0}, { "UNION", SYM(UNION_SYM),0,0},
{ "UNIQUE", SYM(UNIQUE_SYM),0,0}, { "UNIQUE", SYM(UNIQUE_SYM),0,0},
...@@ -381,6 +384,7 @@ static SYMBOL symbols[] = { ...@@ -381,6 +384,7 @@ static SYMBOL symbols[] = {
{ "VARIABLES", SYM(VARIABLES),0,0}, { "VARIABLES", SYM(VARIABLES),0,0},
{ "VARYING", SYM(VARYING),0,0}, { "VARYING", SYM(VARYING),0,0},
{ "VARBINARY", SYM(VARBINARY),0,0}, { "VARBINARY", SYM(VARBINARY),0,0},
{ "WARNINGS", SYM(WARNINGS),0,0},
{ "WITH", SYM(WITH),0,0}, { "WITH", SYM(WITH),0,0},
{ "WORK", SYM(WORK_SYM),0,0}, { "WORK", SYM(WORK_SYM),0,0},
{ "WRITE", SYM(WRITE_SYM),0,0}, { "WRITE", SYM(WRITE_SYM),0,0},
......
...@@ -287,6 +287,8 @@ inline THD *_current_thd(void) ...@@ -287,6 +287,8 @@ inline THD *_current_thd(void)
#define query_cache_invalidate_by_MyISAM_filename_ref NULL #define query_cache_invalidate_by_MyISAM_filename_ref NULL
#endif /*HAVE_QUERY_CACHE*/ #endif /*HAVE_QUERY_CACHE*/
#define prepare_execute(A) ((A)->command == COM_EXECUTE)
int mysql_create_db(THD *thd, char *db, uint create_info, bool silent); int mysql_create_db(THD *thd, char *db, uint create_info, bool silent);
int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent); int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent);
void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags); void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags);
...@@ -363,6 +365,8 @@ bool net_store_data(String *packet, CONVERT *convert, const char *from); ...@@ -363,6 +365,8 @@ bool net_store_data(String *packet, CONVERT *convert, const char *from);
SORT_FIELD * make_unireg_sortorder(ORDER *order, uint *length); SORT_FIELD * make_unireg_sortorder(ORDER *order, uint *length);
int setup_order(THD *thd,TABLE_LIST *tables, List<Item> &fields, int setup_order(THD *thd,TABLE_LIST *tables, List<Item> &fields,
List <Item> &all_fields, ORDER *order); List <Item> &all_fields, ORDER *order);
int setup_group(THD *thd,TABLE_LIST *tables,List<Item> &fields,
List<Item> &all_fields, ORDER *order, bool *hidden_group_fields);
int handle_select(THD *thd, LEX *lex, select_result *result); int handle_select(THD *thd, LEX *lex, select_result *result);
int mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &list,COND *conds, int mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &list,COND *conds,
...@@ -455,7 +459,7 @@ bool load_des_key_file(const char *file_name); ...@@ -455,7 +459,7 @@ bool load_des_key_file(const char *file_name);
/* sql_do.cc */ /* sql_do.cc */
int mysql_do(THD *thd, List<Item> &values); int mysql_do(THD *thd, List<Item> &values);
/* sql_list.c */ /* sql_show.c */
int mysqld_show_dbs(THD *thd,const char *wild); int mysqld_show_dbs(THD *thd,const char *wild);
int mysqld_show_open_tables(THD *thd,const char *wild); int mysqld_show_open_tables(THD *thd,const char *wild);
int mysqld_show_tables(THD *thd,const char *db,const char *wild); int mysqld_show_tables(THD *thd,const char *db,const char *wild);
...@@ -473,6 +477,24 @@ int mysqld_show_status(THD *thd); ...@@ -473,6 +477,24 @@ int mysqld_show_status(THD *thd);
int mysqld_show_variables(THD *thd,const char *wild); int mysqld_show_variables(THD *thd,const char *wild);
int mysqld_show(THD *thd, const char *wild, show_var_st *variables); int mysqld_show(THD *thd, const char *wild, show_var_st *variables);
int mysqld_show_charsets(THD *thd,const char *wild); int mysqld_show_charsets(THD *thd,const char *wild);
int mysqld_show_privileges(THD *thd);
int mysqld_show_column_types(THD *thd);
/* sql_prepare.cc */
void mysql_com_prepare(THD *thd,char*packet,uint packet_length);
void mysql_init_query(THD *thd);/* sql_parse. cc */
void mysql_com_execute(THD *thd);
void mysql_com_longdata(THD *thd);
int check_insert_fields(THD *thd,TABLE *table,List<Item> &fields,
List<Item> &values, ulong counter);
/* sql_error.cc */
void push_error(uint code, const char *msg);
void push_warning(uint code, const char *msg);
int mysqld_show_warnings(THD *thd);
int mysqld_show_errors(THD *thd);
int mysqld_show_warnings_count(THD *thd);
int mysqld_show_errors_count(THD *);
/* sql_handler.cc */ /* sql_handler.cc */
int mysql_ha_open(THD *thd, TABLE_LIST *tables); int mysql_ha_open(THD *thd, TABLE_LIST *tables);
...@@ -654,6 +676,10 @@ extern const char *default_tx_isolation_name; ...@@ -654,6 +676,10 @@ extern const char *default_tx_isolation_name;
extern String empty_string; extern String empty_string;
extern struct show_var_st init_vars[]; extern struct show_var_st init_vars[];
extern struct show_var_st status_vars[]; extern struct show_var_st status_vars[];
extern struct show_table_type_st table_type_vars[];
extern SHOW_COMP_OPTION have_isam;
extern SHOW_COMP_OPTION have_innodb;
extern SHOW_COMP_OPTION have_berkeley_db;
extern enum db_type default_table_type; extern enum db_type default_table_type;
extern enum enum_tx_isolation default_tx_isolation; extern enum enum_tx_isolation default_tx_isolation;
extern char glob_hostname[FN_REFLEN]; extern char glob_hostname[FN_REFLEN];
......
...@@ -48,6 +48,7 @@ void send_error(NET *net, uint sql_errno, const char *err) ...@@ -48,6 +48,7 @@ void send_error(NET *net, uint sql_errno, const char *err)
} }
} }
} }
push_error(sql_errno, err);
if (net->vio == 0) if (net->vio == 0)
{ {
if (thd && thd->bootstrap) if (thd && thd->bootstrap)
...@@ -83,6 +84,13 @@ void send_error(NET *net, uint sql_errno, const char *err) ...@@ -83,6 +84,13 @@ void send_error(NET *net, uint sql_errno, const char *err)
void send_warning(NET *net, uint sql_errno, const char *err) void send_warning(NET *net, uint sql_errno, const char *err)
{ {
DBUG_ENTER("send_warning"); DBUG_ENTER("send_warning");
push_warning(sql_errno, err ? err : ER(sql_errno));
/*
TODO :
Try to return ok with warning status to client, instead
of returning error ..
*/
send_error(net,sql_errno,err); send_error(net,sql_errno,err);
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
...@@ -123,6 +131,7 @@ net_printf(NET *net, uint errcode, ...) ...@@ -123,6 +131,7 @@ net_printf(NET *net, uint errcode, ...)
length=sizeof(net->last_error)-1; /* purecov: inspected */ length=sizeof(net->last_error)-1; /* purecov: inspected */
va_end(args); va_end(args);
push_error(errcode, text_pos);
if (net->vio == 0) if (net->vio == 0)
{ {
if (thd && thd->bootstrap) if (thd && thd->bootstrap)
......
...@@ -179,56 +179,135 @@ OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *wild) ...@@ -179,56 +179,135 @@ OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *wild)
DBUG_RETURN(open_list); DBUG_RETURN(open_list);
} }
/*
/****************************************************************************** Send name and type of result to client.
** Send name and type of result to client. Sum fields has table name empty and field_name.
** Sum fields has table name empty and field_name. flag is a bit mask with the following functions:
** flag is a bit mask with the following functions: 1 send number of rows
** 1 send number of rows 2 send default values
** 2 send default values 4 Don't convert field names
** 4 Don't convert field names */
******************************************************************************/
bool bool
send_fields(THD *thd,List<Item> &list,uint flag) send_convert_fields(THD *thd,List<Item> &list,CONVERT *convert,uint flag)
{ {
List_iterator_fast<Item> it(list); List_iterator_fast<Item> it(list);
Item *item; Item *item;
char buff[80]; char buff[80];
CONVERT *convert= (flag & 4) ? (CONVERT*) 0 : thd->convert_set;
DBUG_ENTER("send_fields");
String tmp((char*) buff,sizeof(buff),default_charset_info); String tmp((char*) buff,sizeof(buff),default_charset_info);
String *res,*packet= &thd->packet; String *res,*packet= &thd->packet;
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));
}
while ((item=it++)) while ((item=it++))
{ {
char *pos; char *pos;
Send_field field; Send_field field;
item->make_field(&field); item->make_field(&field);
packet->length(0); packet->length(0);
if (convert) 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))
return 1;
}
else
{ {
if (convert->store(packet,field.table_name, if (convert->store(packet,field.table_name,
(uint) strlen(field.table_name)) || (uint) strlen(field.table_name)) ||
convert->store(packet,field.col_name, convert->store(packet,field.col_name,
(uint) strlen(field.col_name)) || (uint) strlen(field.col_name)) ||
packet->realloc(packet->length()+10)) packet->realloc(packet->length()+10))
goto err; 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; /* purecov: inspected */
}
return 0;
}
/*
Send name and type of result to client.
Sum fields has table name empty and field_name
flag is a bit mask with the following functios:
1 send number of rows
2 send default values
4 Don't convert field names
*/
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) || else
{
if (net_store_data(packet,field.table_name) ||
net_store_data(packet,field.col_name) || net_store_data(packet,field.col_name) ||
packet->realloc(packet->length()+10)) packet->realloc(packet->length()+10))
goto err; /* purecov: inspected */ return 1;
}
pos= (char*) packet->ptr()+packet->length(); pos= (char*) packet->ptr()+packet->length();
if (!(thd->client_capabilities & CLIENT_LONG_FLAG)) if (!(thd->client_capabilities & CLIENT_LONG_FLAG))
...@@ -250,19 +329,58 @@ send_fields(THD *thd,List<Item> &list,uint flag) ...@@ -250,19 +329,58 @@ send_fields(THD *thd,List<Item> &list,uint flag)
if (!(res=item->val_str(&tmp))) if (!(res=item->val_str(&tmp)))
{ {
if (net_store_null(packet)) if (net_store_null(packet))
goto err; return 1;
} }
else if (net_store_data(packet,res->ptr(),res->length())) else if (net_store_data(packet,res->ptr(),res->length()))
goto err; return 1;
} }
if (my_net_write(&thd->net, (char*) packet->ptr(),packet->length())) if (my_net_write(&thd->net, (char*) packet->ptr(),packet->length()))
break; /* purecov: inspected */ break;
} }
send_eof(&thd->net,1); return 0;
DBUG_RETURN(0); }
err:
/******************************************************************************
** Send name and type of result to client.
** Sum fields has table name empty and field_name.
** flag is a bit mask with the following functions:
** 1 send number of rows
** 2 send default values
** 4 Don't convert field names
******************************************************************************/
bool
send_fields(THD *thd,List<Item> &list,uint flag)
{
List_iterator_fast<Item> it(list);
char buff[80];
CONVERT *convert= (flag & 4) ? (CONVERT*) 0 : thd->convert_set;
String tmp((char*) buff,sizeof(buff),default_charset_info);
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 diffrent functions
*/
if (convert && send_convert_fields(thd,list,convert,flag))
goto err;
else if(send_non_convert_fields(thd,list,flag))
goto err;
send_eof(&thd->net);
return 0;
err:
send_error(&thd->net,ER_OUT_OF_RESOURCES); /* purecov: inspected */ send_error(&thd->net,ER_OUT_OF_RESOURCES); /* purecov: inspected */
DBUG_RETURN(1); /* purecov: inspected */ return 1; /* purecov: inspected */
} }
......
...@@ -140,6 +140,7 @@ THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0), ...@@ -140,6 +140,7 @@ THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0),
command=COM_CONNECT; command=COM_CONNECT;
set_query_id=1; set_query_id=1;
default_select_limit= HA_POS_ERROR; default_select_limit= HA_POS_ERROR;
max_error_count=max_warning_count=MYSQL_DEFAULT_ERROR_COUNT;
max_join_size= ((::max_join_size != ~ (ulong) 0L) ? ::max_join_size : max_join_size= ((::max_join_size != ~ (ulong) 0L) ? ::max_join_size :
HA_POS_ERROR); HA_POS_ERROR);
db_access=NO_ACCESS; db_access=NO_ACCESS;
...@@ -147,6 +148,7 @@ THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0), ...@@ -147,6 +148,7 @@ THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0),
/* Initialize sub structures */ /* Initialize sub structures */
bzero((char*) &mem_root,sizeof(mem_root)); bzero((char*) &mem_root,sizeof(mem_root));
bzero((char*) &transaction.mem_root,sizeof(transaction.mem_root)); bzero((char*) &transaction.mem_root,sizeof(transaction.mem_root));
bzero((char*) &con_root,sizeof(con_root));
user_connect=(USER_CONN *)0; user_connect=(USER_CONN *)0;
hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0, hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0,
(hash_get_key) get_var_key, (hash_get_key) get_var_key,
...@@ -223,6 +225,7 @@ THD::~THD() ...@@ -223,6 +225,7 @@ THD::~THD()
safeFree(db); safeFree(db);
safeFree(ip); safeFree(ip);
free_root(&mem_root,MYF(0)); free_root(&mem_root,MYF(0));
free_root(&con_root,MYF(0));
free_root(&transaction.mem_root,MYF(0)); free_root(&transaction.mem_root,MYF(0));
mysys_var=0; // Safety (shouldn't be needed) mysys_var=0; // Safety (shouldn't be needed)
#ifdef SIGNAL_WITH_VIO_CLOSE #ifdef SIGNAL_WITH_VIO_CLOSE
......
...@@ -289,7 +289,30 @@ public: ...@@ -289,7 +289,30 @@ public:
i_string_pair():key(0),val(0) { } i_string_pair():key(0),val(0) { }
i_string_pair(char* key_arg, char* val_arg) : key(key_arg),val(val_arg) {} i_string_pair(char* key_arg, char* val_arg) : key(key_arg),val(val_arg) {}
}; };
#define MYSQL_DEFAULT_ERROR_COUNT 500
class mysql_st_error
{
public:
uint code;
char msg[MYSQL_ERRMSG_SIZE+1];
char query[NAME_LEN+1];
static void *operator new(size_t size)
{
return (void*)my_malloc((uint)size, MYF(MY_WME | MY_FAE));
}
static void operator delete(void* ptr_arg, size_t size)
{
my_free((gptr)ptr_arg, MYF(MY_WME|MY_ALLOW_ZERO_PTR));
}
mysql_st_error(uint ecode, const char *emsg, const char *equery)
{
code = ecode;
strmov(msg, emsg);
strnmov(query, equery ? equery : "", NAME_LEN);
}
};
class delayed_insert; class delayed_insert;
...@@ -308,6 +331,7 @@ public: ...@@ -308,6 +331,7 @@ public:
NET net; // client connection descriptor NET net; // client connection descriptor
LEX lex; // parse tree descriptor LEX lex; // parse tree descriptor
MEM_ROOT mem_root; // 1 command-life memory MEM_ROOT mem_root; // 1 command-life memory
MEM_ROOT con_root; // connection-life memory
HASH user_vars; // hash for user variables HASH user_vars; // hash for user variables
String packet; // buffer used for network I/O String packet; // buffer used for network I/O
struct sockaddr_in remote; // client socket address struct sockaddr_in remote; // client socket address
...@@ -410,7 +434,8 @@ public: ...@@ -410,7 +434,8 @@ public:
max_join_size, sent_row_count, examined_row_count; max_join_size, sent_row_count, examined_row_count;
table_map used_tables; table_map used_tables;
USER_CONN *user_connect; USER_CONN *user_connect;
ulong query_id,version, inactive_timeout,options,thread_id; ulong query_id,version, inactive_timeout,options,thread_id,
max_error_count, max_warning_count;
long dbug_thread_id; long dbug_thread_id;
pthread_t real_id; pthread_t real_id;
uint current_tablenr,tmp_table,cond_count,col_access; uint current_tablenr,tmp_table,cond_count,col_access;
...@@ -428,8 +453,13 @@ public: ...@@ -428,8 +453,13 @@ public:
bool query_error, bootstrap, cleanup_done; bool query_error, bootstrap, cleanup_done;
bool safe_to_cache_query; bool safe_to_cache_query;
bool volatile killed; bool volatile killed;
// TRUE when having fix field called bool having_fix_field; //TRUE when having fix field called
bool having_fix_field; bool prepare_command;
ulong param_count,current_param_number;
Error<mysql_st_error> err_list;
Error<mysql_st_error> warn_list;
Item_param *current_param;
/* /*
If we do a purge of binary logs, log index info of the threads If we do a purge of binary logs, log index info of the threads
that are currently reading it needs to be adjusted. To do that that are currently reading it needs to be adjusted. To do that
......
/* Copyright (C) 1995-2002 MySQL 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
*/
/**********************************************************************
This file contains the implementation of error and warnings related
- Whenever an error or warning occured, it pushes the same to
the respective list along with sending it to client.
- When client requests the information using SHOW command, then
server processes from this list and returns back in the form of
resultset.
syntax : SHOW [COUNT(*)] ERRORS [LIMIT [offset,] rows]
SHOW [COUNT(*)] WARNINGS [LIMIT [offset,] rows]
***********************************************************************/
/* Handles errors and warnings .. */
#include "mysql_priv.h"
/*
Push the error to error list
*/
void push_error(uint code, const char *msg)
{
THD *thd=current_thd;
mysql_st_error *err = new mysql_st_error(code,msg,(const char*)thd->query);
if (thd->err_list.elements >= thd->max_error_count)
{
/* Remove the old elements and always maintain the max size
equal to sql_error_count.
If one max_error_count using sets sql_error_count less than
the current list size, then make sure it always grows upto
sql_error_count size only
** BUG ** : Doesn't work in removing the old one
from the list, and thus SET SQL_ERROR_COUNT=x doesn't work
*/
for (uint count=thd->err_list.elements-1;
count <= thd->max_error_count-1; count++)
{
thd->err_list.remove_last();
}
}
thd->err_list.push_front(err);
}
/*
Push the warning to warning list
*/
void push_warning(uint code, const char *msg)
{
THD *thd=current_thd;
mysql_st_error *warn = new mysql_st_error(code,msg,(const char *)thd->query);
if (thd->warn_list.elements >= thd->max_warning_count)
{
/* Remove the old elements and always maintian the max size
equal to sql_error_count
*/
for (uint count=thd->warn_list.elements;
count <= thd->max_warning_count-1; count++)
{
thd->warn_list.remove_last();
}
}
thd->warn_list.push_front(warn);
}
/*
List all errors
*/
int mysqld_show_errors(THD *thd)
{
List<Item> field_list;
DBUG_ENTER("mysqld_show_errors");
field_list.push_back(new Item_int("CODE",0,4));
field_list.push_back(new Item_empty_string("MESSAGE",MYSQL_ERRMSG_SIZE));
field_list.push_back(new Item_empty_string("QUERY",NAME_LEN));
if (send_fields(thd,field_list,1))
DBUG_RETURN(1);
mysql_st_error *err;
SELECT_LEX *sel=&thd->lex.select_lex;
ha_rows offset = sel->offset_limit,limit = sel->select_limit;
uint num_rows = 0;
Error_iterator<mysql_st_error> it(thd->err_list);
while(offset-- && (err = it++));/* Should be fixed with overloaded
operator '+' or with new funtion
goto() in list ?
*/
while((num_rows++ < limit) && (err = it++))
{
thd->packet.length(0);
net_store_data(&thd->packet,(uint32)err->code);
net_store_data(&thd->packet,err->msg);
net_store_data(&thd->packet,err->query);
if (my_net_write(&thd->net,(char*)thd->packet.ptr(),thd->packet.length()))
DBUG_RETURN(-1);
}
send_eof(&thd->net);
DBUG_RETURN(0);
}
/*
Return errors count
*/
int mysqld_show_errors_count(THD *thd)
{
List<Item> field_list;
DBUG_ENTER("mysqld_show_errors_count");
field_list.push_back(new Item_int("COUNT(*)",0,4));
if (send_fields(thd,field_list,1))
DBUG_RETURN(1);
thd->packet.length(0);
net_store_data(&thd->packet,(uint32)thd->err_list.elements);
if (my_net_write(&thd->net,(char*) thd->packet.ptr(),thd->packet.length()))
DBUG_RETURN(-1);
send_eof(&thd->net);
DBUG_RETURN(0);
}
/*
List all warnings
*/
int mysqld_show_warnings(THD *thd)
{
List<Item> field_list;
DBUG_ENTER("mysqld_show_warnings");
field_list.push_back(new Item_int("CODE",0,21));
field_list.push_back(new Item_empty_string("MESSAGE",MYSQL_ERRMSG_SIZE));
field_list.push_back(new Item_empty_string("QUERY",NAME_LEN));
if (send_fields(thd,field_list,1))
DBUG_RETURN(1);
mysql_st_error *warn;
SELECT_LEX *sel=&thd->lex.select_lex;
ha_rows offset = sel->offset_limit,limit = sel->select_limit;
uint num_rows = 0;
Error_iterator<mysql_st_error> it(thd->warn_list);
while(offset-- && (warn = it++));
while((num_rows++ < limit) && (warn = it++))
{
thd->packet.length(0);
net_store_data(&thd->packet,(uint32)warn->code);
net_store_data(&thd->packet,warn->msg);
net_store_data(&thd->packet,warn->query);
if (my_net_write(&thd->net,(char*) thd->packet.ptr(),thd->packet.length()))
DBUG_RETURN(-1);
}
send_eof(&thd->net);
DBUG_RETURN(0);
}
/*
Return warnings count
*/
int mysqld_show_warnings_count(THD *thd)
{
List<Item> field_list;
DBUG_ENTER("mysqld_show_warnings_count");
field_list.push_back(new Item_int("COUNT(*)",0,21));
if (send_fields(thd,field_list,1))
DBUG_RETURN(1);
thd->packet.length(0);
net_store_data(&thd->packet,(uint32)thd->warn_list.elements);
if (my_net_write(&thd->net,(char*)thd->packet.ptr(),thd->packet.length()))
DBUG_RETURN(-1);
send_eof(&thd->net);
DBUG_RETURN(0);
}
...@@ -44,7 +44,7 @@ static void unlink_blobs(register TABLE *table); ...@@ -44,7 +44,7 @@ static void unlink_blobs(register TABLE *table);
Resets form->time_stamp if a timestamp value is set Resets form->time_stamp if a timestamp value is set
*/ */
static int int
check_insert_fields(THD *thd,TABLE *table,List<Item> &fields, check_insert_fields(THD *thd,TABLE *table,List<Item> &fields,
List<Item> &values, ulong counter) List<Item> &values, ulong counter)
{ {
......
...@@ -57,8 +57,10 @@ enum enum_sql_command { ...@@ -57,8 +57,10 @@ enum enum_sql_command {
SQLCOM_HA_OPEN, SQLCOM_HA_CLOSE, SQLCOM_HA_READ, SQLCOM_HA_OPEN, SQLCOM_HA_CLOSE, SQLCOM_HA_READ,
SQLCOM_SHOW_SLAVE_HOSTS, SQLCOM_DELETE_MULTI, SQLCOM_MULTI_UPDATE, SQLCOM_SHOW_SLAVE_HOSTS, SQLCOM_DELETE_MULTI, SQLCOM_MULTI_UPDATE,
SQLCOM_SHOW_BINLOG_EVENTS, SQLCOM_SHOW_NEW_MASTER, SQLCOM_DO, SQLCOM_SHOW_BINLOG_EVENTS, SQLCOM_SHOW_NEW_MASTER, SQLCOM_DO,
SQLCOM_EMPTY_QUERY, SQLCOM_END, SQLCOM_SHOW_WARNS, SQLCOM_SHOW_WARNS_COUNT,
SQLCOM_END SQLCOM_EMPTY_QUERY, SQLCOM_SHOW_ERRORS,
SQLCOM_SHOW_ERRORS_COUNT, SQLCOM_SHOW_COLUMN_TYPES,
SQLCOM_SHOW_TABLE_TYPES, SQLCOM_SHOW_PRIVILEGES
}; };
enum lex_states { STATE_START, STATE_CHAR, STATE_IDENT, enum lex_states { STATE_START, STATE_CHAR, STATE_IDENT,
...@@ -318,6 +320,7 @@ typedef struct st_lex { ...@@ -318,6 +320,7 @@ typedef struct st_lex {
List<Item> *insert_list,field_list,value_list; List<Item> *insert_list,field_list,value_list;
List<List_item> many_values; List<List_item> many_values;
List<Set_option> option_list; List<Set_option> option_list;
List<Item> param_list;
SQL_LIST proc_list, auxilliary_table_list; SQL_LIST proc_list, auxilliary_table_list;
TYPELIB *interval; TYPELIB *interval;
create_field *last_field; create_field *last_field;
......
...@@ -122,11 +122,14 @@ public: ...@@ -122,11 +122,14 @@ public:
last= &first; last= &first;
return tmp->info; return tmp->info;
} }
inline list_node* last_node() { return *last; }
inline list_node* first_node() { return first;}
inline void *head() { return first->info; } inline void *head() { return first->info; }
inline void **head_ref() { return first != &end_of_list ? &first->info : 0; } inline void **head_ref() { return first != &end_of_list ? &first->info : 0; }
inline bool is_empty() { return first == &end_of_list ; } inline bool is_empty() { return first == &end_of_list ; }
inline list_node *last_ref() { return &end_of_list; } inline list_node *last_ref() { return &end_of_list; }
friend class base_list_iterator; friend class base_list_iterator;
friend class error_list;
protected: protected:
void after(void *info,list_node *node) void after(void *info,list_node *node)
...@@ -204,6 +207,7 @@ public: ...@@ -204,6 +207,7 @@ public:
{ {
return el == &list->last_ref()->next; return el == &list->last_ref()->next;
} }
friend class error_list_iterator;
}; };
...@@ -356,3 +360,120 @@ public: ...@@ -356,3 +360,120 @@ public:
I_List_iterator(I_List<T> &a) : base_ilist_iterator(a) {} I_List_iterator(I_List<T> &a) : base_ilist_iterator(a) {}
inline T* operator++(int) { return (T*) base_ilist_iterator::next(); } inline T* operator++(int) { return (T*) base_ilist_iterator::next(); }
}; };
/*
New error list without mem_root from THD, to have the life of the
allocation becomes connection level . by ovveriding new from Sql_alloc.
*/
class Error_alloc
{
public:
static void *operator new(size_t size)
{
return (void*)my_malloc((uint)size, MYF(MY_WME | MY_FAE));
}
#if 0
static void operator delete(void* ptr_arg, size_t size)
{
my_free((gptr)ptr_arg, MYF(MY_WME|MY_ALLOW_ZERO_PTR));
}
#endif
friend class error_node;
friend class error_list;
};
class error_node :public Error_alloc, public list_node
{
public:
static void *operator new(size_t size)
{
return (void*)my_malloc((uint)size, MYF(MY_WME | MY_FAE));
}
#if 0
static void operator delete(void* ptr_arg, size_t size)
{
my_free((gptr)ptr_arg, MYF(MY_WME|MY_ALLOW_ZERO_PTR));
}
#endif
error_node(void *info_par,list_node *next_par):list_node(info_par,next_par){};
error_node() : list_node() {};
friend class error_list;
friend class error_list_iterator;
};
class error_list: public Error_alloc, public base_list
{
public:
inline error_list() : base_list() { };
inline error_list(const error_list &tmp) : Error_alloc()
{
elements=tmp.elements;
first=tmp.first;
last=tmp.last;
}
inline bool push_front(void *info)
{
error_node *node=new error_node(info,first);
if (node)
{
if (last == &first)
last= &node->next;
first=node;
elements++;
return 0;
}
return 1;
}
inline void remove_last(void)
{
remove(last);
}
protected:
void after(void *info,list_node *node)
{
error_node *new_node=new error_node(info,node->next);
node->next=new_node;
elements++;
if (last == &(node->next))
last= &new_node->next;
}
};
class error_list_iterator : public base_list_iterator
{
inline error_list_iterator(base_list &base_ptr): base_list_iterator(base_ptr) {};
};
template <class T> class Error :public error_list
{
public:
inline Error() :error_list() {}
inline Error(const Error<T> &tmp) :error_list(tmp) {}
inline bool push_back(T *a) { return error_list::push_back(a); }
inline bool push_front(T *a) { return error_list::push_front(a); }
inline T* head() {return (T*) error_list::head(); }
inline T** head_ref() {return (T**) error_list::head_ref(); }
inline T* pop() {return (T*) error_list::pop(); }
void delete_elements(void)
{
error_node *element,*next;
for (element=first; element != &error_end_of_list; element=next)
{
next=element->next;
delete (T*) element->info;
}
empty();
}
};
template <class T> class Error_iterator :public base_list_iterator
{
public:
Error_iterator(Error<T> &a) : base_list_iterator(a) {}
inline T* operator++(int) { return (T*) base_list_iterator::next(); }
inline T *replace(T *a) { return (T*) base_list_iterator::replace(a); }
inline T *replace(Error<T> &a) { return (T*) base_list_iterator::replace(a); }
inline void after(T *a) { base_list_iterator::after(a); }
inline T** ref(void) { return (T**) base_list_iterator::ref(); }
};
...@@ -65,7 +65,6 @@ static void decrease_user_connections(USER_CONN *uc); ...@@ -65,7 +65,6 @@ static void decrease_user_connections(USER_CONN *uc);
static bool check_db_used(THD *thd,TABLE_LIST *tables); static bool check_db_used(THD *thd,TABLE_LIST *tables);
static bool check_merge_table_access(THD *thd, char *db, TABLE_LIST *tables); static bool check_merge_table_access(THD *thd, char *db, TABLE_LIST *tables);
static bool check_dup(const char *db, const char *name, TABLE_LIST *tables); static bool check_dup(const char *db, const char *name, TABLE_LIST *tables);
void mysql_init_query(THD *thd);
static void remove_escape(char *name); static void remove_escape(char *name);
static void refresh_status(void); static void refresh_status(void);
static bool append_file_to_dir(THD *thd, char **filename_ptr, static bool append_file_to_dir(THD *thd, char **filename_ptr,
...@@ -77,7 +76,8 @@ const char *command_name[]={ ...@@ -77,7 +76,8 @@ const char *command_name[]={
"Sleep", "Quit", "Init DB", "Query", "Field List", "Create DB", "Sleep", "Quit", "Init DB", "Query", "Field List", "Create DB",
"Drop DB", "Refresh", "Shutdown", "Statistics", "Processlist", "Drop DB", "Refresh", "Shutdown", "Statistics", "Processlist",
"Connect","Kill","Debug","Ping","Time","Delayed_insert","Change user", "Connect","Kill","Debug","Ping","Time","Delayed_insert","Change user",
"Binlog Dump","Table Dump", "Connect Out", "Register Slave" "Binlog Dump","Table Dump", "Connect Out", "Register Slave",
"Prepare", "Prepare Execute", "Long Data"
}; };
bool volatile abort_slave = 0; bool volatile abort_slave = 0;
...@@ -486,7 +486,7 @@ check_connections(THD *thd) ...@@ -486,7 +486,7 @@ check_connections(THD *thd)
{ {
/* buff[] needs to big enough to hold the server_version variable */ /* buff[] needs to big enough to hold the server_version variable */
char buff[SERVER_VERSION_LENGTH + SCRAMBLE_LENGTH+32],*end; char buff[SERVER_VERSION_LENGTH + SCRAMBLE_LENGTH+32],*end;
int client_flags = CLIENT_LONG_FLAG | CLIENT_CONNECT_WITH_DB; int client_flags = CLIENT_LONG_FLAG | CLIENT_CONNECT_WITH_DB | CLIENT_PROTOCOL_41;
if (opt_using_transactions) if (opt_using_transactions)
client_flags|=CLIENT_TRANSACTIONS; client_flags|=CLIENT_TRANSACTIONS;
...@@ -957,7 +957,21 @@ bool dispatch_command(enum enum_server_command command, THD *thd, ...@@ -957,7 +957,21 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
thd->password=test(passwd[0]); thd->password=test(passwd[0]);
break; break;
} }
case COM_EXECUTE:
{
mysql_com_execute(thd);
break;
}
case COM_LONG_DATA:
{
mysql_com_longdata(thd);
break;
}
case COM_PREPARE:
{
mysql_com_prepare(thd,packet,packet_length);
break;
}
case COM_QUERY: case COM_QUERY:
{ {
packet_length--; // Remove end null packet_length--; // Remove end null
...@@ -1380,6 +1394,26 @@ mysql_execute_command(void) ...@@ -1380,6 +1394,26 @@ mysql_execute_command(void)
res = purge_master_logs(thd, lex->to_log); res = purge_master_logs(thd, lex->to_log);
break; break;
} }
case SQLCOM_SHOW_WARNS_COUNT:
{
res = mysqld_show_warnings_count(thd);
break;
}
case SQLCOM_SHOW_WARNS:
{
res = mysqld_show_warnings(thd);
break;
}
case SQLCOM_SHOW_ERRORS_COUNT:
{
res = mysqld_show_errors_count(thd);
break;
}
case SQLCOM_SHOW_ERRORS:
{
res = mysqld_show_errors(thd);
break;
}
case SQLCOM_SHOW_NEW_MASTER: case SQLCOM_SHOW_NEW_MASTER:
{ {
if (check_access(thd, FILE_ACL, any_db)) if (check_access(thd, FILE_ACL, any_db))
...@@ -2048,6 +2082,15 @@ mysql_execute_command(void) ...@@ -2048,6 +2082,15 @@ mysql_execute_command(void)
mysqld_list_processes(thd,thd->master_access & PROCESS_ACL ? NullS : mysqld_list_processes(thd,thd->master_access & PROCESS_ACL ? NullS :
thd->priv_user,lex->verbose); thd->priv_user,lex->verbose);
break; break;
case SQLCOM_SHOW_TABLE_TYPES:
res= mysqld_show_table_types(thd);
break;
case SQLCOM_SHOW_PRIVILEGES:
res= mysqld_show_privileges(thd);
break;
case SQLCOM_SHOW_COLUMN_TYPES:
res= mysqld_show_column_types(thd);
break;
case SQLCOM_SHOW_STATUS: case SQLCOM_SHOW_STATUS:
res= mysqld_show(thd,(lex->wild ? lex->wild->ptr() : NullS),status_vars); res= mysqld_show(thd,(lex->wild ? lex->wild->ptr() : NullS),status_vars);
break; break;
...@@ -2732,6 +2775,9 @@ mysql_init_query(THD *thd) ...@@ -2732,6 +2775,9 @@ mysql_init_query(THD *thd)
thd->last_insert_id_used= thd->query_start_used= thd->insert_id_used=0; thd->last_insert_id_used= thd->query_start_used= thd->insert_id_used=0;
thd->sent_row_count= thd->examined_row_count= 0; thd->sent_row_count= thd->examined_row_count= 0;
thd->safe_to_cache_query= 1; thd->safe_to_cache_query= 1;
thd->param_count=0;
thd->prepare_command=false;
thd->lex.param_list.empty();
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
......
This diff is collapsed.
...@@ -126,8 +126,6 @@ static bool store_record_in_cache(JOIN_CACHE *cache); ...@@ -126,8 +126,6 @@ static bool store_record_in_cache(JOIN_CACHE *cache);
static void reset_cache(JOIN_CACHE *cache); static void reset_cache(JOIN_CACHE *cache);
static void read_cached_record(JOIN_TAB *tab); static void read_cached_record(JOIN_TAB *tab);
static bool cmp_buffer_with_ref(JOIN_TAB *tab); static bool cmp_buffer_with_ref(JOIN_TAB *tab);
static int setup_group(THD *thd,TABLE_LIST *tables,List<Item> &fields,
List<Item> &all_fields, ORDER *order, bool *hidden);
static bool setup_new_fields(THD *thd,TABLE_LIST *tables,List<Item> &fields, static bool setup_new_fields(THD *thd,TABLE_LIST *tables,List<Item> &fields,
List<Item> &all_fields,ORDER *new_order); List<Item> &all_fields,ORDER *new_order);
static ORDER *create_distinct_group(ORDER *order, List<Item> &fields); static ORDER *create_distinct_group(ORDER *order, List<Item> &fields);
...@@ -6456,7 +6454,7 @@ int setup_order(THD *thd,TABLE_LIST *tables,List<Item> &fields, ...@@ -6456,7 +6454,7 @@ int setup_order(THD *thd,TABLE_LIST *tables,List<Item> &fields,
} }
static int int
setup_group(THD *thd,TABLE_LIST *tables,List<Item> &fields, setup_group(THD *thd,TABLE_LIST *tables,List<Item> &fields,
List<Item> &all_fields, ORDER *order, bool *hidden_group_fields) List<Item> &all_fields, ORDER *order, bool *hidden_group_fields)
{ {
......
...@@ -169,6 +169,201 @@ int mysqld_show_tables(THD *thd,const char *db,const char *wild) ...@@ -169,6 +169,201 @@ int mysqld_show_tables(THD *thd,const char *db,const char *wild)
DBUG_RETURN(0); DBUG_RETURN(0);
} }
/***************************************************************************
** List all table types supported
***************************************************************************/
static struct show_table_type_st sys_table_types[]= {
{"MyISAM", (char *)"YES", "Default type from 3.23 with great performance"},
{"HEAP" , (char *)"YES", "Hash based, stored in memory, useful for temporary tables"},
{"MERGE", (char *)"YES", "Collection of identical MyISAM tables"},
{"ISAM", (char*) &have_isam,"Obsolete table type"},
{"InnoDB", (char*) &have_innodb,"Supports transactions, row-level locking and foreign keys"},
{"BDB", (char*) &have_berkeley_db, "Supports transactions and page-level locking"},
};
int mysqld_show_table_types(THD *thd)
{
List<Item> field_list;
DBUG_ENTER("mysqld_show_table_types");
field_list.push_back(new Item_empty_string("Type",10));
field_list.push_back(new Item_empty_string("Support",10));
field_list.push_back(new Item_empty_string("Comment",NAME_LEN));
if (send_fields(thd,field_list,1))
DBUG_RETURN(1);
const char *default_type_name=ha_table_typelib.type_names[default_table_type-1];
show_table_type_st *types = sys_table_types;
uint i;
for (i = 0; i < 3; i++)
{
thd->packet.length(0);
net_store_data(&thd->packet,types[i].type);
if (!strcasecmp(default_type_name,types[i].type))
net_store_data(&thd->packet,"DEFAULT");
else
net_store_data(&thd->packet,types[i].value);
net_store_data(&thd->packet,types[i].comment);
if (my_net_write(&thd->net,(char*) thd->packet.ptr(),thd->packet.length()))
DBUG_RETURN(-1);
}
for (; i < sizeof(sys_table_types)/sizeof(sys_table_types[0]); i++)
{
thd->packet.length(0);
net_store_data(&thd->packet,types[i].type);
SHOW_COMP_OPTION tmp= *(SHOW_COMP_OPTION*) types[i].value;
if (tmp == SHOW_OPTION_NO)
net_store_data(&thd->packet,"NO");
else
{
if (tmp == SHOW_OPTION_YES)
{
if (!strcasecmp(default_type_name,types[i].type))
net_store_data(&thd->packet,"DEFAULT");
else
net_store_data(&thd->packet,"YES");
}
else net_store_data(&thd->packet,"DISABLED");
}
net_store_data(&thd->packet,types[i].comment);
if (my_net_write(&thd->net,(char*) thd->packet.ptr(),thd->packet.length()))
DBUG_RETURN(-1);
}
send_eof(&thd->net);
DBUG_RETURN(0);
}
/***************************************************************************
** List all privileges supported
***************************************************************************/
static struct show_table_type_st sys_privileges[]= {
{"Select", (char *)"Tables", "To retrieve rows from table"},
{"Insert", (char *)"Tables", "To insert data into tables"},
{"Update", (char *)"Tables", "To update existing rows "},
{"Delete", (char *)"Tables", "To delete existing rows"},
{"Index", (char *)"Tables", "To create or drop indexes"},
{"Alter", (char *)"Tables", "To alter the table"},
{"Create", (char *)"Databases,Tables,Indexes", "To create new databases and tables"},
{"Drop", (char *)"Databases,Tables", "To drop databases and tables"},
{"Grant", (char *)"Databases,Tables", "To give to other users those privileges you possesed"},
{"References", (char *)"Databases,Tables", "To have references on tables"},
{"Reload", (char *)"Server Admin", "To reload or refresh tables, logs and privileges"},
{"Shutdown",(char *)"Server Admin", "To shutdown the server"},
{"Process", (char *)"Server Admin", "To view the plain text of currently executing queries"},
{"File", (char *)"File access on server", "To read and write files on the server"},
};
int mysqld_show_privileges(THD *thd)
{
List<Item> field_list;
DBUG_ENTER("mysqld_show_privileges");
field_list.push_back(new Item_empty_string("Privilege",10));
field_list.push_back(new Item_empty_string("Context",15));
field_list.push_back(new Item_empty_string("Comment",NAME_LEN));
if (send_fields(thd,field_list,1))
DBUG_RETURN(1);
for (uint i=0; i < sizeof(sys_privileges)/sizeof(sys_privileges[0]); i++)
{
thd->packet.length(0);
net_store_data(&thd->packet,sys_privileges[i].type);
net_store_data(&thd->packet,sys_privileges[i].value);
net_store_data(&thd->packet,sys_privileges[i].comment);
if (my_net_write(&thd->net,(char*) thd->packet.ptr(),thd->packet.length()))
DBUG_RETURN(-1);
}
send_eof(&thd->net);
DBUG_RETURN(0);
}
/***************************************************************************
** List all column types
***************************************************************************/
#if 0
struct show_column_type_st {
const char *type;
uint size;
char *min_value;
char *max_value;
uint precision,
uint scale,
char *nullable;
char *auto_increment;
char *unsigned_attr;
char *zerofill;
char *searchable;
char *case_sensitivity;
char *default_value;
char *comment;
};
#endif
static struct show_column_type_st sys_column_types[]= {
{"tinyint",
1, "-128", "127", 0, 0, "YES", "YES",
"NO", "YES", "YES", "NO", "NULL,0",
"A very small integer"},
{"tinyint unsigned",
1, "0" , "255", 0, 0, "YES", "YES",
"YES", "YES", "YES", "NO", "NULL,0",
"A very small integer"},
};
int mysqld_show_column_types(THD *thd)
{
List<Item> field_list;
DBUG_ENTER("mysqld_show_column_types");
field_list.push_back(new Item_empty_string("Type",30));
field_list.push_back(new Item_int("Size",(longlong) 1,21));
field_list.push_back(new Item_empty_string("Min_Value",20));
field_list.push_back(new Item_empty_string("Max_Value",20));
field_list.push_back(new Item_int("Prec", 0,4));
field_list.push_back(new Item_int("Scale", 0,4));
field_list.push_back(new Item_empty_string("Nullable",4));
field_list.push_back(new Item_empty_string("Auto_Increment",4));
field_list.push_back(new Item_empty_string("Unsigned",4));
field_list.push_back(new Item_empty_string("Zerofill",4));
field_list.push_back(new Item_empty_string("Searchable",4));
field_list.push_back(new Item_empty_string("Case_Sensitive",4));
field_list.push_back(new Item_empty_string("Default",NAME_LEN));
field_list.push_back(new Item_empty_string("Comment",NAME_LEN));
if (send_fields(thd,field_list,1))
DBUG_RETURN(1);
for (uint i=0; i < sizeof(sys_column_types)/sizeof(sys_column_types[0]); i++)
{
thd->packet.length(0);
net_store_data(&thd->packet,sys_column_types[i].type);
net_store_data(&thd->packet,(longlong)sys_column_types[i].size);
net_store_data(&thd->packet,sys_column_types[i].min_value);
net_store_data(&thd->packet,sys_column_types[i].max_value);
net_store_data(&thd->packet,(uint32)sys_column_types[i].precision);
net_store_data(&thd->packet,(uint32)sys_column_types[i].scale);
net_store_data(&thd->packet,sys_column_types[i].nullable);
net_store_data(&thd->packet,sys_column_types[i].auto_increment);
net_store_data(&thd->packet,sys_column_types[i].unsigned_attr);
net_store_data(&thd->packet,sys_column_types[i].zerofill);
net_store_data(&thd->packet,sys_column_types[i].searchable);
net_store_data(&thd->packet,sys_column_types[i].case_sensitivity);
net_store_data(&thd->packet,sys_column_types[i].default_value);
net_store_data(&thd->packet,sys_column_types[i].comment);
if (my_net_write(&thd->net,(char*) thd->packet.ptr(),thd->packet.length()))
DBUG_RETURN(-1);
}
send_eof(&thd->net);
DBUG_RETURN(0);
}
static int static int
mysql_find_files(THD *thd,List<char> *files, const char *db,const char *path, mysql_find_files(THD *thd,List<char> *files, const char *db,const char *path,
......
...@@ -324,6 +324,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); ...@@ -324,6 +324,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token TRAILING %token TRAILING
%token TRANSACTION_SYM %token TRANSACTION_SYM
%token TYPE_SYM %token TYPE_SYM
%token TYPES_SYM
%token FUNC_ARG0 %token FUNC_ARG0
%token FUNC_ARG1 %token FUNC_ARG1
%token FUNC_ARG2 %token FUNC_ARG2
...@@ -346,6 +347,11 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); ...@@ -346,6 +347,11 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token X509_SYM %token X509_SYM
%token COMPRESSED_SYM %token COMPRESSED_SYM
%token ERRORS
%token SQL_ERROR_COUNT
%token WARNINGS
%token SQL_WARNING_COUNT
%token BIGINT %token BIGINT
%token BLOB_SYM %token BLOB_SYM
%token CHAR_SYM %token CHAR_SYM
...@@ -548,7 +554,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); ...@@ -548,7 +554,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
literal text_literal insert_ident order_ident literal text_literal insert_ident order_ident
simple_ident select_item2 expr opt_expr opt_else sum_expr in_sum_expr simple_ident select_item2 expr opt_expr opt_else sum_expr in_sum_expr
table_wild opt_pad no_in_expr expr_expr simple_expr no_and_expr table_wild opt_pad no_in_expr expr_expr simple_expr no_and_expr
using_list subselect subselect_init using_list param_marker subselect subselect_init
%type <item_list> %type <item_list>
expr_list udf_expr_list when_list ident_list ident_list_arg expr_list udf_expr_list when_list ident_list ident_list_arg
...@@ -1720,6 +1726,7 @@ no_and_expr: ...@@ -1720,6 +1726,7 @@ no_and_expr:
simple_expr: simple_expr:
simple_ident simple_ident
| literal | literal
| param_marker
| '@' ident_or_text SET_VAR expr | '@' ident_or_text SET_VAR expr
{ $$= new Item_func_set_user_var($2,$4); { $$= new Item_func_set_user_var($2,$4);
current_thd->safe_to_cache_query=0; current_thd->safe_to_cache_query=0;
...@@ -2795,6 +2802,29 @@ show_param: ...@@ -2795,6 +2802,29 @@ show_param:
if (!add_table_to_list($3,NULL,0)) if (!add_table_to_list($3,NULL,0))
YYABORT; YYABORT;
} }
| COLUMN_SYM TYPES_SYM
{
LEX *lex=Lex;
lex->sql_command= SQLCOM_SHOW_COLUMN_TYPES;
}
| TABLE_SYM TYPES_SYM
{
LEX *lex=Lex;
lex->sql_command= SQLCOM_SHOW_TABLE_TYPES;
}
| PRIVILEGES
{
LEX *lex=Lex;
lex->sql_command= SQLCOM_SHOW_PRIVILEGES;
}
| COUNT_SYM '(' '*' ')' WARNINGS
{ Lex->sql_command = SQLCOM_SHOW_WARNS_COUNT;}
| COUNT_SYM '(' '*' ')' ERRORS
{ Lex->sql_command = SQLCOM_SHOW_ERRORS_COUNT;}
| WARNINGS {Select->offset_limit=0L;} limit_clause
{ Lex->sql_command = SQLCOM_SHOW_WARNS;}
| ERRORS {Select->offset_limit=0L;} limit_clause
{ Lex->sql_command = SQLCOM_SHOW_ERRORS;}
| STATUS_SYM wild | STATUS_SYM wild
{ Lex->sql_command= SQLCOM_SHOW_STATUS; } { Lex->sql_command= SQLCOM_SHOW_STATUS; }
| opt_full PROCESSLIST_SYM | opt_full PROCESSLIST_SYM
...@@ -3055,7 +3085,20 @@ text_string: ...@@ -3055,7 +3085,20 @@ text_string:
Item *tmp = new Item_varbinary($1.str,$1.length,default_charset_info); Item *tmp = new Item_varbinary($1.str,$1.length,default_charset_info);
$$= tmp ? tmp->val_str((String*) 0) : (String*) 0; $$= tmp ? tmp->val_str((String*) 0) : (String*) 0;
}; };
param_marker:
'?'
{
if(current_thd->prepare_command)
{
Lex->param_list.push_back($$=new Item_param());
current_thd->param_count++;
}
else
{
yyerror("You have an error in your SQL syntax");
YYABORT;
}
}
literal: literal:
text_literal { $$ = $1; } text_literal { $$ = $1; }
| NUM { $$ = new Item_int($1.str, (longlong) atol($1.str),$1.length); } | NUM { $$ = new Item_int($1.str, (longlong) atol($1.str),$1.length); }
...@@ -3411,6 +3454,16 @@ option_value: ...@@ -3411,6 +3454,16 @@ option_value:
YYABORT; YYABORT;
} }
| SQL_QUERY_CACHE_TYPE_SYM equal query_cache_type | SQL_QUERY_CACHE_TYPE_SYM equal query_cache_type
| SQL_ERROR_COUNT equal ULONG_NUM
{
LEX *lex = Lex;
lex->thd->max_error_count = $3;
}
| SQL_WARNING_COUNT equal ULONG_NUM
{
LEX *lex = Lex;
lex->thd->max_warning_count = $3;
}
| '@' ident_or_text equal expr | '@' ident_or_text equal expr
{ {
Item_func_set_user_var *item = new Item_func_set_user_var($2,$4); Item_func_set_user_var *item = new Item_func_set_user_var($2,$4);
......
...@@ -152,6 +152,29 @@ struct show_var_st { ...@@ -152,6 +152,29 @@ struct show_var_st {
SHOW_TYPE type; SHOW_TYPE type;
}; };
struct show_table_type_st {
const char *type;
char *value;
const char *comment;
};
struct show_column_type_st {
const char *type;
uint size;
const char *min_value;
const char *max_value;
uint precision;
uint scale;
const char *nullable;
const char *auto_increment;
const char *unsigned_attr;
const char *zerofill;
const char *searchable;
const char *case_sensitivity;
const char *default_value;
const char *comment;
};
typedef struct lex_string { typedef struct lex_string {
char *str; char *str;
uint length; uint length;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment