diff options
Diffstat (limited to 'sql')
71 files changed, 1968 insertions, 1708 deletions
diff --git a/sql/field.cc b/sql/field.cc index c9669c93c04..336bc9d7cc2 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -314,6 +314,7 @@ void Field::store_time(TIME *ltime,timestamp_type type) store(buff,(uint) length, default_charset_info); break; } + } } @@ -476,7 +477,7 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs) from++; frac_digits_from= from; /* Read digits at the right of '.' */ - for (;from!=end && my_isdigit(system_charset_info, (*from); from++) ; + for (;from!=end && my_isdigit(system_charset_info, *from); from++) ; frac_digits_end=from; // Some exponentiation symbol ? if (from != end && (*from == 'e' || *from == 'E')) @@ -505,7 +506,8 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs) if (current_thd->count_cuted_fields) { - for (;from != end && isspace(*from); from++) ; // Read end spaces + // Skip end spaces + for (;from != end && my_isspace(system_charset_info, *from); from++) ; if (from != end) // If still something left, warn { current_thd->cuted_fields++; @@ -736,10 +738,10 @@ int Field_decimal::store(double nr) #ifdef HAVE_SNPRINTF_ buff[sizeof(buff)-1]=0; // Safety snprintf(buff,sizeof(buff)-1, "%.*f",(int) dec,nr); + length=(uint) strlen(buff); #else - sprintf(buff,"%.*f",dec,nr); + length=(uint) my_sprintf(buff,(buff,"%.*f",dec,nr)); #endif - length=(uint) strlen(buff); if (length > field_length) { @@ -2207,10 +2209,10 @@ String *Field_float::val_str(String *val_buffer, #ifdef HAVE_SNPRINTF to[to_length-1]=0; // Safety snprintf(to,to_length-1,"%.*f",dec,nr); + to=strend(to); #else - sprintf(to,"%.*f",dec,nr); + to+= my_sprintf(to,(to,"%.*f",dec,nr)); #endif - to=strend(to); #endif } #ifdef HAVE_FCONVERT @@ -2468,10 +2470,10 @@ String *Field_double::val_str(String *val_buffer, #ifdef HAVE_SNPRINTF to[to_length-1]=0; // Safety snprintf(to,to_length-1,"%.*f",dec,nr); + to=strend(to); #else - sprintf(to,"%.*f",dec,nr); + to+= my_sprintf(to,(to,"%.*f",dec,nr)); #endif - to=strend(to); #endif } #ifdef HAVE_FCONVERT @@ -2886,8 +2888,10 @@ void Field_timestamp::sort_string(char *to,uint length __attribute__((unused))) void Field_timestamp::sql_type(String &res) const { - sprintf((char*) res.ptr(),"timestamp(%d)",(int) field_length); - res.length((uint) strlen(res.ptr())); + ulong length= my_sprintf((char*) res.ptr(), + ((char*) res.ptr(),"timestamp(%d)", + (int) field_length)); + res.length(length); } @@ -3026,10 +3030,11 @@ String *Field_time::val_str(String *val_buffer, tmp= -tmp; sign= "-"; } - sprintf((char*) val_buffer->ptr(),"%s%02d:%02d:%02d", - sign,(int) (tmp/10000), (int) (tmp/100 % 100), - (int) (tmp % 100)); - val_buffer->length((uint) strlen(val_buffer->ptr())); + long length= my_sprintf((char*) val_buffer->ptr(), + ((char*) val_buffer->ptr(),"%s%02d:%02d:%02d", + sign,(int) (tmp/10000), (int) (tmp/100 % 100), + (int) (tmp % 100))); + val_buffer->length(length); return val_buffer; } @@ -3158,8 +3163,9 @@ String *Field_year::val_str(String *val_buffer, void Field_year::sql_type(String &res) const { - sprintf((char*) res.ptr(),"year(%d)",(int) field_length); - res.length((uint) strlen(res.ptr())); + ulong length=my_sprintf((char*) res.ptr(), + ((char*) res.ptr(),"year(%d)",(int) field_length)); + res.length(length); } @@ -3852,12 +3858,14 @@ void Field_string::sort_string(char *to,uint length) void Field_string::sql_type(String &res) const { - sprintf((char*) res.ptr(),"%s(%d)", - field_length > 3 && - (table->db_options_in_use & HA_OPTION_PACK_RECORD) ? - "varchar" : "char", - (int) field_length); - res.length((uint) strlen(res.ptr())); + ulong length= my_sprintf((char*) res.ptr(), + ((char*) res.ptr(), "%s(%d)", + (field_length > 3 && + (table->db_options_in_use & + HA_OPTION_PACK_RECORD) ? + "varchar" : "char"), + (int) field_length)); + res.length((uint) length); if (binary_flag) res.append(" binary"); else @@ -4060,8 +4068,10 @@ void Field_varstring::sort_string(char *to,uint length) void Field_varstring::sql_type(String &res) const { - sprintf((char*) res.ptr(),"varchar(%d)",(int) field_length); - res.length((uint) strlen(res.ptr())); + ulong length= my_sprintf((char*) res.ptr(), + ((char*) res.ptr(),"varchar(%u)", + field_length)); + res.length((uint) length); if (binary_flag) res.append(" binary"); else diff --git a/sql/field.h b/sql/field.h index 551619abc6f..d8cfba14e02 100644 --- a/sql/field.h +++ b/sql/field.h @@ -1036,6 +1036,7 @@ public: uint decimals,flags,pack_length; Field::utype unireg_check; TYPELIB *interval; // Which interval to use + CHARSET_INFO *charset; Field *field; // For alter table uint8 row,col,sc_length,interval_id; // For rea_create_table diff --git a/sql/gstream.h b/sql/gstream.h index f8df6e337b0..f26ef8899f8 100644 --- a/sql/gstream.h +++ b/sql/gstream.h @@ -1,11 +1,19 @@ -#ifndef GSTREAM_H -#define GSTREAM_H +/* 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 WITHOUT_MYSQL - #include ".\rtree\myisamdef.h" -#else - #include "mysql_priv.h" -#endif class GTextReadStream { @@ -20,9 +28,13 @@ public: r_bra, comma, }; - GTextReadStream(const char *buffer, int size) : - m_cur(buffer), m_limit(buffer + size), m_last_text_position(buffer), m_err_msg(NULL) {} - GTextReadStream() : m_cur(NULL), m_limit(NULL), m_err_msg(NULL) {} + + GTextReadStream(const char *buffer, int size) + :m_cur(buffer), m_limit(buffer + size), m_last_text_position(buffer), + m_err_msg(NULL) + {} + GTextReadStream(): m_cur(NULL), m_limit(NULL), m_err_msg(NULL) + {} ~GTextReadStream() { @@ -41,21 +53,17 @@ public: void set_error_msg(const char *msg); -// caller should free this pointer + // caller should free this pointer char *get_error_msg() { char *err_msg = m_err_msg; m_err_msg = NULL; return err_msg; } + protected: const char *m_cur; const char *m_limit; const char *m_last_text_position; char *m_err_msg; }; - -#endif - - - diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index d42311b43b6..65aaa63f7db 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -3557,7 +3557,7 @@ innodb_show_status( ut_free(buf); - send_eof(&thd->net); + send_eof(thd); DBUG_RETURN(0); } diff --git a/sql/item.cc b/sql/item.cc index 7693ef428c6..946c0f24fe1 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -44,10 +44,10 @@ Item::Item() current_thd->free_list=this; } -void Item::set_name(char *str,uint length) +void Item::set_name(const char *str,uint length) { if (!length) - name=str; // Used by AS + name= (char*) str; // Used by AS else { while (length && !my_isgraph(system_charset_info,*str)) @@ -303,21 +303,13 @@ void Item_param::set_int(longlong i) item_type = INT_ITEM; } -void Item_param::set_double(double i) +void Item_param::set_double(double value) { - 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) { @@ -326,6 +318,7 @@ void Item_param::set_value(const char *str, uint length) item_type = STRING_ITEM; } + void Item_param::set_longdata(const char *str, ulong length) { /* TODO: Fix this for binary handling by making use of @@ -334,16 +327,11 @@ void Item_param::set_longdata(const char *str, ulong length) str_value.append(str,length); } -void Item_param::set_long_end() -{ - long_data_supplied = true; - item_result_type = STRING_RESULT; -}; -int Item_param::save_in_field(Field *field) +int Item_param::save_in_field(Field *field) { if (null_value) - return set_field_to_null(field); + return (int) set_field_to_null(field); field->set_notnull(); if (item_result_type == INT_RESULT) @@ -357,24 +345,21 @@ int Item_param::save_in_field(Field *field) return (field->store(nr)) ? -1 : 0; } String *result; - CHARSET_INFO *cs=default_charset_info;//fix this + CHARSET_INFO *cs=default_charset_info; //fix this result=val_str(&str_value); return (field->store(result->ptr(),result->length(),cs)) ? -1 : 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) { - + switch (item_result_type) { case STRING_RESULT: return (double)atof(str_value.ptr()); case INT_RESULT: @@ -384,16 +369,12 @@ double Item_param::val() } } + longlong Item_param::val_int() { - /* Cross check whether we need need this conversions ? or direct - return(int_value) is enough ? - */ - - switch(item_result_type) { - + switch (item_result_type) { case STRING_RESULT: - return (longlong)strtoll(str_value.ptr(),(char**) 0,10); + return strtoll(str_value.ptr(),(char**) 0,10); case REAL_RESULT: return (longlong) (real_value+(real_value > 0 ? 0.5 : -0.5)); default: @@ -401,14 +382,10 @@ longlong Item_param::val_int() } } + 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) { - + switch (item_result_type) { case INT_RESULT: str->set(int_value); return str; @@ -421,6 +398,7 @@ String *Item_param::val_str(String* str) } /* End of Item_param related */ + void Item_copy_string::copy() { String *res=item->val_str(&str_value); @@ -438,7 +416,7 @@ String *Item_copy_string::val_str(String *str) } /* -** Functions to convert item to field (for send_fields) + Functions to convert item to field (for send_fields) */ /* ARGSUSED */ @@ -614,7 +592,7 @@ void Item_field::save_org_in_field(Field *to) } } -int Item_field::save_in_field(Field *to) +int Item_field::save_in_field(Field *to) { if (result_field->is_null()) { @@ -631,13 +609,13 @@ int Item_field::save_in_field(Field *to) } -int Item_null::save_in_field(Field *field) +int Item_null::save_in_field(Field *field) { return set_field_to_null(field); } -int Item::save_in_field(Field *field) +int Item::save_in_field(Field *field) { int error; if (result_type() == STRING_RESULT || @@ -674,7 +652,7 @@ int Item::save_in_field(Field *field) return (error) ? -1 : 0; } -int Item_string::save_in_field(Field *field) +int Item_string::save_in_field(Field *field) { String *result; CHARSET_INFO *cs=field->binary()?default_charset_info:((Field_str*)field)->charset(); @@ -685,7 +663,7 @@ int Item_string::save_in_field(Field *field) return (field->store(result->ptr(),result->length(),cs)) ? -1 : 0; } -int Item_int::save_in_field(Field *field) +int Item_int::save_in_field(Field *field) { longlong nr=val_int(); if (null_value) @@ -694,7 +672,7 @@ int Item_int::save_in_field(Field *field) return (field->store(nr)) ? -1 : 0; } -int Item_real::save_in_field(Field *field) +int Item_real::save_in_field(Field *field) { double nr=val(); if (null_value) @@ -716,7 +694,8 @@ inline uint char_val(char X) X-'a'+10); } -Item_varbinary::Item_varbinary(const char *str, uint str_length, CHARSET_INFO *cs) +Item_varbinary::Item_varbinary(const char *str, uint str_length, + CHARSET_INFO *cs) { name=(char*) str-2; // Lex makes this start with 0x max_length=(str_length+1)/2; @@ -748,7 +727,7 @@ longlong Item_varbinary::val_int() } -int Item_varbinary::save_in_field(Field *field) +int Item_varbinary::save_in_field(Field *field) { int error; CHARSET_INFO *cs=field->binary()?default_charset_info:((Field_str*)field)->charset(); diff --git a/sql/item.h b/sql/item.h index 206d7b5bd78..84182203d4c 100644 --- a/sql/item.h +++ b/sql/item.h @@ -50,7 +50,7 @@ public: // alloc & destruct is done as start of select using sql_alloc Item(); virtual ~Item() { name=0; } /*lint -e1509 */ - void set_name(char* str,uint length=0); + void set_name(const char *str,uint length=0); void init_make_field(Send_field *tmp_field,enum enum_field_types type); virtual bool fix_fields(THD *, struct st_table_list *, Item **); virtual int save_in_field(Field *field); @@ -82,7 +82,6 @@ public: virtual bool get_date(TIME *ltime,bool fuzzydate); virtual bool get_time(TIME *ltime); virtual bool is_null() { return 0; } - virtual unsigned int size_of()= 0; }; @@ -100,7 +99,6 @@ public: field_name(field_name_par), depended_from(0) { name = (char*) field_name_par; } const char *full_name() const; - unsigned int size_of() { return sizeof(*this);} }; @@ -141,7 +139,6 @@ public: bool get_date(TIME *ltime,bool fuzzydate); bool get_time(TIME *ltime); bool is_null() { return field->is_null(); } - unsigned int size_of() { return sizeof(*this);} }; @@ -163,7 +160,6 @@ public: bool basic_const_item() const { return 1; } Item *new_item() { return new Item_null(name); } bool is_null() { return 1; } - unsigned int size_of() { return sizeof(*this);} }; class Item_param :public Item @@ -176,10 +172,12 @@ public: enum enum_field_types buffer_type; my_bool long_data_supplied; - Item_param(char *name_par=0){ + 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; + item_type = STRING_ITEM; + item_result_type = STRING_RESULT; } enum Type type() const { return item_type; } double val(); @@ -189,13 +187,13 @@ public: int 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(); + void reset() {} enum Item_result result_type () const { return item_result_type; } Item *new_item() { return new Item_param(name); } @@ -227,7 +225,6 @@ public: bool basic_const_item() const { return 1; } Item *new_item() { return new Item_int(name,value,max_length); } void print(String *str); - unsigned int size_of() { return sizeof(*this);} }; @@ -242,7 +239,6 @@ public: void make_field(Send_field *field); Item *new_item() { return new Item_uint(name,max_length); } void print(String *str); - unsigned int size_of() { return sizeof(*this);} }; @@ -273,7 +269,6 @@ public: 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); } - unsigned int size_of() { return sizeof(*this);} }; @@ -285,7 +280,6 @@ public: decimals=NOT_FIXED_DEC; max_length=DBL_DIG+8; } - unsigned int size_of() { return sizeof(*this);} }; class Item_string :public Item @@ -319,7 +313,6 @@ public: String *const_string() { return &str_value; } inline void append(char *str,uint length) { str_value.append(str,length); } void print(String *str); - unsigned int size_of() { return sizeof(*this);} }; @@ -331,7 +324,7 @@ public: Item_default() { name= (char*) "DEFAULT"; } enum Type type() const { return DEFAULT_ITEM; } void make_field(Send_field *field) {} - bool save_in_field(Field *field) + int save_in_field(Field *field) { field->set_default(); return 0; @@ -340,7 +333,6 @@ public: virtual longlong val_int() { return 0; } virtual String *val_str(String *str) { return 0; } bool basic_const_item() const { return 1; } - unsigned int size_of() { return sizeof(*this);} }; @@ -352,7 +344,6 @@ public: Item_datetime(const char *item_name): Item_string(item_name,"",0,default_charset_info) { max_length=19;} void make_field(Send_field *field); - unsigned int size_of() { return sizeof(*this);} }; class Item_empty_string :public Item_string @@ -360,7 +351,6 @@ class Item_empty_string :public Item_string public: Item_empty_string(const char *header,uint length) :Item_string("",0,default_charset_info) { name=(char*) header; max_length=length;} - unsigned int size_of() { return sizeof(*this);} }; class Item_varbinary :public Item @@ -375,7 +365,6 @@ public: int save_in_field(Field *field); void make_field(Send_field *field); enum Item_result result_type () const { return INT_RESULT; } - unsigned int size_of() { return sizeof(*this);} }; @@ -388,7 +377,6 @@ public: Field *tmp_table_field(TABLE *t_arg=(TABLE *)0) { return result_field; } table_map used_tables() const { return 1; } virtual void fix_length_and_dec()=0; - unsigned int size_of() { return sizeof(*this);} }; @@ -438,7 +426,6 @@ public: void save_org_in_field(Field *field) { (*ref)->save_org_in_field(field); } enum Item_result result_type () const { return (*ref)->result_type(); } table_map used_tables() const { return (*ref)->used_tables(); } - unsigned int size_of() { return sizeof(*this);} }; @@ -458,10 +445,10 @@ public: { return ref->save_in_field(field); } - unsigned int size_of() { return sizeof(*this);} }; +#include "gstream.h" #include "spatial.h" #include "item_sum.h" #include "item_func.h" @@ -495,7 +482,6 @@ public: table_map used_tables() const { return (table_map) 1L; } bool const_item() const { return 0; } bool is_null() { return null_value; } - unsigned int size_of() { return sizeof(*this);} }; @@ -506,7 +492,6 @@ public: Item_buff() :null_value(0) {} virtual bool cmp(void)=0; virtual ~Item_buff(); /*line -e1509 */ - unsigned int size_of() { return sizeof(*this);} }; class Item_str_buff :public Item_buff @@ -517,7 +502,6 @@ public: Item_str_buff(Item *arg) :item(arg),value(arg->max_length) {} bool cmp(void); ~Item_str_buff(); // Deallocate String:s - unsigned int size_of() { return sizeof(*this);} }; @@ -528,7 +512,6 @@ class Item_real_buff :public Item_buff public: Item_real_buff(Item *item_par) :item(item_par),value(0.0) {} bool cmp(void); - unsigned int size_of() { return sizeof(*this);} }; class Item_int_buff :public Item_buff @@ -538,7 +521,6 @@ class Item_int_buff :public Item_buff public: Item_int_buff(Item *item_par) :item(item_par),value(0) {} bool cmp(void); - unsigned int size_of() { return sizeof(*this);} }; @@ -555,7 +537,6 @@ public: buff= (char*) sql_calloc(length=field->pack_length()); } bool cmp(void); - unsigned int size_of() { return sizeof(*this);} }; extern Item_buff *new_Item_buff(Item *item); diff --git a/sql/item_func.cc b/sql/item_func.cc index bd811726b47..ed7398b4f94 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -22,14 +22,13 @@ #endif #include "mysql_priv.h" +#include "slave.h" // for wait_for_master_pos #include <m_ctype.h> #include <hash.h> #include <time.h> #include <ft_global.h> #include <zlib.h> -#include "slave.h" // for wait_for_master_pos -#include "gstream.h" - +#include <assert.h> /* return TRUE if item is a constant */ @@ -231,9 +230,11 @@ Field *Item_func::tmp_table_field(TABLE *t_arg) break; case STRING_RESULT: if (max_length > 255) - res= new Field_blob(max_length, maybe_null, name, t_arg, binary); + res= new Field_blob(max_length, maybe_null, name, t_arg, binary, + str_value.charset()); else - res= new Field_string(max_length, maybe_null, name, t_arg, binary); + res= new Field_string(max_length, maybe_null, name, t_arg, binary, + str_value.charset()); break; } return res; @@ -2390,18 +2391,19 @@ longlong Item_func_bit_xor::val_int() Item *get_system_var(enum_var_type var_type, LEX_STRING name) { - if (!my_strcasecmp(name.str,"VERSION")) - return new Item_string("@@VERSION",server_version, - (uint) strlen(server_version)); + if (!my_strcasecmp(system_charset_info, name.str, "VERSION")) + return new Item_string("@@VERSION", server_version, + (uint) strlen(server_version), + system_charset_info); THD *thd=current_thd; Item *item; sys_var *var; char buff[MAX_SYS_VAR_LENGTH+3]; - if (!(var= find_sys_var(name.str))) + if (!(var= find_sys_var(name.str, name.length))) { - net_printf(&thd->net, ER_UNKNOWN_SYSTEM_VARIABLE, name.str); + net_printf(thd, ER_UNKNOWN_SYSTEM_VARIABLE, name.str); return 0; } if (!(item=var->item(thd, var_type))) @@ -2415,6 +2417,23 @@ Item *get_system_var(enum_var_type var_type, LEX_STRING name) } +Item *get_system_var(enum_var_type var_type, const char *var_name, uint length, + const char *item_name) +{ + THD *thd=current_thd; + Item *item; + sys_var *var; + + var= find_sys_var(var_name, length); + DBUG_ASSERT(var != 0); + if (!(item=var->item(thd, var_type))) + return 0; // Impossible + thd->safe_to_cache_query=0; + item->set_name(item_name); // Will use original name + return item; +} + + /* Check a user level lock. diff --git a/sql/item_func.h b/sql/item_func.h index 45427bec017..3ef25a1fae2 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -39,7 +39,7 @@ public: enum Functype { UNKNOWN_FUNC,EQ_FUNC,EQUAL_FUNC,NE_FUNC,LT_FUNC,LE_FUNC, GE_FUNC,GT_FUNC,FT_FUNC, LIKE_FUNC,NOTLIKE_FUNC,ISNULL_FUNC,ISNOTNULL_FUNC, - COND_AND_FUNC, COND_OR_FUNC, CONX_XOR_FUNC, BETWEEN, IN_FUNC, + COND_AND_FUNC, COND_OR_FUNC, COND_XOR_FUNC, BETWEEN, IN_FUNC, INTERVAL_FUNC, SP_EQUALS_FUNC, SP_DISJOINT_FUNC,SP_INTERSECTS_FUNC, SP_TOUCHES_FUNC,SP_CROSSES_FUNC,SP_WITHIN_FUNC, diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 2bc9b170fc1..1b091f29a6b 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -2394,8 +2394,6 @@ null: General functions for spatial objects ********************************************************/ -#include "gstream.h" - String *Item_func_geometry_from_text::val_str(String *str) { Geometry geom; @@ -2715,7 +2713,7 @@ String *Item_func_spatial_collection::val_str(String *str) } } - if (str->length() > max_allowed_packet) + if (str->length() > current_thd->variables.max_allowed_packet) goto ret; null_value = 0; diff --git a/sql/item_sum.h b/sql/item_sum.h index 3c86370c189..3e67f1e3624 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -70,7 +70,6 @@ public: void print(String *str); void fix_num_length_and_dec(); virtual bool setup(THD *thd) {return 0;} - unsigned int size_of() { return sizeof(*this);} }; @@ -85,7 +84,6 @@ public: longlong val_int() { return (longlong) val(); } /* Real as default */ String *val_str(String*str); void reset_field(); - unsigned int size_of() { return sizeof(*this);} }; @@ -100,7 +98,6 @@ public: double val() { return (double) val_int(); } String *val_str(String*str); enum Item_result result_type () const { return INT_RESULT; } - unsigned int size_of() { return sizeof(*this);} }; @@ -118,7 +115,6 @@ class Item_sum_sum :public Item_sum_num void reset_field(); void update_field(int offset); const char *func_name() const { return "sum"; } - unsigned int size_of() { return sizeof(*this);} }; @@ -141,7 +137,6 @@ class Item_sum_count :public Item_sum_int void reset_field(); void update_field(int offset); const char *func_name() const { return "count"; } - unsigned int size_of() { return sizeof(*this);} }; @@ -193,7 +188,6 @@ class Item_sum_count_distinct :public Item_sum_int void update_field(int offset) { return ; } // Never called const char *func_name() const { return "count_distinct"; } bool setup(THD *thd); - unsigned int size_of() { return sizeof(*this);} }; @@ -213,7 +207,6 @@ public: String *val_str(String*); void make_field(Send_field *field); void fix_length_and_dec() {} - unsigned int size_of() { return sizeof(*this);} }; @@ -235,7 +228,6 @@ class Item_sum_avg :public Item_sum_num Item *result_item(Field *field) { return new Item_avg_field(this); } const char *func_name() const { return "avg"; } - unsigned int size_of() { return sizeof(*this);} }; class Item_sum_std; @@ -252,7 +244,6 @@ public: bool is_null() { (void) val_int(); return null_value; } void make_field(Send_field *field); void fix_length_and_dec() {} - unsigned int size_of() { return sizeof(*this);} }; class Item_sum_std :public Item_sum_num @@ -273,7 +264,6 @@ class Item_sum_std :public Item_sum_num Item *result_item(Field *field) { return new Item_std_field(this); } const char *func_name() const { return "std"; } - unsigned int size_of() { return sizeof(*this);} }; @@ -316,7 +306,6 @@ class Item_sum_hybrid :public Item_sum void min_max_update_str_field(int offset); void min_max_update_real_field(int offset); void min_max_update_int_field(int offset); - unsigned int size_of() { return sizeof(*this);} }; @@ -328,7 +317,6 @@ public: bool add(); const char *func_name() const { return "min"; } - unsigned int size_of() { return sizeof(*this);} }; @@ -340,7 +328,6 @@ public: bool add(); const char *func_name() const { return "max"; } - unsigned int size_of() { return sizeof(*this);} }; @@ -356,7 +343,6 @@ class Item_sum_bit :public Item_sum_int void reset(); longlong val_int(); void reset_field(); - unsigned int size_of() { return sizeof(*this);} }; @@ -367,7 +353,6 @@ class Item_sum_or :public Item_sum_bit bool add(); void update_field(int offset); const char *func_name() const { return "bit_or"; } - unsigned int size_of() { return sizeof(*this);} }; @@ -378,7 +363,6 @@ class Item_sum_and :public Item_sum_bit bool add(); void update_field(int offset); const char *func_name() const { return "bit_and"; } - unsigned int size_of() { return sizeof(*this);} }; /* @@ -409,7 +393,6 @@ public: bool add(); void reset_field() {}; void update_field(int offset_arg) {}; - unsigned int size_of() { return sizeof(*this);} }; diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 566097893a8..b42b78c9c91 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -477,11 +477,10 @@ void Item_func_curtime::fix_length_and_dec() value=(longlong) ((ulong) ((uint) start->tm_hour)*10000L+ (ulong) (((uint) start->tm_min)*100L+ (uint) start->tm_sec)); - sprintf(buff,"%02d:%02d:%02d", - (int) start->tm_hour, - (int) start->tm_min, - (int) start->tm_sec); - buff_length=(uint) strlen(buff); + buff_length= my_sprintf(buff, (buff,"%02d:%02d:%02d", + (int) start->tm_hour, + (int) start->tm_min, + (int) start->tm_sec)); } void Item_func_now::fix_length_and_dec() @@ -497,14 +496,13 @@ void Item_func_now::fix_length_and_dec() (longlong) ((ulong) ((uint) start->tm_hour)*10000L+ (ulong) (((uint) start->tm_min)*100L+ (uint) start->tm_sec))); - sprintf(buff,"%04d-%02d-%02d %02d:%02d:%02d", - ((int) (start->tm_year+1900)) % 10000, - (int) start->tm_mon+1, - (int) start->tm_mday, - (int) start->tm_hour, - (int) start->tm_min, - (int) start->tm_sec); - buff_length=(uint) strlen(buff); + buff_length= (uint) my_sprintf(buff, (buff,"%04d-%02d-%02d %02d:%02d:%02d", + ((int) (start->tm_year+1900)) % 10000, + (int) start->tm_mon+1, + (int) start->tm_mday, + (int) start->tm_hour, + (int) start->tm_min, + (int) start->tm_sec)); /* For getdate */ ltime.year= start->tm_year+1900; ltime.month= start->tm_mon+1; @@ -538,6 +536,7 @@ String *Item_func_sec_to_time::val_str(String *str) char buff[23]; const char *sign=""; longlong seconds=(longlong) args[0]->val_int(); + ulong length; if ((null_value=args[0]->null_value)) return (String*) 0; if (seconds < 0) @@ -546,9 +545,9 @@ String *Item_func_sec_to_time::val_str(String *str) sign= "-"; } uint sec= (uint) ((ulonglong) seconds % 3600); - sprintf(buff,"%s%02lu:%02u:%02u",sign,(long) (seconds/3600), - sec/60, sec % 60); - str->copy(buff,(uint) strlen(buff)); + length= my_sprintf(buff,(buff,"%s%02lu:%02u:%02u",sign,(long) (seconds/3600), + sec/60, sec % 60)); + str->copy(buff, length); return str; } @@ -658,6 +657,7 @@ String *Item_func_date_format::val_str(String *str) TIME l_time; char intbuff[15]; uint size,weekday; + ulong length; if (!date_or_time) { @@ -750,40 +750,39 @@ String *Item_func_date_format::val_str(String *str) null_value=1; return 0; } - sprintf(intbuff,"%d",l_time.day); - str->append(intbuff); + length= my_sprintf(intbuff, (intbuff,"%d",l_time.day)); + str->append(intbuff, length); if (l_time.day >= 10 && l_time.day <= 19) str->append("th"); else { - switch (l_time.day %10) - { + switch (l_time.day %10) { case 1: - str->append("st"); + str->append("st",2); break; case 2: - str->append("nd"); + str->append("nd",2); break; case 3: - str->append("rd"); + str->append("rd",2); break; default: - str->append("th"); + str->append("th",2); break; } } break; case 'Y': sprintf(intbuff,"%04d",l_time.year); - str->append(intbuff); + str->append(intbuff,4); break; case 'y': sprintf(intbuff,"%02d",l_time.year%100); - str->append(intbuff); + str->append(intbuff,2); break; case 'm': sprintf(intbuff,"%02d",l_time.month); - str->append(intbuff); + str->append(intbuff,2); break; case 'c': sprintf(intbuff,"%d",l_time.month); @@ -791,7 +790,7 @@ String *Item_func_date_format::val_str(String *str) break; case 'd': sprintf(intbuff,"%02d",l_time.day); - str->append(intbuff); + str->append(intbuff,2); break; case 'e': sprintf(intbuff,"%d",l_time.day); @@ -799,16 +798,16 @@ String *Item_func_date_format::val_str(String *str) break; case 'H': sprintf(intbuff,"%02d",l_time.hour); - str->append(intbuff); + str->append(intbuff,2); break; case 'h': case 'I': sprintf(intbuff,"%02d", (l_time.hour+11)%12+1); - str->append(intbuff); + str->append(intbuff,2); break; case 'i': /* minutes */ sprintf(intbuff,"%02d",l_time.minute); - str->append(intbuff); + str->append(intbuff,2); break; case 'j': if (date_or_time) @@ -819,7 +818,7 @@ String *Item_func_date_format::val_str(String *str) sprintf(intbuff,"%03d", (int) (calc_daynr(l_time.year,l_time.month,l_time.day) - calc_daynr(l_time.year,1,1)) + 1); - str->append(intbuff); + str->append(intbuff,3); break; case 'k': sprintf(intbuff,"%d",l_time.hour); @@ -830,7 +829,7 @@ String *Item_func_date_format::val_str(String *str) str->append(intbuff); break; case 'p': - str->append(l_time.hour < 12 ? "AM" : "PM"); + str->append(l_time.hour < 12 ? "AM" : "PM",2); break; case 'r': sprintf(intbuff,(l_time.hour < 12) ? "%02d:%02d:%02d AM" : @@ -844,7 +843,8 @@ String *Item_func_date_format::val_str(String *str) str->append(intbuff); break; case 'T': - sprintf(intbuff,"%02d:%02d:%02d",l_time.hour,l_time.minute,l_time.second); + sprintf(intbuff,"%02d:%02d:%02d", l_time.hour, l_time.minute, + l_time.second); str->append(intbuff); break; case 'U': @@ -852,7 +852,7 @@ String *Item_func_date_format::val_str(String *str) { uint year; sprintf(intbuff,"%02d",calc_week(&l_time, 0, (*ptr) == 'U', &year)); - str->append(intbuff); + str->append(intbuff,2); } break; case 'v': @@ -860,7 +860,7 @@ String *Item_func_date_format::val_str(String *str) { uint year; sprintf(intbuff,"%02d",calc_week(&l_time, 1, (*ptr) == 'V', &year)); - str->append(intbuff); + str->append(intbuff,2); } break; case 'x': @@ -869,13 +869,13 @@ String *Item_func_date_format::val_str(String *str) uint year; (void) calc_week(&l_time, 1, (*ptr) == 'X', &year); sprintf(intbuff,"%04d",year); - str->append(intbuff); + str->append(intbuff,4); } break; case 'w': weekday=calc_weekday(calc_daynr(l_time.year,l_time.month,l_time.day),1); - sprintf(intbuff,"%01d",weekday); - str->append(intbuff); + sprintf(intbuff,"%d",weekday); + str->append(intbuff,1); break; default: str->append(*ptr); diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index a45ea159014..94e8e6eba43 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -176,7 +176,6 @@ public: const char *func_name() const { return "weekday"; } enum Item_result result_type () const { return INT_RESULT; } void fix_length_and_dec() { decimals=0; max_length=1; maybe_null=1; } - unsigned int size_of() { return sizeof(*this);} }; class Item_func_dayname :public Item_func_weekday @@ -202,7 +201,6 @@ public: { decimals=0; max_length=10; } - unsigned int size_of() { return sizeof(*this);} }; @@ -240,7 +238,6 @@ public: { return (!t_arg) ? result_field : new Field_date(maybe_null, name, t_arg); } - unsigned int size_of() { return sizeof(*this);} }; @@ -259,7 +256,6 @@ public: return (!t_arg) ? result_field : new Field_datetime(maybe_null, name, t_arg); } - unsigned int size_of() { return sizeof(*this);} }; @@ -286,7 +282,6 @@ public: { return (!t_arg) ? result_field : new Field_time(maybe_null, name, t_arg); } - unsigned int size_of() { return sizeof(*this);} }; @@ -300,7 +295,6 @@ public: const char *func_name() const { return "curdate"; } void fix_length_and_dec(); /* Retrieves curtime */ bool get_date(TIME *res,bool fuzzy_date); - unsigned int size_of() { return sizeof(*this);} }; @@ -322,7 +316,6 @@ public: const char *func_name() const { return "now"; } void fix_length_and_dec(); bool get_date(TIME *res,bool fuzzy_date); - unsigned int size_of() { return sizeof(*this);} }; @@ -347,7 +340,6 @@ public: const char *func_name() const { return "date_format"; } void fix_length_and_dec(); uint format_length(const String *format); - unsigned int size_of() { return sizeof(*this);} }; @@ -407,7 +399,6 @@ public: double val() { return (double) val_int(); } longlong val_int(); bool get_date(TIME *res,bool fuzzy_date); - unsigned int size_of() { return sizeof(*this);} }; class Item_extract :public Item_int_func @@ -421,7 +412,6 @@ class Item_extract :public Item_int_func longlong val_int(); const char *func_name() const { return "extract"; } void fix_length_and_dec(); - unsigned int size_of() { return sizeof(*this);} }; class Item_typecast :public Item_str_func diff --git a/sql/item_uniq.h b/sql/item_uniq.h index 6ab01d55e2f..f0d1d353cfb 100644 --- a/sql/item_uniq.h +++ b/sql/item_uniq.h @@ -29,9 +29,9 @@ public: :Item_real_func(list) {} double val() { return 0.0; } void fix_length_and_dec() { decimals=0; max_length=6; } - unsigned int size_of() { return sizeof(*this);} }; + class Item_sum_unique_users :public Item_sum_num { public: diff --git a/sql/lex.h b/sql/lex.h index 83890e75c20..b9e993c54c7 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -327,7 +327,6 @@ static SYMBOL symbols[] = { { "SQL_BUFFER_RESULT", SYM(SQL_BUFFER_RESULT),0,0}, { "SQL_CACHE", SYM(SQL_CACHE_SYM), 0, 0}, { "SQL_CALC_FOUND_ROWS", SYM(SQL_CALC_FOUND_ROWS),0,0}, - { "SQL_ERROR_COUNT", SYM(SQL_ERROR_COUNT),0,0}, { "SQL_NO_CACHE", SYM(SQL_NO_CACHE_SYM), 0, 0}, { "SQL_SMALL_RESULT", SYM(SQL_SMALL_RESULT),0,0}, { "SQL_THREAD", SYM(SQL_THREAD),0,0}, diff --git a/sql/log.cc b/sql/log.cc index b3ce1226210..213f5102507 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -215,15 +215,18 @@ bool MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg, time_t skr=time(NULL); struct tm tm_tmp; localtime_r(&skr,&tm_tmp); - sprintf(buff,"# %s, Version: %s at %02d%02d%02d %2d:%02d:%02d\n", - my_progname,server_version, - tm_tmp.tm_year % 100, - tm_tmp.tm_mon+1, - tm_tmp.tm_mday, - tm_tmp.tm_hour, - tm_tmp.tm_min, - tm_tmp.tm_sec); - if (my_b_write(&log_file, (byte*) buff,(uint) strlen(buff)) || + ulong length; + length= my_sprintf(buff, + (buff, + "# %s, Version: %s at %02d%02d%02d %2d:%02d:%02d\n", + my_progname,server_version, + tm_tmp.tm_year % 100, + tm_tmp.tm_mon+1, + tm_tmp.tm_mday, + tm_tmp.tm_hour, + tm_tmp.tm_min, + tm_tmp.tm_sec)); + if (my_b_write(&log_file, (byte*) buff, length) || flush_io_cache(&log_file)) goto err; break; @@ -931,7 +934,8 @@ bool MYSQL_LOG::write(THD *thd,enum enum_server_command command, { if (is_open() && (what_to_log & (1L << (uint) command))) { - int error=0; + uint length; + int error= 0; VOID(pthread_mutex_lock(&LOCK_log)); /* Test if someone closed after the is_open test */ @@ -965,6 +969,7 @@ bool MYSQL_LOG::write(THD *thd,enum enum_server_command command, last_time=skr; struct tm tm_tmp; struct tm *start; + ulong length; localtime_r(&skr,&tm_tmp); start=&tm_tmp; /* Note that my_b_write() assumes it knows the length for this */ @@ -980,8 +985,10 @@ bool MYSQL_LOG::write(THD *thd,enum enum_server_command command, } else if (my_b_write(&log_file, (byte*) "\t\t",2) < 0) error=errno; - sprintf(buff,"%7ld %-11.11s", id,command_name[(uint) command]); - if (my_b_write(&log_file, (byte*) buff,strlen(buff))) + length=my_sprintf(buff, + (buff, "%7ld %-11.11s", id, + command_name[(uint) command])); + if (my_b_write(&log_file, (byte*) buff,length)) error=errno; if (format) { @@ -1218,11 +1225,7 @@ err: /* Write update log in a format suitable for incremental backup - - NOTE - - This code should be deleted in MySQL 5,0 as the binary log - is a full replacement for the update log. - + This is also used by the slow query log. */ bool MYSQL_LOG::write(THD *thd,const char *query, uint query_length, diff --git a/sql/log_event.cc b/sql/log_event.cc index 23622bc0141..df5ef4eb7fe 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -1516,9 +1516,12 @@ void Append_block_log_event::print(FILE* file, bool short_form, #ifndef MYSQL_CLIENT void Append_block_log_event::pack_info(String* packet) { - char buf1[256]; - sprintf(buf1, ";file_id=%u;block_len=%u", file_id, block_len); - net_store_data(packet, buf1); + 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, length); } @@ -1560,9 +1563,10 @@ void Delete_file_log_event::print(FILE* file, bool short_form, #ifndef MYSQL_CLIENT void Delete_file_log_event::pack_info(String* packet) { - char buf1[64]; - sprintf(buf1, ";file_id=%u", (uint) file_id); - net_store_data(packet, buf1); + char buf[64]; + uint length; + length= (uint) my_sprintf(buf, (buf, ";file_id=%u", (uint) file_id)); + net_store_data(packet, buf, length); } #endif @@ -1607,8 +1611,9 @@ void Execute_load_log_event::print(FILE* file, bool short_form, void Execute_load_log_event::pack_info(String* packet) { char buf[64]; - sprintf(buf, ";file_id=%u", (uint) file_id); - net_store_data(packet, buf); + uint length; + length= (uint) my_sprintf(buf, (buf, ";file_id=%u", (uint) file_id)); + net_store_data(packet, buf, length); } #endif diff --git a/sql/mini_client.cc b/sql/mini_client.cc index 5bd88e9b09a..d678e76c5ed 100644 --- a/sql/mini_client.cc +++ b/sql/mini_client.cc @@ -40,6 +40,7 @@ #include "mysql_version.h" #include "mysqld_error.h" #include "errmsg.h" +#include <assert.h> #if defined( OS2) && defined(MYSQL_SERVER) #undef ER @@ -124,7 +125,7 @@ HANDLE create_named_pipe(NET *net, uint connect_timeout, char **arg_host, if (!host || !strcmp(host,LOCAL_HOST)) host=LOCAL_HOST_NAMEDPIPE; - sprintf( szPipeName, "\\\\%s\\pipe\\%s", host, unix_socket); + sprintf(szPipeName, "\\\\%s\\pipe\\%s", host, unix_socket); DBUG_PRINT("info",("Server name: '%s'. Named Pipe: %s", host, unix_socket)); @@ -456,15 +457,14 @@ mc_simple_command(MYSQL *mysql,enum enum_server_command command, if (!arg) arg=""; - if (net_write_command(net,(uchar) command,arg, - length ? length :(uint) strlen(arg))) + if (net_write_command(net, (uchar) command, NullS, 0, arg, length)) { - DBUG_PRINT("error",("Can't send command to server. Error: %d",socket_errno)); + DBUG_PRINT("error",("Can't send command to server. Error: %d", + socket_errno)); mc_end_server(mysql); if (mc_mysql_reconnect(mysql)) goto end; - if (net_write_command(net,(uchar) command,arg, - length ? length :(uint) strlen(arg))) + if (net_write_command(net,(uchar) command, NullS, 0, arg, length)) { net->last_errno=CR_SERVER_GONE_ERROR; strmov(net->last_error,ER(net->last_errno)); @@ -1027,18 +1027,19 @@ get_info: DBUG_RETURN(0); } -int mc_mysql_query(MYSQL *mysql, const char *query, uint length) + +int mc_mysql_query(MYSQL *mysql, const char *query, uint length) { - DBUG_ENTER("mysql_real_query"); + DBUG_ENTER("mc_mysql_query"); DBUG_PRINT("enter",("handle: %lx",mysql)); DBUG_PRINT("query",("Query = \"%s\"",query)); - if (!length) - length = strlen(query); + DBUG_ASSERT(length == strlen(query)); if (mc_simple_command(mysql,COM_QUERY,query,length,1)) DBUG_RETURN(-1); DBUG_RETURN(mc_mysql_read_query_result(mysql)); } + static int mc_send_file_to_server(MYSQL *mysql, const char *filename) { int fd, readcount, result= -1; diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 61973c5af91..4532646b1c2 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -294,7 +294,7 @@ inline THD *_current_thd(void) #define prepare_execute(A) ((A)->command == COM_EXECUTE) int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create, bool silent); -int mysql_alter_db(THD *thd, char *db, HA_CREATE_INFO *create, bool silent); +int mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create); int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent); void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos, ushort flags); int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists); @@ -308,8 +308,13 @@ int quick_rm_table(enum db_type base,const char *db, bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list); bool mysql_change_db(THD *thd,const char *name); void mysql_parse(THD *thd,char *inBuf,uint length); +void free_items(Item *item); +bool alloc_query(THD *thd, char *packet, ulong packet_length); void mysql_init_select(LEX *lex); +void mysql_init_query(THD *thd); +void mysql_reset_errors(THD *thd); bool mysql_new_select(LEX *lex, bool move_down); +void create_select_for_variable(const char *var_name); void mysql_init_multi_delete(LEX *lex); void init_max_user_conn(void); void free_max_user_conn(void); @@ -318,7 +323,7 @@ pthread_handler_decl(handle_bootstrap,arg); sig_handler end_thread_signal(int sig); void end_thread(THD *thd,bool put_in_cache); void flush_thread_cache(); -void mysql_execute_command(void); +void mysql_execute_command(THD *thd); bool do_command(THD *thd); bool dispatch_command(enum enum_server_command command, THD *thd, char* packet, uint packet_length); @@ -349,11 +354,12 @@ int mysql_optimize_table(THD* thd, TABLE_LIST* table_list, bool check_simple_select(); /* net_pkg.c */ -void send_warning(NET *net, uint sql_errno, const char *err=0); -void net_printf(NET *net,uint sql_errno, ...); -void send_ok(NET *net,ha_rows affected_rows=0L,ulonglong id=0L, +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(NET *net,bool no_flush=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); @@ -391,7 +397,7 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, int mysql_create_table(THD *thd,const char *db, const char *table_name, HA_CREATE_INFO *create_info, List<create_field> &fields, List<Key> &keys, - bool tmp_table, bool no_log); + bool tmp_table, bool no_log, uint select_field_count); TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info, const char *db, const char *name, List<create_field> *extra_fields, @@ -491,20 +497,19 @@ 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 compare_prep_stmt(PREP_STMT *a, PREP_STMT *b, void *not_used); +void free_prep_stmt(PREP_STMT *stmt, TREE_FREE mode, void *not_used); +bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length); +void mysql_stmt_execute(THD *thd, char *packet); +void mysql_stm_close(THD *thd, char *packet); +void mysql_stmt_get_longdata(THD *thd, char *pos, ulong packet_length); 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 *); +void push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level, uint code, + const char *msg); +my_bool mysqld_show_warnings(THD *thd, ulong levels_to_show); /* sql_handler.cc */ int mysql_ha_open(THD *thd, TABLE_LIST *tables); @@ -682,13 +687,13 @@ extern char f_fyllchar; extern MYSQL_LOG mysql_log,mysql_update_log,mysql_slow_log,mysql_bin_log; extern FILE *bootstrap_file; extern pthread_key(MEM_ROOT*,THR_MALLOC); -extern pthread_key(NET*, THR_NET); extern pthread_mutex_t LOCK_mysql_create_db,LOCK_Acl,LOCK_open, LOCK_thread_count,LOCK_mapped_file,LOCK_user_locks, LOCK_status, - LOCK_grant, LOCK_error_log, LOCK_delayed_insert, + LOCK_error_log, LOCK_delayed_insert, LOCK_delayed_status, LOCK_delayed_create, LOCK_crypt, LOCK_timezone, LOCK_slave_list, LOCK_active_mi, LOCK_manager, LOCK_global_system_variables; +extern rw_lock_t LOCK_grant; extern pthread_cond_t COND_refresh, COND_thread_count, COND_manager; extern pthread_attr_t connection_attrib; extern I_List<THD> threads; @@ -737,7 +742,7 @@ bool wait_for_locked_table_names(THD *thd, TABLE_LIST *table_list); void unireg_init(ulong options); void unireg_end(int signal); -int rea_create_table(my_string file_name,HA_CREATE_INFO *create_info, +int rea_create_table(THD *thd, my_string file_name,HA_CREATE_INFO *create_info, List<create_field> &create_field, uint key_count,KEY *key_info); int format_number(uint inputflag,uint max_length,my_string pos,uint length, @@ -818,6 +823,8 @@ extern int sql_cache_hit(THD *thd, char *inBuf, uint length); /* item.cc */ Item *get_system_var(enum_var_type var_type, LEX_STRING name); +Item *get_system_var(enum_var_type var_type, const char *var_name, uint length, + const char *item_name); /* Some inline functions for more speed */ diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 89f1c07b2fe..8c3db86e44f 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -240,6 +240,8 @@ SHOW_COMP_OPTION have_query_cache=SHOW_OPTION_YES; SHOW_COMP_OPTION have_query_cache=SHOW_OPTION_NO; #endif +const char *show_comp_option_name[]= {"YES", "NO", "DISABLED"}; + bool opt_large_files= sizeof(my_off_t) > 4; /* @@ -413,15 +415,14 @@ my_bool use_temp_pool=0; pthread_key(MEM_ROOT*,THR_MALLOC); pthread_key(THD*, THR_THD); -pthread_key(NET*, THR_NET); pthread_mutex_t LOCK_mysql_create_db, LOCK_Acl, LOCK_open, LOCK_thread_count, - LOCK_mapped_file, LOCK_status, LOCK_grant, + LOCK_mapped_file, LOCK_status, LOCK_error_log, LOCK_delayed_insert, LOCK_delayed_status, LOCK_delayed_create, LOCK_crypt, LOCK_bytes_sent, LOCK_bytes_received, LOCK_global_system_variables, LOCK_user_conn, LOCK_slave_list, LOCK_active_mi; - +rw_lock_t LOCK_grant; pthread_cond_t COND_refresh,COND_thread_count, COND_slave_stopped, COND_slave_start; pthread_cond_t COND_thread_cache,COND_flush_thread_cache; @@ -1042,7 +1043,7 @@ static void server_init(void) if (Service.IsNT() && mysql_unix_port[0] && !opt_bootstrap && opt_enable_named_pipe) { - sprintf( szPipeName, "\\\\.\\pipe\\%s", mysql_unix_port ); + sprintf(szPipeName, "\\\\.\\pipe\\%s", mysql_unix_port ); ZeroMemory( &saPipeSecurity, sizeof(saPipeSecurity) ); ZeroMemory( &sdPipeDescriptor, sizeof(sdPipeDescriptor) ); if ( !InitializeSecurityDescriptor(&sdPipeDescriptor, @@ -1127,12 +1128,12 @@ static void server_init(void) void yyerror(const char *s) { - NET *net=my_pthread_getspecific_ptr(NET*,THR_NET); - char *yytext=(char*) current_lex->tok_start; + THD *thd=current_thd; + char *yytext=(char*) thd->lex.tok_start; if (!strcmp(s,"parse error")) s=ER(ER_SYNTAX_ERROR); - net_printf(net,ER_PARSE_ERROR, s, yytext ? (char*) yytext : "", - current_lex->yylineno); + net_printf(thd,ER_PARSE_ERROR, s, yytext ? (char*) yytext : "", + thd->lex.yylineno); } @@ -1148,7 +1149,7 @@ void close_connection(NET *net,uint errcode,bool lock) if ((vio=net->vio) != 0) { if (errcode) - send_error(net,errcode,ER(errcode)); /* purecov: inspected */ + net_send_error(net,errcode,ER(errcode)); /* purecov: inspected */ vio_close(vio); /* vio is freed in delete thd */ } if (lock) @@ -1541,8 +1542,8 @@ static void *signal_hand(void *arg __attribute__((unused))) if ((pidFile = my_create(pidfile_name,0664, O_WRONLY, MYF(MY_WME))) >= 0) { char buff[21]; - sprintf(buff,"%lu",(ulong) getpid()); - (void) my_write(pidFile, buff,strlen(buff),MYF(MY_WME)); + ulong length= my_sprintf(buff, (buff,"%lu",(ulong) getpid())); + (void) my_write(pidFile, buff, length, MYF(MY_WME)); (void) my_close(pidFile,MYF(0)); } } @@ -1640,11 +1641,12 @@ static void *signal_hand(void *arg __attribute__((unused))) static int my_message_sql(uint error, const char *str, myf MyFlags __attribute__((unused))) { - NET *net; + THD *thd; DBUG_ENTER("my_message_sql"); DBUG_PRINT("error",("Message: '%s'",str)); - if ((net=my_pthread_getspecific_ptr(NET*,THR_NET))) + if ((thd=current_thd)) { + NET *net= &thd->net; if (!net->last_error[0]) // Return only first message { strmake(net->last_error,str,sizeof(net->last_error)-1); @@ -1853,7 +1855,6 @@ int main(int argc, char **argv) (void) pthread_mutex_init(&LOCK_mysql_create_db,MY_MUTEX_INIT_SLOW); (void) pthread_mutex_init(&LOCK_Acl,MY_MUTEX_INIT_SLOW); - (void) pthread_mutex_init(&LOCK_grant,MY_MUTEX_INIT_FAST); (void) pthread_mutex_init(&LOCK_open,MY_MUTEX_INIT_FAST); (void) pthread_mutex_init(&LOCK_thread_count,MY_MUTEX_INIT_FAST); (void) pthread_mutex_init(&LOCK_mapped_file,MY_MUTEX_INIT_SLOW); @@ -1871,6 +1872,7 @@ int main(int argc, char **argv) (void) pthread_mutex_init(&LOCK_rpl_status, MY_MUTEX_INIT_FAST); (void) pthread_mutex_init(&LOCK_active_mi, MY_MUTEX_INIT_FAST); (void) pthread_mutex_init(&LOCK_global_system_variables, MY_MUTEX_INIT_FAST); + (void) my_rwlock_init(&LOCK_grant, NULL); (void) pthread_cond_init(&COND_thread_count,NULL); (void) pthread_cond_init(&COND_refresh,NULL); (void) pthread_cond_init(&COND_thread_cache,NULL); @@ -2027,7 +2029,7 @@ int main(int argc, char **argv) After this we can't quit by a simple unireg_abort */ error_handler_hook = my_message_sql; - if (pthread_key_create(&THR_THD,NULL) || pthread_key_create(&THR_NET,NULL) || + if (pthread_key_create(&THR_THD,NULL) || pthread_key_create(&THR_MALLOC,NULL)) { sql_print_error("Can't create thread-keys"); @@ -2481,7 +2483,7 @@ static void create_new_thread(THD *thd) thread_count--; thd->killed=1; // Safety (void) pthread_mutex_unlock(&LOCK_thread_count); - net_printf(net,ER_CANT_CREATE_THREAD,error); + net_printf(thd,ER_CANT_CREATE_THREAD,error); (void) pthread_mutex_lock(&LOCK_thread_count); close_connection(net,0,0); delete thd; @@ -2886,6 +2888,7 @@ enum options { OPT_MAX_JOIN_SIZE, OPT_MAX_SORT_LENGTH, OPT_MAX_TMP_TABLES, OPT_MAX_USER_CONNECTIONS, OPT_MAX_WRITE_LOCK_COUNT, OPT_BULK_INSERT_BUFFER_SIZE, + OPT_MAX_ERROR_COUNT, OPT_MAX_PREP_STMT, OPT_MYISAM_BLOCK_SIZE, OPT_MYISAM_MAX_EXTRA_SORT_FILE_SIZE, OPT_MYISAM_MAX_SORT_FILE_SIZE, OPT_MYISAM_SORT_BUFFER_SIZE, OPT_NET_BUFFER_LENGTH, OPT_NET_RETRY_COUNT, @@ -3506,6 +3509,11 @@ struct my_option my_long_options[] = "Don't start more than this number of threads to handle INSERT DELAYED statements.", (gptr*) &max_insert_delayed_threads, (gptr*) &max_insert_delayed_threads, 0, GET_ULONG, REQUIRED_ARG, 20, 1, 16384, 0, 1, 0}, + {"max_error_count", OPT_MAX_ERROR_COUNT, + "Max number of errors/warnings to store for a statement", + (gptr*) &global_system_variables.max_error_count, + (gptr*) &max_system_variables.max_error_count, + 0, GET_ULONG, REQUIRED_ARG, DEFAULT_ERROR_COUNT, 1, 65535, 0, 1, 0}, {"max_heap_table_size", OPT_MAX_HEP_TABLE_SIZE, "Don't allow creation of heap tables bigger than this.", (gptr*) &global_system_variables.max_heap_table_size, @@ -3516,6 +3524,11 @@ struct my_option my_long_options[] = (gptr*) &global_system_variables.max_join_size, (gptr*) &max_system_variables.max_join_size, 0, GET_ULONG, REQUIRED_ARG, ~0L, 1, ~0L, 0, 1, 0}, + {"max_prepared_statements", OPT_MAX_PREP_STMT, + "Max number of prepared_statements for a thread", + (gptr*) &global_system_variables.max_prep_stmt_count, + (gptr*) &max_system_variables.max_prep_stmt_count, 0, GET_ULONG, + REQUIRED_ARG, DEFAULT_PREP_STMT_COUNT, 0, ~0L, 0, 1, 0}, {"max_sort_length", OPT_MAX_SORT_LENGTH, "The number of bytes to use when sorting BLOB or TEXT values (only the first max_sort_length bytes of each value are used; the rest are ignored).", (gptr*) &global_system_variables.max_sort_length, diff --git a/sql/net_pkg.cc b/sql/net_pkg.cc index 1e7536e3007..19234181839 100644 --- a/sql/net_pkg.cc +++ b/sql/net_pkg.cc @@ -20,19 +20,17 @@ /* Send a error string to client */ -void send_error(NET *net, uint sql_errno, const char *err) +void send_error(THD *thd, uint sql_errno, const char *err) { uint length; char buff[MYSQL_ERRMSG_SIZE+2]; - THD *thd=current_thd; + 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")); + net->last_error : "NULL")); query_cache_abort(net); - if (thd) - thd->query_error = 1; // needed to catch query errors during replication if (!err) { if (sql_errno) @@ -48,10 +46,9 @@ void send_error(NET *net, uint sql_errno, const char *err) } } } - push_error(sql_errno, err); if (net->vio == 0) { - if (thd && thd->bootstrap) + if (thd->bootstrap) { /* In bootstrap it's ok to print on stderr */ fprintf(stderr,"ERROR: %d %s\n",sql_errno,err); @@ -68,53 +65,73 @@ void send_error(NET *net, uint sql_errno, const char *err) else { length=(uint) strlen(err); - set_if_smaller(length,MYSQL_ERRMSG_SIZE); + set_if_smaller(length,MYSQL_ERRMSG_SIZE-1); } - VOID(net_write_command(net,(uchar) 255,(char*) err,length)); - if (thd) - thd->fatal_error=0; // Error message is given + VOID(net_write_command(net,(uchar) 255, "", 0, (char*) err,length)); + thd->fatal_error=0; // Error message is given DBUG_VOID_RETURN; } /* - At some point we need to be able to distinguish between warnings and - errors; The following function will help make this easier. + 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 send_warning(NET *net, uint sql_errno, const char *err) +void net_send_error(NET *net, uint sql_errno, const char *err) { - DBUG_ENTER("send_warning"); - push_warning(sql_errno, err ? err : ER(sql_errno)); + char buff[2]; + uint length; + DBUG_ENTER("send_net_error"); - /* - TODO : - Try to return ok with warning status to client, instead - of returning error .. - */ - send_error(net,sql_errno,err); + 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 allow another buffer + It's a little too low level, but I don't want to use another buffer for + this */ -/* VARARGS3 */ void -net_printf(NET *net, uint errcode, ...) +net_printf(THD *thd, uint errcode, ...) { va_list args; uint length,offset; const char *format,*text_pos; int head_length= NET_HEADER_SIZE; - THD *thd=current_thd; + NET *net= &thd->net; DBUG_ENTER("net_printf"); DBUG_PRINT("enter",("message: %u",errcode)); - if (thd) - thd->query_error = 1; // if we are here, something is wrong :-) query_cache_abort(net); // Safety va_start(args,errcode); /* @@ -132,10 +149,9 @@ net_printf(NET *net, uint errcode, ...) length=sizeof(net->last_error)-1; /* purecov: inspected */ va_end(args); - push_error(errcode, text_pos); if (net->vio == 0) { - if (thd && thd->bootstrap) + if (thd->bootstrap) { /* In bootstrap it's ok to print on stderr */ fprintf(stderr,"ERROR: %d %s\n",errcode,text_pos); @@ -150,16 +166,42 @@ net_printf(NET *net, uint errcode, ...) if (offset) int2store(text_pos-2, errcode); VOID(net_real_write(net,(char*) net->buff,length+head_length+1+offset)); - if (thd) - thd->fatal_error=0; // Error message is given + 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(NET *net,ha_rows affected_rows,ulonglong id,const char *message) +send_ok(THD *thd, ha_rows affected_rows, ulonglong id, const char *message) { - if (net->no_send_ok) // hack for re-parsing queries + NET *net= &thd->net; + if (net->no_send_ok || !net->vio) // hack for re-parsing queries return; char buff[MYSQL_ERRMSG_SIZE+10],*pos; @@ -167,31 +209,75 @@ send_ok(NET *net,ha_rows affected_rows,ulonglong id,const char *message) buff[0]=0; // No fields pos=net_store_length(buff+1,(ulonglong) affected_rows); pos=net_store_length(pos, (ulonglong) id); - if (net->return_status) + 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,*net->return_status); + int2store(pos,thd->server_status); pos+=2; } if (message) pos=net_store_data((char*) pos,message); - if (net->vio != 0) - { - VOID(my_net_write(net,buff,(uint) (pos-buff))); - VOID(net_flush(net)); - } + 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(NET *net,bool no_flush) +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) { - VOID(my_net_write(net,eof_buff,1)); - if (!no_flush) + if (!no_flush && (thd->client_capabilities & CLIENT_PROTOCOL_41)) + { + char 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,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; } diff --git a/sql/net_serv.cc b/sql/net_serv.cc index bb7100f31be..538ff5babe6 100644 --- a/sql/net_serv.cc +++ b/sql/net_serv.cc @@ -75,12 +75,12 @@ extern pthread_mutex_t LOCK_bytes_sent , LOCK_bytes_received; #define TEST_BLOCKING 8 #define MAX_THREE_BYTES 255L*255L*255L -static int net_write_buff(NET *net,const char *packet,ulong len); +static my_bool net_write_buff(NET *net,const char *packet,ulong len); /* Init with packet info */ -int my_net_init(NET *net, Vio* vio) +my_bool my_net_init(NET *net, Vio* vio) { DBUG_ENTER("my_net_init"); my_net_local_init(net); /* Set some limits */ @@ -127,7 +127,7 @@ void net_end(NET *net) /* Realloc the packet buffer */ -static my_bool net_realloc(NET *net, ulong length) +my_bool net_realloc(NET *net, ulong length) { uchar *buff; ulong pkt_length; @@ -184,14 +184,14 @@ void net_clear(NET *net) /* Flush write_buffer if not empty. */ -int net_flush(NET *net) +my_bool net_flush(NET *net) { - int error=0; + my_bool error= 0; DBUG_ENTER("net_flush"); if (net->buff != net->write_pos) { - error=net_real_write(net,(char*) net->buff, - (ulong) (net->write_pos - net->buff)); + error=test(net_real_write(net,(char*) net->buff, + (ulong) (net->write_pos - net->buff))); net->write_pos=net->buff; } /* Sync packet number if using compression */ @@ -212,7 +212,7 @@ int net_flush(NET *net) ** NOTE: If compression is used the original package is modified! */ -int +my_bool my_net_write(NET *net,const char *packet,ulong len) { uchar buff[NET_HEADER_SIZE]; @@ -242,17 +242,38 @@ my_net_write(NET *net,const char *packet,ulong len) /* Send a command to the server. - As the command is part of the first data packet, we have to do some data - juggling to put the command in there, without having to create a new - packet. - This function will split big packets into sub-packets if needed. - (Each sub packet can only be 2^24 bytes) + + SYNOPSIS + net_write_command() + net NET handler + command Command in MySQL server (enum enum_server_command) + header Header to write after command + head_len Length of header + packet Query or parameter to query + len Length of packet + + DESCRIPTION + The reason for having both header and packet is so that libmysql + can easy add a header to a special command (like prepared statements) + without having to re-alloc the string. + + As the command is part of the first data packet, we have to do some data + juggling to put the command in there, without having to create a new + packet. + This function will split big packets into sub-packets if needed. + (Each sub packet can only be 2^24 bytes) + + RETURN VALUES + 0 ok + 1 error */ -int -net_write_command(NET *net,uchar command,const char *packet,ulong len) +my_bool +net_write_command(NET *net,uchar command, + const char *header, ulong head_len, + const char *packet, ulong len) { - ulong length=len+1; /* 1 extra byte for command */ + ulong length=len+1+head_len; /* 1 extra byte for command */ uchar buff[NET_HEADER_SIZE+1]; uint header_size=NET_HEADER_SIZE+1; buff[4]=command; /* For first packet */ @@ -260,25 +281,28 @@ net_write_command(NET *net,uchar command,const char *packet,ulong len) if (length >= MAX_THREE_BYTES) { /* Take into account that we have the command in the first header */ - len= MAX_THREE_BYTES -1; + len= MAX_THREE_BYTES - 1 - head_len; do { int3store(buff, MAX_THREE_BYTES); buff[3]= (uchar) net->pkt_nr++; if (net_write_buff(net,(char*) buff, header_size) || - net_write_buff(net,packet,len)) + net_write_buff(net, header, head_len) || + net_write_buff(net, packet, len)) return 1; packet+= len; length-= MAX_THREE_BYTES; len=MAX_THREE_BYTES; + head_len=0; header_size=NET_HEADER_SIZE; } while (length >= MAX_THREE_BYTES); len=length; /* Data left to be written */ } int3store(buff,length); buff[3]= (uchar) net->pkt_nr++; - return test(net_write_buff(net,(char*) buff,header_size) || - net_write_buff(net,packet,len) || net_flush(net)); + return test(net_write_buff(net, (char*) buff, header_size) || + (head_len && net_write_buff(net, (char*) header, head_len)) || + net_write_buff(net, packet, len) || net_flush(net)); } /* @@ -286,7 +310,7 @@ net_write_command(NET *net,uchar command,const char *packet,ulong len) One can force the buffer to be flushed with 'net_flush'. */ -static int +static my_bool net_write_buff(NET *net,const char *packet,ulong len) { ulong left_length=(ulong) (net->buff_end - net->write_pos); @@ -815,13 +839,3 @@ my_net_read(NET *net) #endif /* HAVE_COMPRESS */ return len; } - -bool net_request_file(NET* net, const char* fname) -{ - char tmp [FN_REFLEN+1],*end; - DBUG_ENTER("net_request_file"); - tmp[0] = (char) 251; /* NULL_LENGTH */ - end=strnmov(tmp+1,fname,sizeof(tmp)-2); - DBUG_RETURN(my_net_write(net,tmp,(uint) (end-tmp)) || - net_flush(net)); -} diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc index 04f1ffce00e..3d4a7893790 100644 --- a/sql/repl_failsafe.cc +++ b/sql/repl_failsafe.cc @@ -186,7 +186,7 @@ err: my_message(ER_UNKNOWN_ERROR, "Wrong parameters to function register_slave", MYF(0)); err2: - send_error(&thd->net); + send_error(thd); return 1; } @@ -425,10 +425,10 @@ int show_new_master(THD* thd) if (translate_master(thd, lex_mi, errmsg)) { if (errmsg[0]) - net_printf(&thd->net, ER_ERROR_WHEN_EXECUTING_COMMAND, + net_printf(thd, ER_ERROR_WHEN_EXECUTING_COMMAND, "SHOW NEW MASTER", errmsg); else - send_error(&thd->net, 0); + send_error(thd, 0); DBUG_RETURN(1); } @@ -444,7 +444,7 @@ int show_new_master(THD* thd) net_store_data(packet, (longlong)lex_mi->pos); if (my_net_write(&thd->net, packet->ptr(), packet->length())) DBUG_RETURN(-1); - send_eof(&thd->net); + send_eof(thd); DBUG_RETURN(0); } } @@ -459,7 +459,7 @@ int update_slave_list(MYSQL* mysql) int port_ind; DBUG_ENTER("update_slave_list"); - if (mc_mysql_query(mysql,"SHOW SLAVE HOSTS",0) || + if (mc_mysql_query(mysql,"SHOW SLAVE HOSTS",16) || !(res = mc_mysql_store_result(mysql))) { error = "Query error"; @@ -623,7 +623,7 @@ int show_slave_hosts(THD* thd) } } pthread_mutex_unlock(&LOCK_slave_list); - send_eof(net); + send_eof(thd); DBUG_RETURN(0); } @@ -709,7 +709,7 @@ int load_master_data(THD* thd) (error=terminate_slave_threads(active_mi,restart_thread_mask, 1 /*skip lock*/))) { - send_error(&thd->net,error); + send_error(thd,error); unlock_slave_threads(active_mi); UNLOCK_ACTIVE_MI; return 1; @@ -717,7 +717,7 @@ int load_master_data(THD* thd) if (connect_to_master(thd, &mysql, active_mi)) { - net_printf(&thd->net, error= ER_CONNECT_TO_MASTER, + net_printf(thd, error= ER_CONNECT_TO_MASTER, mc_mysql_error(&mysql)); goto err; } @@ -727,10 +727,10 @@ int load_master_data(THD* thd) MYSQL_RES *db_res, **table_res, **table_res_end, **cur_table_res; uint num_dbs; - if (mc_mysql_query(&mysql, "show databases", 0) || + if (mc_mysql_query(&mysql, "SHOW DATABASES", 14) || !(db_res = mc_mysql_store_result(&mysql))) { - net_printf(&thd->net, error = ER_QUERY_ON_MASTER, + net_printf(thd, error = ER_QUERY_ON_MASTER, mc_mysql_error(&mysql)); goto err; } @@ -744,7 +744,7 @@ int load_master_data(THD* thd) if (!(table_res = (MYSQL_RES**)thd->alloc(num_dbs * sizeof(MYSQL_RES*)))) { - net_printf(&thd->net, error = ER_OUTOFMEMORY); + net_printf(thd, error = ER_OUTOFMEMORY); goto err; } @@ -754,11 +754,11 @@ int load_master_data(THD* thd) we wait to issue FLUSH TABLES WITH READ LOCK for as long as we can to minimize the lock time. */ - if (mc_mysql_query(&mysql, "FLUSH TABLES WITH READ LOCK", 0) || - mc_mysql_query(&mysql, "SHOW MASTER STATUS",0) || + if (mc_mysql_query(&mysql, "FLUSH TABLES WITH READ LOCK", 27) || + mc_mysql_query(&mysql, "SHOW MASTER STATUS",18) || !(master_status_res = mc_mysql_store_result(&mysql))) { - net_printf(&thd->net, error = ER_QUERY_ON_MASTER, + net_printf(thd, error = ER_QUERY_ON_MASTER, mc_mysql_error(&mysql)); goto err; } @@ -798,16 +798,16 @@ int load_master_data(THD* thd) if (mysql_rm_db(thd, db, 1,1) || mysql_create_db(thd, db, 0, 1)) { - send_error(&thd->net, 0, 0); + send_error(thd, 0, 0); cleanup_mysql_results(db_res, cur_table_res - 1, table_res); goto err; } if (mc_mysql_select_db(&mysql, db) || - mc_mysql_query(&mysql, "show tables", 0) || + mc_mysql_query(&mysql, "SHOW TABLES", 11) || !(*cur_table_res = mc_mysql_store_result(&mysql))) { - net_printf(&thd->net, error = ER_QUERY_ON_MASTER, + net_printf(thd, error = ER_QUERY_ON_MASTER, mc_mysql_error(&mysql)); cleanup_mysql_results(db_res, cur_table_res - 1, table_res); goto err; @@ -848,9 +848,9 @@ int load_master_data(THD* thd) mc_mysql_free_result(master_status_res); } - if (mc_mysql_query(&mysql, "UNLOCK TABLES", 0)) + if (mc_mysql_query(&mysql, "UNLOCK TABLES", 13)) { - net_printf(&thd->net, error = ER_QUERY_ON_MASTER, + net_printf(thd, error = ER_QUERY_ON_MASTER, mc_mysql_error(&mysql)); goto err; } @@ -860,7 +860,7 @@ int load_master_data(THD* thd) 0 /* not only reset, but also reinit */, &errmsg)) { - send_error(&thd->net, 0, "Failed purging old relay logs"); + send_error(thd, 0, "Failed purging old relay logs"); unlock_slave_threads(active_mi); UNLOCK_ACTIVE_MI; return 1; @@ -888,7 +888,7 @@ err: mc_mysql_close(&mysql); // safe to call since we always do mc_mysql_init() if (!error) - send_ok(&thd->net); + send_ok(thd); return error; } diff --git a/sql/set_var.cc b/sql/set_var.cc index 3c71d1d32e3..29c9ac09131 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -24,8 +24,9 @@ - Use one of the 'sys_var... classes from set_var.h or write a specific one for the variable type. - Define it in the 'variable definition list' in this file. - - If the variable should be changeable, it should be added to the - 'list of all variables' list in this file. + - If the variable should be changeable or one should be able to access it + with @@variable_name, it should be added to the 'list of all variables' + list in this file. - If the variable should be changed from the command line, add a definition of it in the my_option structure list in mysqld.dcc - If the variable should show up in 'show variables' add it to the @@ -82,6 +83,8 @@ static void fix_net_retry_count(THD *thd, enum_var_type type); static void fix_max_join_size(THD *thd, enum_var_type type); static void fix_query_cache_size(THD *thd, enum_var_type type); static void fix_key_buffer_size(THD *thd, enum_var_type type); +static byte *get_error_count(THD *thd); +static byte *get_warning_count(THD *thd); /* Variable definition list @@ -147,6 +150,8 @@ sys_var_long_ptr sys_max_connect_errors("max_connect_errors", &max_connect_errors); sys_var_long_ptr sys_max_delayed_threads("max_delayed_threads", &max_insert_delayed_threads); +sys_var_thd_ulong sys_max_error_count("max_error_count", + &SV::max_error_count); sys_var_thd_ulong sys_max_heap_table_size("max_heap_table_size", &SV::max_heap_table_size); sys_var_thd_ulong sys_max_join_size("max_join_size", @@ -157,6 +162,8 @@ sys_var_thd_ulong sys_sql_max_join_size("sql_max_join_size", &SV::max_join_size, fix_max_join_size); #endif +sys_var_thd_ulong sys_max_prep_stmt_count("max_prepared_statements", + &SV::max_prep_stmt_count); sys_var_thd_ulong sys_max_sort_length("max_sort_length", &SV::max_sort_length); sys_var_long_ptr sys_max_user_connections("max_user_connections", @@ -220,8 +227,6 @@ sys_var_thd_ulong sys_tmp_table_size("tmp_table_size", &SV::tmp_table_size); sys_var_thd_ulong sys_net_wait_timeout("wait_timeout", &SV::net_wait_timeout); - - /* Variables that are bits in THD */ @@ -283,6 +288,15 @@ static sys_var_timestamp sys_timestamp("timestamp"); static sys_var_last_insert_id sys_last_insert_id("last_insert_id"); static sys_var_last_insert_id sys_identity("identity"); static sys_var_insert_id sys_insert_id("insert_id"); +static sys_var_readonly sys_error_count("error_count", + OPT_SESSION, + SHOW_LONG, + get_error_count); +static sys_var_readonly sys_warning_count("warning_count", + OPT_SESSION, + SHOW_LONG, + get_warning_count); + /* alias for last_insert_id() to be compatible with Sybase */ static sys_var_slave_skip_counter sys_slave_skip_counter("sql_slave_skip_counter"); @@ -311,6 +325,7 @@ sys_var *sys_variables[]= &sys_delayed_insert_limit, &sys_delayed_insert_timeout, &sys_delayed_queue_size, + &sys_error_count, &sys_flush, &sys_flush_time, &sys_foreign_key_checks, @@ -333,8 +348,10 @@ sys_var *sys_variables[]= &sys_max_connect_errors, &sys_max_connections, &sys_max_delayed_threads, + &sys_max_error_count, &sys_max_heap_table_size, &sys_max_join_size, + &sys_max_prep_stmt_count, &sys_max_sort_length, &sys_max_tmp_tables, &sys_max_user_connections, @@ -375,7 +392,8 @@ sys_var *sys_variables[]= &sys_timestamp, &sys_tmp_table_size, &sys_tx_isolation, - &sys_unique_checks + &sys_unique_checks, + &sys_warning_count }; @@ -465,9 +483,11 @@ struct show_var_st init_vars[]= { {sys_max_binlog_size.name, (char*) &sys_max_binlog_size, SHOW_SYS}, {sys_max_connections.name, (char*) &sys_max_connections, SHOW_SYS}, {sys_max_connect_errors.name, (char*) &sys_max_connect_errors, SHOW_SYS}, + {sys_max_error_count.name, (char*) &sys_max_error_count, SHOW_SYS}, {sys_max_delayed_threads.name,(char*) &sys_max_delayed_threads, SHOW_SYS}, {sys_max_heap_table_size.name,(char*) &sys_max_heap_table_size, SHOW_SYS}, {sys_max_join_size.name, (char*) &sys_max_join_size, SHOW_SYS}, + {sys_max_prep_stmt_count.name,(char*) &sys_max_prep_stmt_count, SHOW_SYS}, {sys_max_sort_length.name, (char*) &sys_max_sort_length, SHOW_SYS}, {sys_max_user_connections.name,(char*) &sys_max_user_connections, SHOW_SYS}, {sys_max_tmp_tables.name, (char*) &sys_max_tmp_tables, SHOW_SYS}, @@ -793,7 +813,7 @@ byte *sys_var_thd_bool::value_ptr(THD *thd, enum_var_type type) bool sys_var::check_enum(THD *thd, set_var *var, TYPELIB *enum_names) { char buff[80], *value; - String str(buff,sizeof(buff)), *res; + String str(buff, sizeof(buff), system_charset_info), *res; if (var->value->result_type() == STRING_RESULT) { @@ -831,6 +851,10 @@ err: We have to use netprintf() instead of my_error() here as this is called on the parsing stage. + + TODO: + With prepared statements/stored procedures this has to be fixed + to create an item that gets the current value at fix_fields() stage. */ Item *sys_var::item(THD *thd, enum_var_type var_type) @@ -839,7 +863,7 @@ Item *sys_var::item(THD *thd, enum_var_type var_type) { if (var_type != OPT_DEFAULT) { - net_printf(&thd->net, + net_printf(thd, var_type == OPT_GLOBAL ? ER_LOCAL_VARIABLE : ER_GLOBAL_VARIABLE, name); return 0; @@ -857,10 +881,10 @@ Item *sys_var::item(THD *thd, enum_var_type var_type) case SHOW_CHAR: { char *str= (char*) value_ptr(thd, var_type); - return new Item_string(str,strlen(str)); + return new Item_string(str, strlen(str), system_charset_info); } default: - net_printf(&thd->net, ER_VAR_CANT_BE_READ, name); + net_printf(thd, ER_VAR_CANT_BE_READ, name); } return 0; } @@ -918,7 +942,7 @@ bool sys_var_thd_conv_charset::check(THD *thd, set_var *var) { CONVERT *tmp; char buff[80]; - String str(buff,sizeof(buff)), *res; + String str(buff,sizeof(buff), system_charset_info), *res; if (!var->value) // Default value { @@ -1100,6 +1124,21 @@ static bool set_log_update(THD *thd, set_var *var) return 0; } +static byte *get_warning_count(THD *thd) +{ + thd->sys_var_tmp.long_value= + (thd->warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_NOTE] + + thd->warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_WARN]); + return (byte*) &thd->sys_var_tmp.long_value; +} + +static byte *get_error_count(THD *thd) +{ + thd->sys_var_tmp.long_value= + thd->warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_ERROR]; + return (byte*) &thd->sys_var_tmp.long_value; +} + /**************************************************************************** Main handling of variables: @@ -1161,7 +1200,8 @@ void set_var_init() { extern struct my_option my_long_options[]; // From mysqld - hash_init(&system_variable_hash,array_elements(sys_variables),0,0, + hash_init(&system_variable_hash, system_charset_info, + array_elements(sys_variables),0,0, (hash_get_key) get_sys_var_length,0, HASH_CASE_INSENSITIVE); sys_var **var, **end; for (var= sys_variables, end= sys_variables+array_elements(sys_variables) ; @@ -1212,7 +1252,7 @@ sys_var *find_sys_var(const char *str, uint length) length ? length : strlen(str)); if (!var) - net_printf(¤t_thd->net, ER_UNKNOWN_SYSTEM_VARIABLE, (char*) str); + net_printf(current_thd, ER_UNKNOWN_SYSTEM_VARIABLE, (char*) str); return var; } @@ -1286,7 +1326,7 @@ bool set_var::check(THD *thd) return 0; } - if (value->fix_fields(thd,0)) + if (value->fix_fields(thd, 0, &value)) return 1; if (var->check_update_type(value->result_type())) { @@ -1315,7 +1355,7 @@ bool set_var::update(THD *thd) bool set_var_user::check(THD *thd) { - return user_var_item->fix_fields(thd,0); + return user_var_item->fix_fields(thd,0, (Item**) 0); } @@ -1324,7 +1364,7 @@ bool set_var_user::update(THD *thd) if (user_var_item->update()) { /* Give an error if it's not given already */ - send_error(&thd->net, ER_SET_CONSTANTS_ONLY); + send_error(thd, ER_SET_CONSTANTS_ONLY); return 1; } return 0; diff --git a/sql/set_var.h b/sql/set_var.h index cbe479b7902..2c40414f591 100644 --- a/sql/set_var.h +++ b/sql/set_var.h @@ -39,6 +39,7 @@ typedef bool (*sys_check_func)(THD *, set_var *); typedef bool (*sys_update_func)(THD *, set_var *); typedef void (*sys_after_update_func)(THD *,enum_var_type); typedef void (*sys_set_default_func)(THD *, enum_var_type); +typedef byte *(*sys_value_ptr_func)(THD *thd); class sys_var { @@ -350,6 +351,31 @@ public: }; +/* Variable that you can only read from */ + +class sys_var_readonly: public sys_var +{ +public: + enum_var_type var_type; + SHOW_TYPE show_type; + sys_value_ptr_func value_ptr_func; + sys_var_readonly(const char *name_arg, enum_var_type type, + SHOW_TYPE show_type_arg, + sys_value_ptr_func value_ptr_func_arg) + :sys_var(name_arg), var_type(type), + show_type(show_type_arg), value_ptr_func(value_ptr_func_arg) + {} + bool update(THD *thd, set_var *var) { return 1; } + bool check_default(enum_var_type type) { return 1; } + bool check_type(enum_var_type type) { return type != var_type; } + bool check_update_type(Item_result type) { return 1; } + byte *value_ptr(THD *thd, enum_var_type type) + { + return (*value_ptr_func)(thd); + } + SHOW_TYPE type() { return show_type; } +}; + /**************************************************************************** Classes for parsing of the SET command ****************************************************************************/ @@ -388,7 +414,8 @@ public: if (value_arg && value_arg->type() == Item::FIELD_ITEM) { Item_field *item= (Item_field*) value_arg; - if (!(value=new Item_string(item->field_name, strlen(item->field_name)))) + if (!(value=new Item_string(item->field_name, strlen(item->field_name), + system_charset_info))) value=value_arg; /* Give error message later */ } else diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt index e9f3b997a96..17651303714 100644 --- a/sql/share/czech/errmsg.txt +++ b/sql/share/czech/errmsg.txt @@ -206,7 +206,7 @@ "Nezn-Bámá systémová promìnná '%-.64s'", "Tabulka '%-.64s' je ozna-Bèena jako poru¹ená a mìla by být opravena", "Tabulka '%-.64s' je ozna-Bèena jako poru¹ená a poslední (automatická?) oprava se nezdaøila", -"Warning: Some non-transactional changed tables couldn't be rolled back", +"Some non-transactional changed tables couldn't be rolled back", "Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage. Increase this mysqld variable and try again', "This operation cannot be performed with a running slave, run SLAVE STOP first", "This operation requires a running slave, configure slave and do SLAVE START", diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt index 88ab604fbcf..ccb452f0cca 100644 --- a/sql/share/english/errmsg.txt +++ b/sql/share/english/errmsg.txt @@ -197,7 +197,7 @@ "Unknown system variable '%-.64s'", "Table '%-.64s' is marked as crashed and should be repaired", "Table '%-.64s' is marked as crashed and last (automatic?) repair failed", -"Warning: Some non-transactional changed tables couldn't be rolled back", +"Some non-transactional changed tables couldn't be rolled back", "Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage. Increase this mysqld variable and try again', "This operation cannot be performed with a running slave, run SLAVE STOP first", "This operation requires a running slave, configure slave and do SLAVE START", @@ -242,3 +242,4 @@ "Key reference and table reference doesn't match", "Subselect return more than 1 field", "Subselect return more than 1 record", +"Unknown prepared statement handler (%ld) given to %s", diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt index a344ed2df9e..f9117bdd44e 100644 --- a/sql/share/greek/errmsg.txt +++ b/sql/share/greek/errmsg.txt @@ -197,7 +197,7 @@ "Unknown system variable '%-.64s'", "Table '%-.64s' is marked as crashed and should be repaired", "Table '%-.64s' is marked as crashed and last (automatic?) repair failed", -"Warning: Some non-transactional changed tables couldn't be rolled back", +"Some non-transactional changed tables couldn't be rolled back", "Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage. Increase this mysqld variable and try again', "This operation cannot be performed with a running slave, run SLAVE STOP first", "This operation requires a running slave, configure slave and do SLAVE START", diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt index 9e88f2c3e2c..9bf7121d309 100644 --- a/sql/share/hungarian/errmsg.txt +++ b/sql/share/hungarian/errmsg.txt @@ -199,7 +199,7 @@ "Unknown system variable '%-.64s'", "Table '%-.64s' is marked as crashed and should be repaired", "Table '%-.64s' is marked as crashed and last (automatic?) repair failed", -"Warning: Some non-transactional changed tables couldn't be rolled back", +"Some non-transactional changed tables couldn't be rolled back", "Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage. Increase this mysqld variable and try again', "This operation cannot be performed with a running slave, run SLAVE STOP first", "This operation requires a running slave, configure slave and do SLAVE START", diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt index 07bdcd6bee5..215a30c5062 100644 --- a/sql/share/japanese/errmsg.txt +++ b/sql/share/japanese/errmsg.txt @@ -199,7 +199,7 @@ "Unknown system variable '%-.64s'", "Table '%-.64s' is marked as crashed and should be repaired", "Table '%-.64s' is marked as crashed and last (automatic?) repair failed", -"Warning: Some non-transactional changed tables couldn't be rolled back", +"Some non-transactional changed tables couldn't be rolled back", "Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage. Increase this mysqld variable and try again', "This operation cannot be performed with a running slave, run SLAVE STOP first", "This operation requires a running slave, configure slave and do SLAVE START", diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt index 57f990fdc04..0560442ddb8 100644 --- a/sql/share/korean/errmsg.txt +++ b/sql/share/korean/errmsg.txt @@ -197,7 +197,7 @@ "Unknown system variable '%-.64s'", "Table '%-.64s' is marked as crashed and should be repaired", "Table '%-.64s' is marked as crashed and last (automatic?) repair failed", -"Warning: Some non-transactional changed tables couldn't be rolled back", +"Some non-transactional changed tables couldn't be rolled back", "Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage. Increase this mysqld variable and try again', "This operation cannot be performed with a running slave, run SLAVE STOP first", "This operation requires a running slave, configure slave and do SLAVE START", diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt index 37f7f2fac01..bc9f9829945 100644 --- a/sql/share/norwegian-ny/errmsg.txt +++ b/sql/share/norwegian-ny/errmsg.txt @@ -199,7 +199,7 @@ "Unknown system variable '%-.64s'", "Table '%-.64s' is marked as crashed and should be repaired", "Table '%-.64s' is marked as crashed and last (automatic?) repair failed", -"Warning: Some non-transactional changed tables couldn't be rolled back", +"Some non-transactional changed tables couldn't be rolled back", "Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage. Increase this mysqld variable and try again', "This operation cannot be performed with a running slave, run SLAVE STOP first", "This operation requires a running slave, configure slave and do SLAVE START", diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt index 93f4090d697..2af2e7809b0 100644 --- a/sql/share/norwegian/errmsg.txt +++ b/sql/share/norwegian/errmsg.txt @@ -199,7 +199,7 @@ "Unknown system variable '%-.64s'", "Table '%-.64s' is marked as crashed and should be repaired", "Table '%-.64s' is marked as crashed and last (automatic?) repair failed", -"Warning: Some non-transactional changed tables couldn't be rolled back", +"Some non-transactional changed tables couldn't be rolled back", "Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage. Increase this mysqld variable and try again', "This operation cannot be performed with a running slave, run SLAVE STOP first", "This operation requires a running slave, configure slave and do SLAVE START", diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt index 3b43ce539c7..93578e6119d 100644 --- a/sql/share/polish/errmsg.txt +++ b/sql/share/polish/errmsg.txt @@ -201,7 +201,7 @@ "Unknown system variable '%-.64s'", "Table '%-.64s' is marked as crashed and should be repaired", "Table '%-.64s' is marked as crashed and last (automatic?) repair failed", -"Warning: Some non-transactional changed tables couldn't be rolled back", +"Some non-transactional changed tables couldn't be rolled back", "Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage. Increase this mysqld variable and try again', "This operation cannot be performed with a running slave, run SLAVE STOP first", "This operation requires a running slave, configure slave and do SLAVE START", diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt index ce237d755d4..cde6ab9a4f4 100644 --- a/sql/share/romanian/errmsg.txt +++ b/sql/share/romanian/errmsg.txt @@ -201,7 +201,7 @@ "Unknown system variable '%-.64s'", "Table '%-.64s' is marked as crashed and should be repaired", "Table '%-.64s' is marked as crashed and last (automatic?) repair failed", -"Warning: Some non-transactional changed tables couldn't be rolled back", +"Some non-transactional changed tables couldn't be rolled back", "Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage. Increase this mysqld variable and try again', "This operation cannot be performed with a running slave, run SLAVE STOP first", "This operation requires a running slave, configure slave and do SLAVE START", diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt index 9912e4c9191..4c5cf834262 100644 --- a/sql/share/slovak/errmsg.txt +++ b/sql/share/slovak/errmsg.txt @@ -205,7 +205,7 @@ "Unknown system variable '%-.64s'", "Table '%-.64s' is marked as crashed and should be repaired", "Table '%-.64s' is marked as crashed and last (automatic?) repair failed", -"Warning: Some non-transactional changed tables couldn't be rolled back", +"Some non-transactional changed tables couldn't be rolled back", "Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage. Increase this mysqld variable and try again', "This operation cannot be performed with a running slave, run SLAVE STOP first", "This operation requires a running slave, configure slave and do SLAVE START", diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt index f6553f247b6..587c9cab406 100644 --- a/sql/share/swedish/errmsg.txt +++ b/sql/share/swedish/errmsg.txt @@ -197,7 +197,7 @@ "Okänd system variabel '%-.64s'", "Tabell '%-.64s' är crashad och bör repareras med REPAIR TABLE", "Tabell '%-.64s' är crashad och senast (automatiska?) reparation misslyckades", -"Warning: Några icke transaktionella tabeller kunde inte återställas vid ROLLBACK", +"Några icke transaktionella tabeller kunde inte återställas vid ROLLBACK", "Transaktionen krävde mera än 'max_binlog_cache_size' minne. Utöka denna mysqld variabel och försök på nytt", "Denna operation kan inte göras under replikering; Gör SLAVE STOP först", "Denna operation kan endast göras under replikering; Konfigurera slaven och gör SLAVE START", diff --git a/sql/slave.cc b/sql/slave.cc index 01f6233a2e0..71dbb1fc1a2 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -56,7 +56,6 @@ static int events_till_disconnect = -1; typedef enum { SLAVE_THD_IO, SLAVE_THD_SQL} SLAVE_THD_TYPE; -void skip_load_data_infile(NET* net); static int process_io_rotate(MASTER_INFO* mi, Rotate_log_event* rev); static int process_io_create_file(MASTER_INFO* mi, Create_file_log_event* cev); static bool wait_for_relay_log_space(RELAY_LOG_INFO* rli); @@ -723,13 +722,22 @@ void slave_print_error(RELAY_LOG_INFO* rli, int err_code, const char* msg, ...) rli->last_slave_errno = err_code; } +/* + This is used to tell a 3.23 master to break send_file() +*/ + +void skip_load_data_infile(NET *net) +{ + (void)net_request_file(net, "/dev/null"); + (void)my_net_read(net); // discard response + (void)net_write_command(net, 0, "", 0, "", 0); // Send ok +} + -void skip_load_data_infile(NET* net) +bool net_request_file(NET* net, const char* fname) { - (void)my_net_write(net, "\xfb/dev/null", 10); - (void)net_flush(net); - (void)my_net_read(net); // discard response - send_ok(net); // the master expects it + DBUG_ENTER("net_request_file"); + DBUG_RETURN(net_write_command(net, 251, fname, strlen(fname), "", 0)); } @@ -875,13 +883,13 @@ static int create_table_from_dump(THD* thd, NET* net, const char* db, if (packet_len == packet_error) { - send_error(&thd->net, ER_MASTER_NET_READ); + send_error(thd, ER_MASTER_NET_READ); return 1; } if (net->read_pos[0] == 255) // error from master { net->read_pos[packet_len] = 0; - net_printf(&thd->net, ER_MASTER, net->read_pos + 3); + net_printf(thd, ER_MASTER, net->read_pos + 3); return 1; } thd->command = COM_TABLE_DUMP; @@ -889,7 +897,7 @@ static int create_table_from_dump(THD* thd, NET* net, const char* db, if (!thd->query) { sql_print_error("create_table_from_dump: out of memory"); - net_printf(&thd->net, ER_GET_ERRNO, "Out of memory"); + net_printf(thd, ER_GET_ERRNO, "Out of memory"); return 1; } memcpy(thd->query, net->read_pos, packet_len); @@ -919,7 +927,7 @@ static int create_table_from_dump(THD* thd, NET* net, const char* db, thd->proc_info = "Opening master dump table"; if (!open_ltable(thd, &tables, TL_WRITE)) { - send_error(&thd->net,0,0); // Send error from open_ltable + send_error(thd,0,0); // Send error from open_ltable sql_print_error("create_table_from_dump: could not open created table"); goto err; } @@ -928,7 +936,7 @@ static int create_table_from_dump(THD* thd, NET* net, const char* db, thd->proc_info = "Reading master dump table data"; if (file->net_read_dump(net)) { - net_printf(&thd->net, ER_MASTER_NET_READ); + net_printf(thd, ER_MASTER_NET_READ); sql_print_error("create_table_from_dump::failed in\ handler::net_read_dump()"); goto err; @@ -947,7 +955,7 @@ static int create_table_from_dump(THD* thd, NET* net, const char* db, error=file->repair(thd,&check_opt) != 0; thd->net.vio = save_vio; if (error) - net_printf(&thd->net, ER_INDEX_REBUILD,tables.table->real_name); + net_printf(thd, ER_INDEX_REBUILD,tables.table->real_name); err: close_thread_tables(thd); @@ -969,12 +977,12 @@ int fetch_master_table(THD *thd, const char *db_name, const char *table_name, { if (!(mysql = mc_mysql_init(NULL))) { - send_error(&thd->net); // EOM + send_error(thd); // EOM DBUG_RETURN(1); } if (connect_to_master(thd, mysql, mi)) { - net_printf(&thd->net, ER_CONNECT_TO_MASTER, mc_mysql_error(mysql)); + net_printf(thd, ER_CONNECT_TO_MASTER, mc_mysql_error(mysql)); mc_mysql_close(mysql); DBUG_RETURN(1); } @@ -998,7 +1006,7 @@ int fetch_master_table(THD *thd, const char *db_name, const char *table_name, if (!called_connected) mc_mysql_close(mysql); if (errmsg && thd->net.vio) - send_error(&thd->net, error, errmsg); + send_error(thd, error, errmsg); DBUG_RETURN(test(error)); // Return 1 on error } @@ -1440,7 +1448,7 @@ int show_master_info(THD* thd, MASTER_INFO* mi) if (my_net_write(&thd->net, (char*)thd->packet.ptr(), packet->length())) DBUG_RETURN(-1); } - send_eof(&thd->net); + send_eof(thd); DBUG_RETURN(0); } @@ -2222,8 +2230,8 @@ static int process_io_create_file(MASTER_INFO* mi, Create_file_log_event* cev) int error = 1; ulong num_bytes; bool cev_not_written; - THD* thd; - NET* net = &mi->mysql->net; + THD *thd = mi->io_thd; + NET *net = &mi->mysql->net; DBUG_ENTER("process_io_create_file"); if (unlikely(!cev->is_valid())) @@ -2237,7 +2245,6 @@ static int process_io_create_file(MASTER_INFO* mi, Create_file_log_event* cev) DBUG_RETURN(0); } DBUG_ASSERT(cev->inited_from_old); - thd = mi->io_thd; thd->file_id = cev->file_id = mi->file_id++; thd->server_id = cev->server_id; cev_not_written = 1; @@ -2266,7 +2273,7 @@ static int process_io_create_file(MASTER_INFO* mi, Create_file_log_event* cev) } if (unlikely(!num_bytes)) /* eof */ { - send_ok(net); /* 3.23 master wants it */ + net_write_command(net, 0, "", 0, "", 0);/* 3.23 master wants it */ Execute_load_log_event xev(thd); xev.log_pos = mi->master_log_pos; if (unlikely(mi->rli.relay_log.append(&xev))) diff --git a/sql/spatial.h b/sql/spatial.h index c6e30a44fbf..3f09e86e823 100644 --- a/sql/spatial.h +++ b/sql/spatial.h @@ -1,8 +1,22 @@ +/* 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 */ + #ifndef _spatial_h #define _spatial_h -#include "gstream.h" - const uint POINT_DATA_SIZE = 8+8; const uint WKB_HEADER_SIZE = 1+4; @@ -30,7 +44,8 @@ struct MBR ymax=-DBL_MAX; } - MBR(const double &_xmin, const double &_ymin, const double &_xmax, const double &_ymax) + MBR(const double &_xmin, const double &_ymin, + const double &_xmax, const double &_ymax) { xmin=_xmin; ymin=_ymin; @@ -52,7 +67,8 @@ struct MBR double ymax; void add_xy(double x, double y) - { /* Not using "else" for proper one point MBR calculation */ + { + /* Not using "else" for proper one point MBR calculation */ if (x<xmin) { xmin=x; @@ -72,10 +88,11 @@ struct MBR } void add_xy(const char *px, const char *py) - { /* Not using "else" for proper one point MBR calculation */ + { double x, y; float8get(x, px); float8get(y, py); + /* Not using "else" for proper one point MBR calculation */ if (x<xmin) { xmin=x; @@ -116,12 +133,14 @@ struct MBR int equals(const MBR *mbr) { - return (mbr->xmin==xmin)&&(mbr->ymin==ymin)&&(mbr->xmax==xmax)&&(mbr->ymax==ymax); + return ((mbr->xmin == xmin) && (mbr->ymin == ymin) && + (mbr->xmax == xmax) && (mbr->ymax == ymax)); } int disjoint(const MBR *mbr) { - return (mbr->xmin>xmax)||(mbr->ymin>ymax)||(mbr->xmax<xmin)||(mbr->ymax<ymin); + return ((mbr->xmin > xmax) || (mbr->ymin > ymax) || + (mbr->xmax < xmin) || (mbr->ymax < ymin)); } int intersects(const MBR *mbr) @@ -131,24 +150,24 @@ struct MBR int touches(const MBR *mbr) { - return (((mbr->xmin==xmax) || (mbr->xmax==xmin)) && - ((mbr->ymin>=ymin) && (mbr->ymin<=ymax) || - (mbr->ymax>=ymin) && (mbr->ymax<=ymax))) || - (((mbr->ymin==ymax) || (mbr->ymax==ymin)) && - ((mbr->xmin>=xmin) && (mbr->xmin<=xmax) || - (mbr->xmax>=xmin)&&(mbr->xmax<=xmax))); + return ((((mbr->xmin == xmax) || (mbr->xmax == xmin)) && + ((mbr->ymin >= ymin) && (mbr->ymin <= ymax) || + (mbr->ymax >= ymin) && (mbr->ymax <= ymax))) || + (((mbr->ymin == ymax) || (mbr->ymax == ymin)) && + ((mbr->xmin >= xmin) && (mbr->xmin <= xmax) || + (mbr->xmax >= xmin) && (mbr->xmax <= xmax)))); } int within(const MBR *mbr) { - return (mbr->xmin<=xmin) && (mbr->ymin<=ymin) && - (mbr->xmax>=xmax) && (mbr->ymax>=ymax); + return ((mbr->xmin <= xmin) && (mbr->ymin <= ymin) && + (mbr->xmax >= xmax) && (mbr->ymax >= ymax)); } int contains(const MBR *mbr) { - return (mbr->xmin>=xmin) && (mbr->ymin>=ymin) && - (mbr->xmax<=xmax) && (mbr->ymax<=ymax); + return ((mbr->xmin >= xmin) && (mbr->ymin >= ymin) && + (mbr->xmax <= xmax) && (mbr->ymax <= ymax)); } bool inner_point(double x, double y) const @@ -245,45 +264,46 @@ public: size_t get_data_size() const { return (this->*m_vmt->get_data_size)(); } int init_from_text(GTextReadStream *trs, String *wkb) - { return (this->*m_vmt->init_from_text)(trs, wkb); } + { return (this->*m_vmt->init_from_text)(trs, wkb); } int get_data_as_text(String *txt) const - { return (this->*m_vmt->get_data_as_text)(txt); } + { return (this->*m_vmt->get_data_as_text)(txt); } int get_mbr(MBR *mbr) const { return (this->*m_vmt->get_mbr)(mbr); } int dimension(uint32 *dim) const - { return (this->*m_vmt->dimension)(dim); } + { return (this->*m_vmt->dimension)(dim); } int get_x(double *x) const { return (this->*m_vmt->get_x)(x); } int get_y(double *y) const { return (this->*m_vmt->get_y)(y); } int length(double *len) const { return (this->*m_vmt->length)(len); } int area(double *ar) const { return (this->*m_vmt->area)(ar); } - int is_closed(int *closed) const { return (this->*m_vmt->is_closed)(closed); } + int is_closed(int *closed) const + { return (this->*m_vmt->is_closed)(closed); } int num_interior_ring(uint32 *n_int_rings) const - { return (this->*m_vmt->num_interior_ring)(n_int_rings); } + { return (this->*m_vmt->num_interior_ring)(n_int_rings); } int num_points(uint32 *n_points) const - { return (this->*m_vmt->num_points)(n_points); } + { return (this->*m_vmt->num_points)(n_points); } int num_geometries(uint32 *num) const - { return (this->*m_vmt->num_geometries)(num); } + { return (this->*m_vmt->num_geometries)(num); } int start_point(String *point) const - { return (this->*m_vmt->start_point)(point); } + { return (this->*m_vmt->start_point)(point); } int end_point(String *point) const - { return (this->*m_vmt->end_point)(point); } + { return (this->*m_vmt->end_point)(point); } int exterior_ring(String *ring) const - { return (this->*m_vmt->exterior_ring)(ring); } + { return (this->*m_vmt->exterior_ring)(ring); } int centroid(String *point) const - { return (this->*m_vmt->centroid)(point); } + { return (this->*m_vmt->centroid)(point); } int point_n(uint32 num, String *result) const - { return (this->*m_vmt->point_n)(num, result); } + { return (this->*m_vmt->point_n)(num, result); } int interior_ring_n(uint32 num, String *result) const - { return (this->*m_vmt->interior_ring_n)(num, result); } + { return (this->*m_vmt->interior_ring_n)(num, result); } int geometry_n(uint32 num, String *result) const - { return (this->*m_vmt->geometry_n)(num, result); } + { return (this->*m_vmt->geometry_n)(num, result); } public: int create_from_wkb(const char *data, uint32 data_len); @@ -301,11 +321,11 @@ public: int as_wkt(String *wkt) const { - if(wkt->reserve(strlen(get_class_info()->m_name) + 2, 512)) + if (wkt->reserve(strlen(get_class_info()->m_name) + 2, 512)) return 1; wkt->qs_append(get_class_info()->m_name); wkt->qs_append('('); - if(get_data_as_text(wkt)) + if (get_data_as_text(wkt)) return 1; wkt->qs_append(')'); return 0; @@ -330,35 +350,37 @@ protected: bool no_data(const char *cur_data, uint32 data_amount) const { - return cur_data + data_amount > m_data_end; + return (cur_data + data_amount > m_data_end); } const char *m_data; const char *m_data_end; }; +#define SIZEOF_STORED_DOUBLE 8 + /***************************** Point *******************************/ class GPoint: public Geometry { public: - size_t get_data_size() const; - int init_from_text(GTextReadStream *trs, String *wkb); - int get_data_as_text(String *txt) const; - int get_mbr(MBR *mbr) const; + size_t get_data_size() const; + int init_from_text(GTextReadStream *trs, String *wkb); + int get_data_as_text(String *txt) const; + int get_mbr(MBR *mbr) const; int get_xy(double *x, double *y) const { const char *data = m_data; - if(no_data(data, sizeof(double)) * 2) return 1; + if (no_data(data, SIZEOF_STORED_DOUBLE * 2)) return 1; float8get(*x, data); - float8get(*y, data + sizeof(double)); + float8get(*y, data + SIZEOF_STORED_DOUBLE); return 0; } int get_x(double *x) const { - if(no_data(m_data, sizeof(double))) return 1; + if (no_data(m_data, SIZEOF_STORED_DOUBLE)) return 1; float8get(*x, m_data); return 0; } @@ -366,8 +388,8 @@ public: int get_y(double *y) const { const char *data = m_data; - if(no_data(data, sizeof(double)) * 2) return 1; - float8get(*y, data + sizeof(double)); + if (no_data(data, SIZEOF_STORED_DOUBLE * 2)) return 1; + float8get(*y, data + SIZEOF_STORED_DOUBLE); return 0; } @@ -399,11 +421,11 @@ public: class GPolygon: public Geometry { public: - size_t get_data_size() const; - int init_from_text(GTextReadStream *trs, String *wkb); - int get_data_as_text(String *txt) const; - int get_mbr(MBR *mbr) const; - + size_t get_data_size() const; + int init_from_text(GTextReadStream *trs, String *wkb); + int get_data_as_text(String *txt) const; + int get_mbr(MBR *mbr) const; + int area(double *ar) const; int exterior_ring(String *result) const; int num_interior_ring(uint32 *n_int_rings) const; @@ -431,11 +453,11 @@ public: class GMultiLineString: public Geometry { public: - size_t get_data_size() const; - int init_from_text(GTextReadStream *trs, String *wkb); - int get_data_as_text(String *txt) const; - int get_mbr(MBR *mbr) const; - + size_t get_data_size() const; + int init_from_text(GTextReadStream *trs, String *wkb); + int get_data_as_text(String *txt) const; + int get_mbr(MBR *mbr) const; + int length(double *len) const; int is_closed(int *closed) const; int dimension(uint32 *dim) const { *dim = 1; return 0; } @@ -446,10 +468,10 @@ public: class GMultiPolygon: public Geometry { public: - size_t get_data_size() const; - int init_from_text(GTextReadStream *trs, String *wkb); - int get_data_as_text(String *txt) const; - int get_mbr(MBR *mbr) const; + size_t get_data_size() const; + int init_from_text(GTextReadStream *trs, String *wkb); + int get_data_as_text(String *txt) const; + int get_mbr(MBR *mbr) const; int area(double *ar) const; int centroid(String *result) const; @@ -462,14 +484,13 @@ public: class GGeometryCollection: public Geometry { public: - size_t get_data_size() const; - int init_from_text(GTextReadStream *trs, String *wkb); - int get_data_as_text(String *txt) const; - int get_mbr(MBR *mbr) const; + size_t get_data_size() const; + int init_from_text(GTextReadStream *trs, String *wkb); + int get_data_as_text(String *txt) const; + int get_mbr(MBR *mbr) const; int num_geometries(uint32 *num) const; int geometry_n(uint32 num, String *result) const; - int dimension(uint32 *dim) const; }; diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 1069e779e86..e6b9a1f532b 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -997,7 +997,7 @@ bool check_change_password(THD *thd, const char *host, const char *user) { if (!initialized) { - send_error(&thd->net, ER_PASSWORD_NOT_ALLOWED); /* purecov: inspected */ + send_error(thd, ER_PASSWORD_NOT_ALLOWED); /* purecov: inspected */ return(1); /* purecov: inspected */ } if (!thd->slave_thread && @@ -1009,7 +1009,7 @@ bool check_change_password(THD *thd, const char *host, const char *user) } if (!thd->slave_thread && !thd->user[0]) { - send_error(&thd->net, ER_PASSWORD_ANONYMOUS_USER); + send_error(thd, ER_PASSWORD_ANONYMOUS_USER); return(1); } return(0); @@ -1036,7 +1036,7 @@ bool change_password(THD *thd, const char *host, const char *user, ACL_USER *acl_user; if (!(acl_user= find_acl_user(host,user))) { - send_error(&thd->net, ER_PASSWORD_NO_MATCH); + send_error(thd, ER_PASSWORD_NO_MATCH); VOID(pthread_mutex_unlock(&acl_cache->lock)); DBUG_RETURN(1); } @@ -1046,7 +1046,7 @@ bool change_password(THD *thd, const char *host, const char *user, new_password)) { VOID(pthread_mutex_unlock(&acl_cache->lock)); /* purecov: deadcode */ - send_error(&thd->net,0); /* purecov: deadcode */ + send_error(thd,0); /* purecov: deadcode */ DBUG_RETURN(1); /* purecov: deadcode */ } get_salt_from_password(acl_user->salt,new_password); @@ -1960,7 +1960,7 @@ int mysql_table_grant (THD *thd, TABLE_LIST *table_list, if (!initialized) { - send_error(&(thd->net), ER_UNKNOWN_COM_ERROR); /* purecov: inspected */ + send_error(thd, ER_UNKNOWN_COM_ERROR); /* purecov: inspected */ return 1; /* purecov: inspected */ } if (rights & ~TABLE_ACLS) @@ -2026,7 +2026,7 @@ int mysql_table_grant (THD *thd, TABLE_LIST *table_list, if (!revoke_grant) create_new_users= test_if_create_new_users(thd); int result=0; - pthread_mutex_lock(&LOCK_grant); + rw_wrlock(&LOCK_grant); MEM_ROOT *old_root=my_pthread_getspecific_ptr(MEM_ROOT*,THR_MALLOC); my_pthread_setspecific_ptr(THR_MALLOC,&memex); @@ -2135,9 +2135,9 @@ int mysql_table_grant (THD *thd, TABLE_LIST *table_list, } grant_option=TRUE; my_pthread_setspecific_ptr(THR_MALLOC,old_root); - pthread_mutex_unlock(&LOCK_grant); + rw_unlock(&LOCK_grant); if (!result) - send_ok(&thd->net); + send_ok(thd); /* Tables are automatically closed */ DBUG_RETURN(result); } @@ -2155,8 +2155,8 @@ int mysql_grant (THD *thd, const char *db, List <LEX_USER> &list, if (!initialized) { - send_error(&(thd->net), ER_UNKNOWN_COM_ERROR); /* purecov: tested */ - return 1; /* purecov: tested */ + send_error(thd, ER_UNKNOWN_COM_ERROR); /* purecov: tested */ + return 1; /* purecov: tested */ } if (lower_case_table_names && db) @@ -2185,7 +2185,7 @@ int mysql_grant (THD *thd, const char *db, List <LEX_USER> &list, create_new_users= test_if_create_new_users(thd); // go through users in user_list - pthread_mutex_lock(&LOCK_grant); + rw_wrlock(&LOCK_grant); VOID(pthread_mutex_lock(&acl_cache->lock)); grant_version++; @@ -2218,11 +2218,11 @@ int mysql_grant (THD *thd, const char *db, List <LEX_USER> &list, } } VOID(pthread_mutex_unlock(&acl_cache->lock)); - pthread_mutex_unlock(&LOCK_grant); + rw_unlock(&LOCK_grant); close_thread_tables(thd); if (!result) - send_ok(&thd->net); + send_ok(thd); DBUG_RETURN(result); } @@ -2341,7 +2341,7 @@ void grant_reload(void) // Locked tables are checked by acl_init and doesn't have to be checked here - pthread_mutex_lock(&LOCK_grant); + rw_wrlock(&LOCK_grant); grant_version++; old_hash_tables=hash_tables; old_grant_option = grant_option; @@ -2359,7 +2359,7 @@ void grant_reload(void) hash_free(&old_hash_tables); free_root(&old_mem,MYF(0)); } - pthread_mutex_unlock(&LOCK_grant); + rw_unlock(&LOCK_grant); DBUG_VOID_RETURN; } @@ -2379,7 +2379,7 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables, if (!want_access) return 0; // ok - pthread_mutex_lock(&LOCK_grant); + rw_rdlock(&LOCK_grant); for (table=tables; table ;table=table->next) { if (!(~table->grant.privilege & want_access)) @@ -2413,11 +2413,11 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables, goto err; // impossible } } - pthread_mutex_unlock(&LOCK_grant); + rw_unlock(&LOCK_grant); return 0; err: - pthread_mutex_unlock(&LOCK_grant); + rw_unlock(&LOCK_grant); if (!no_errors) // Not a silent skip of table { const char *command=""; @@ -2439,7 +2439,7 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables, command = "index"; else if (want_access & GRANT_ACL) command = "grant"; - net_printf(&thd->net,ER_TABLEACCESS_DENIED_ERROR, + net_printf(thd,ER_TABLEACCESS_DENIED_ERROR, command, thd->priv_user, thd->host_or_ip, @@ -2459,7 +2459,7 @@ bool check_grant_column (THD *thd,TABLE *table, const char *name, if (!want_access) return 0; // Already checked - pthread_mutex_lock(&LOCK_grant); + rw_rdlock(&LOCK_grant); // reload table if someone has modified any grants @@ -2477,20 +2477,20 @@ bool check_grant_column (THD *thd,TABLE *table, const char *name, grant_column=column_hash_search(grant_table, name, length); if (grant_column && !(~grant_column->rights & want_access)) { - pthread_mutex_unlock(&LOCK_grant); + rw_unlock(&LOCK_grant); return 0; } #ifdef NOT_USED if (show_tables && (grant_column || table->grant.privilege & COL_ACLS)) { - pthread_mutex_unlock(&LOCK_grant); /* purecov: deadcode */ + rw_unlock(&LOCK_grant); /* purecov: deadcode */ return 0; /* purecov: deadcode */ } #endif /* We must use my_printf_error() here! */ err: - pthread_mutex_unlock(&LOCK_grant); + rw_unlock(&LOCK_grant); if (!show_tables) { char command[128]; @@ -2518,7 +2518,7 @@ bool check_grant_all_columns(THD *thd, ulong want_access, TABLE *table) if (!want_access) return 0; // Already checked - pthread_mutex_lock(&LOCK_grant); + rw_rdlock(&LOCK_grant); // reload table if someone has modified any grants @@ -2541,12 +2541,12 @@ bool check_grant_all_columns(THD *thd, ulong want_access, TABLE *table) if (!grant_column || (~grant_column->rights & want_access)) goto err; } - pthread_mutex_unlock(&LOCK_grant); + rw_unlock(&LOCK_grant); return 0; /* We must use my_printf_error() here! */ err: - pthread_mutex_unlock(&LOCK_grant); + rw_unlock(&LOCK_grant); const char *command=""; if (want_access & SELECT_ACL) @@ -2578,7 +2578,7 @@ bool check_grant_db(THD *thd,const char *db) bool error=1; len = (uint) (strmov(strmov(helping,thd->priv_user)+1,db)-helping)+ 1; - pthread_mutex_lock(&LOCK_grant); + rw_rdlock(&LOCK_grant); for (uint idx=0 ; idx < hash_tables.records ; idx++) { @@ -2594,7 +2594,7 @@ bool check_grant_db(THD *thd,const char *db) break; } } - pthread_mutex_unlock(&LOCK_grant); + rw_unlock(&LOCK_grant); return error; } @@ -2608,14 +2608,14 @@ ulong get_table_grant(THD *thd, TABLE_LIST *table) const char *db = table->db ? table->db : thd->db; GRANT_TABLE *grant_table; - pthread_mutex_lock(&LOCK_grant); + rw_rdlock(&LOCK_grant); grant_table = table_hash_search(thd->host,thd->ip,db,user, table->real_name,0); table->grant.grant_table=grant_table; // Remember for column test table->grant.version=grant_version; if (grant_table) table->grant.privilege|= grant_table->privs; - pthread_mutex_unlock(&LOCK_grant); + rw_unlock(&LOCK_grant); return table->grant.privilege; } @@ -2626,7 +2626,7 @@ ulong get_column_grant(THD *thd, TABLE_LIST *table, Field *field) GRANT_COLUMN *grant_column; ulong priv; - pthread_mutex_lock(&LOCK_grant); + rw_rdlock(&LOCK_grant); // reload table if someone has modified any grants if (table->grant.version != grant_version) { @@ -2648,7 +2648,7 @@ ulong get_column_grant(THD *thd, TABLE_LIST *table, Field *field) else priv=table->grant.privilege | grant_column->rights; } - pthread_mutex_unlock(&LOCK_grant); + rw_unlock(&LOCK_grant); return priv; } @@ -2683,7 +2683,7 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user) LINT_INIT(acl_user); if (!initialized) { - send_error(&(thd->net), ER_UNKNOWN_COM_ERROR); + send_error(thd, ER_UNKNOWN_COM_ERROR); DBUG_RETURN(-1); } if (!lex_user->host.str) @@ -2990,7 +2990,7 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user) } end: VOID(pthread_mutex_unlock(&acl_cache->lock)); - send_eof(&thd->net); + send_eof(thd); DBUG_RETURN(error); } diff --git a/sql/sql_analyse.cc b/sql/sql_analyse.cc index 91d6b967929..363a194276b 100644 --- a/sql/sql_analyse.cc +++ b/sql/sql_analyse.cc @@ -89,21 +89,21 @@ proc_analyse_init(THD *thd, ORDER *param, select_result *result, if ((*param->item)->type() != Item::INT_ITEM || (*param->item)->val() < 0) { - net_printf(&thd->net, ER_WRONG_PARAMETERS_TO_PROCEDURE, proc_name); + net_printf(thd, ER_WRONG_PARAMETERS_TO_PROCEDURE, proc_name); DBUG_RETURN(0); } pc->max_tree_elements = (uint) (*param->item)->val_int(); param = param->next; if (param->next) // no third parameter possible { - net_printf(&thd->net, ER_WRONG_PARAMCOUNT_TO_PROCEDURE, proc_name); + net_printf(thd, ER_WRONG_PARAMCOUNT_TO_PROCEDURE, proc_name); DBUG_RETURN(0); } // second parameter if ((*param->item)->type() != Item::INT_ITEM || (*param->item)->val() < 0) { - net_printf(&thd->net, ER_WRONG_PARAMETERS_TO_PROCEDURE, proc_name); + net_printf(thd, ER_WRONG_PARAMETERS_TO_PROCEDURE, proc_name); DBUG_RETURN(0); } pc->max_treemem = (uint) (*param->item)->val_int(); @@ -111,7 +111,7 @@ proc_analyse_init(THD *thd, ORDER *param, select_result *result, else if ((*param->item)->type() != Item::INT_ITEM || (*param->item)->val() < 0) { - net_printf(&thd->net, ER_WRONG_PARAMETERS_TO_PROCEDURE, proc_name); + net_printf(thd, ER_WRONG_PARAMETERS_TO_PROCEDURE, proc_name); DBUG_RETURN(0); } // if only one parameter was given, it will be the value of max_tree_elements @@ -387,8 +387,7 @@ void field_real::add() if ((decs = decimals()) == NOT_FIXED_DEC) { - sprintf(buff, "%g", num); - length = (uint) strlen(buff); + length= my_sprintf(buff, (buff, "%g", num)); if (rint(num) != num) max_notzero_dec_len = 1; } @@ -397,11 +396,11 @@ void field_real::add() #ifdef HAVE_SNPRINTF buff[sizeof(buff)-1]=0; // Safety snprintf(buff, sizeof(buff)-1, "%-.*f", (int) decs, num); + length = (uint) strlen(buff); #else - sprintf(buff, "%-.*f", (int) decs, num); + length= my_sprintf(buff, (buff, "%-.*f", (int) decs, num)); #endif - length = (uint) strlen(buff); // We never need to check further than this end = buff + length - 1 - decs + max_notzero_dec_len; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index a8115c15412..3175193e8ce 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -224,7 +224,7 @@ send_convert_fields(THD *thd,List<Item> &list,CONVERT *convert,uint flag) char buff[80]; String tmp((char*) buff,sizeof(buff),default_charset_info); String *res,*packet= &thd->packet; - DBUG_ENTER("send_fields"); + DBUG_ENTER("send_convert_fields"); while ((item=it++)) { @@ -286,10 +286,10 @@ send_convert_fields(THD *thd,List<Item> &list,CONVERT *convert,uint flag) if (my_net_write(&thd->net, (char*) packet->ptr(),packet->length())) break; /* purecov: inspected */ } - return 0; + DBUG_RETURN(0); err: - return 1; + DBUG_RETURN(1); } @@ -406,7 +406,8 @@ send_non_convert_fields(THD *thd,List<Item> &list,uint flag) bool send_fields(THD *thd, List<Item> &list, uint flag) { - CONVERT *convert= (flag & 4) ? (CONVERT*) 0 : thd->convert_set; + 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 @@ -414,7 +415,7 @@ send_fields(THD *thd, List<Item> &list, uint flag) if (flag & 1) { // Packet with number of elements - char *pos=net_store_length(buff,(uint) list.elements); + char *pos=net_store_length(buff, (uint) list.elements); (void) my_net_write(&thd->net, buff,(uint) (pos-buff)); } @@ -430,11 +431,11 @@ send_fields(THD *thd, List<Item> &list, uint flag) else if (send_non_convert_fields(thd, list, flag)) goto err; - send_eof(&thd->net); - return 0; + send_eof(thd); + DBUG_RETURN(0); err: - send_error(&thd->net,ER_OUT_OF_RESOURCES); /* purecov: inspected */ + send_error(thd,ER_OUT_OF_RESOURCES); /* purecov: inspected */ DBUG_RETURN(1); /* purecov: inspected */ } diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 41def4aa1b5..277492bcea6 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -77,14 +77,15 @@ static void free_var(user_var_entry *entry) ** Thread specific functions ****************************************************************************/ -THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0), +THD::THD():user_time(0), fatal_error(0), + last_insert_id_used(0), insert_id_used(0), in_lock_tables(0), global_read_lock(0), bootstrap(0) { host=user=priv_user=db=query=ip=0; host_or_ip="unknown ip"; locked=killed=count_cuted_fields=some_tables_deleted=no_errors=password= - query_start_used=safe_to_cache_query=0; + query_start_used=safe_to_cache_query=prepare_command=0; pthread_mutex_lock(&LOCK_global_system_variables); variables= global_system_variables; pthread_mutex_unlock(&LOCK_global_system_variables); @@ -96,7 +97,7 @@ THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0), tmp_table=0; lock=locked_tables=0; used_tables=0; - cuted_fields=sent_row_count=0L; + cuted_fields= sent_row_count= current_stmt_id= 0L; start_time=(time_t) 0; current_linfo = 0; slave_thread = 0; @@ -142,10 +143,21 @@ THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0), bzero((char*) &mem_root,sizeof(mem_root)); bzero((char*) &transaction.mem_root,sizeof(transaction.mem_root)); bzero((char*) &con_root,sizeof(con_root)); + bzero((char*) &warn_root,sizeof(warn_root)); + init_alloc_root(&warn_root, 1024, 0); + bzero((char*) warn_count, sizeof(warn_count)); + warn_list.empty(); user_connect=(USER_CONN *)0; hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0, (hash_get_key) get_var_key, (void (*)(void*)) free_var,0); + + /* Prepared statements */ + last_prepared_stmt= 0; + init_tree(&prepared_statements, 0, 0, sizeof(PREP_STMT), + (qsort_cmp2) compare_prep_stmt, 1, + (tree_element_free) free_prep_stmt, 0); + #ifdef USING_TRANSACTIONS bzero((char*) &transaction,sizeof(transaction)); if (opt_using_transactions) @@ -222,7 +234,9 @@ THD::~THD() safeFree(ip); free_root(&mem_root,MYF(0)); free_root(&con_root,MYF(0)); + free_root(&warn_root,MYF(0)); free_root(&transaction.mem_root,MYF(0)); + delete_tree(&prepared_statements); mysys_var=0; // Safety (shouldn't be needed) pthread_mutex_destroy(&LOCK_delete); #ifndef DBUG_OFF @@ -272,8 +286,7 @@ void THD::awake(bool prepare_to_die) bool THD::store_globals() { return (my_pthread_setspecific_ptr(THR_THD, this) || - my_pthread_setspecific_ptr(THR_MALLOC, &mem_root) || - my_pthread_setspecific_ptr(THR_NET, &net)); + my_pthread_setspecific_ptr(THR_MALLOC, &mem_root)); } @@ -424,7 +437,7 @@ bool select_send::send_eof() { mysql_unlock_tables(thd, thd->lock); thd->lock=0; } - ::send_eof(&thd->net); + ::send_eof(thd); return 0; } @@ -649,7 +662,7 @@ err: void select_export::send_error(uint errcode,const char *err) { - ::send_error(&thd->net,errcode,err); + ::send_error(thd,errcode,err); (void) end_io_cache(&cache); (void) my_close(file,MYF(0)); file= -1; @@ -662,9 +675,9 @@ bool select_export::send_eof() if (my_close(file,MYF(MY_WME))) error=1; if (error) - ::send_error(&thd->net); + ::send_error(thd); else - ::send_ok(&thd->net,row_count); + ::send_ok(thd,row_count); file= -1; return error; } @@ -761,7 +774,7 @@ err: void select_dump::send_error(uint errcode,const char *err) { - ::send_error(&thd->net,errcode,err); + ::send_error(thd,errcode,err); (void) end_io_cache(&cache); (void) my_close(file,MYF(0)); (void) my_delete(path,MYF(0)); // Delete file on error @@ -774,9 +787,9 @@ bool select_dump::send_eof() if (my_close(file,MYF(MY_WME))) error=1; if (error) - ::send_error(&thd->net); + ::send_error(thd); else - ::send_ok(&thd->net,row_count); + ::send_ok(thd,row_count); file= -1; return error; } diff --git a/sql/sql_class.h b/sql/sql_class.h index 8b2e9400613..f1eb4febf0f 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -292,31 +292,43 @@ public: i_string_pair():key(0),val(0) { } 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 + +class MYSQL_ERROR: public Sql_alloc { public: + enum enum_warning_level + { WARN_LEVEL_NOTE, WARN_LEVEL_WARN, WARN_LEVEL_ERROR, WARN_LEVEL_END}; + uint code; - char msg[MYSQL_ERRMSG_SIZE+1]; - char query[NAME_LEN+1]; + enum_warning_level level; + char *msg; - 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) + MYSQL_ERROR(uint code_arg, enum_warning_level level_arg, + const char *msg_arg) + :code(code_arg), level(level_arg) { - code = ecode; - strmov(msg, emsg); - strnmov(query, equery ? equery : "", NAME_LEN); + msg=sql_strdup(msg_arg); } }; + +/* This is a struct as it's allocated in tree_insert */ + +typedef struct st_prep_stmt +{ + THD *thd; + Item_param *param; + Item *free_list; + MEM_ROOT mem_root; + ulong stmt_id; + uint param_count; + uint last_errno; + char last_error[MYSQL_ERRMSG_SIZE]; + bool error_in_prepare, long_data_used; +} PREP_STMT; + + class delayed_insert; #define THD_SENTRY_MAGIC 0xfeedd1ff @@ -332,27 +344,27 @@ struct system_variables ulong join_buff_size; ulong long_query_time; ulong max_allowed_packet; + ulong max_error_count; ulong max_heap_table_size; - ulong max_sort_length; ulong max_join_size; + ulong max_prep_stmt_count; + ulong max_sort_length; ulong max_tmp_tables; - ulong max_error_count; - ulong max_warning_count; ulong myisam_sort_buff_size; ulong net_buffer_length; ulong net_interactive_timeout; ulong net_read_timeout; + ulong net_retry_count; ulong net_wait_timeout; ulong net_write_timeout; - ulong net_retry_count; ulong query_cache_type; ulong read_buff_size; ulong read_rnd_buff_size; ulong select_limit; ulong sortbuff_size; + ulong table_type; ulong tmp_table_size; ulong tx_isolation; - ulong table_type; my_bool log_warnings; my_bool low_priority_updates; @@ -372,7 +384,9 @@ public: LEX lex; // parse tree descriptor MEM_ROOT mem_root; // 1 command-life memory pool MEM_ROOT con_root; // connection-life memory + MEM_ROOT warn_root; // For warnings and errors HASH user_vars; // hash for user variables + TREE prepared_statements; String packet; // dynamic buffer for network I/O struct sockaddr_in remote; // client socket address struct rand_struct rand; // used for authentication @@ -408,7 +422,6 @@ public: ulong master_access; /* Global privileges from mysql.user */ ulong db_access; /* Privileges for current db */ - /* open_tables - list of regular tables in use by this thread temporary_tables - list of temp tables in use by this thread @@ -417,9 +430,10 @@ public: */ TABLE *open_tables,*temporary_tables, *handler_tables; // TODO: document the variables below - MYSQL_LOCK *lock; /* Current locks */ - MYSQL_LOCK *locked_tables; /* Tables locked with LOCK */ - ULL *ull; + MYSQL_LOCK *lock; /* Current locks */ + MYSQL_LOCK *locked_tables; /* Tables locked with LOCK */ + ULL *ull; + PREP_STMT *last_prepared_stmt; #ifndef DBUG_OFF uint dbug_sentry; // watch out for memory corruption #endif @@ -466,8 +480,11 @@ public: table_map used_tables; USER_CONN *user_connect; CHARSET_INFO *db_charset; + List <MYSQL_ERROR> warn_list; + uint warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_END]; + uint total_warn_count, old_total_warn_count; ulong query_id, version, options, thread_id, col_access; - ulong param_count,current_param_number; + ulong current_stmt_id; long dbug_thread_id; pthread_t real_id; uint current_tablenr,tmp_table,cond_count; @@ -480,16 +497,15 @@ public: uint8 query_cache_type; // type of query cache processing bool slave_thread; bool set_query_id,locked,count_cuted_fields,some_tables_deleted; - bool no_errors, allow_sum_func, password, fatal_error; + bool no_errors, allow_sum_func, password; + bool fatal_error; bool query_start_used,last_insert_id_used,insert_id_used; bool system_thread,in_lock_tables,global_read_lock; bool query_error, bootstrap, cleanup_done; bool safe_to_cache_query; bool volatile killed; bool prepare_command; - Error<mysql_st_error> err_list; - Error<mysql_st_error> warn_list; - Item_param *current_param; + Item_param *params; // Pointer to array of params /* If we do a purge of binary logs, log index info of the threads @@ -638,7 +654,7 @@ public: class JOIN; -void send_error(NET *net,uint sql_errno=0, const char *err=0); +void send_error(THD *thd, uint sql_errno=0, const char *err=0); class select_result :public Sql_alloc { protected: @@ -657,7 +673,7 @@ public: virtual void initialize_tables (JOIN *join=0) {} virtual void send_error(uint errcode,const char *err) { - ::send_error(&thd->net,errcode,err); + ::send_error(thd,errcode,err); } virtual bool send_eof()=0; virtual void abort() {} diff --git a/sql/sql_db.cc b/sql/sql_db.cc index dee26aae4be..708a016f727 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -25,112 +25,138 @@ #include <direct.h> #endif -#define MY_DB_OPT_FILE ".db.opt" +#define MY_DB_OPT_FILE "db.opt" + +const char *del_exts[]= {".frm", ".BAK", ".TMD",".opt", NullS}; +static TYPELIB deletable_extentions= +{array_elements(del_exts)-1,"del_exts", del_exts}; + +const char *known_exts[]= +{".ISM",".ISD",".ISM",".MRG",".MYI",".MYD",".db",NullS}; +static TYPELIB known_extentions= +{array_elements(known_exts)-1,"known_exts", known_exts}; static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db, const char *path, uint level); /* - Create database options file: - Currently databse default charset is only stored there. + Create database options file: + + DESCRIPTION + Currently database default charset is only stored there. + + RETURN VALUES + 0 ok + 1 Could not create file or write to it. Error sent through my_error() */ -static int write_db_opt(THD *thd,const char *db,HA_CREATE_INFO *create,char *fn) +static bool write_db_opt(const char *path, HA_CREATE_INFO *create) { register File file; - char buf[256]; // Should be enough - int error=0; + char buf[256]; // Should be enough for one option + bool error=1; - if ((file=my_create(fn,CREATE_MODE,O_RDWR | O_TRUNC,MYF(MY_WME))) >= 0) + if ((file=my_create(path, CREATE_MODE,O_RDWR | O_TRUNC,MYF(MY_WME))) >= 0) { - sprintf(buf,"default-character-set=%s\n", - (create && create->table_charset) ? - create->table_charset->name : "DEFAULT"); - - if (my_write(file,(byte*)buf,strlen(buf),MYF(MY_NABP+MY_WME))) - { - // QQ : should we send more suitable error message? - my_error(ER_CANT_CREATE_DB,MYF(0),db,my_errno); - error = -1; - goto exit; - } + ulong length; + length= my_sprintf(buf,(buf, "default-character-set=%s\n", + (create && create->table_charset) ? + create->table_charset->name : "DEFAULT")); + + /* Error is written by my_write */ + if (!my_write(file,(byte*) buf, length, MYF(MY_NABP+MY_WME))) + error=0; my_close(file,MYF(0)); } - else - { - // QQ : should we send more suitable error message? - my_error(ER_CANT_CREATE_DB,MYF(0),db,my_errno); - error = -1; - goto exit; - } exit: return error; } - /* - Load database options file: - */ -static int load_db_opt(THD *thd,const char *db,HA_CREATE_INFO *create,char *fn) -{ - register File file; - char buf[256]=""; +/* + Load database options file - if ((file=my_open(fn,O_RDWR|O_BINARY,MYF(MY_WME))) >= 0) - { - int nbytes=my_read(file,(byte*)buf,sizeof(buf)-1,MYF(0)); - if ( nbytes >= 0 ) - { - char *ln=buf; - char *pe=buf+nbytes; + load_db_opt() + path Path for option file + create Where to store the read options + + DESCRIPTION + For now, only default-character-set is read. - buf[nbytes]='\0'; + RETURN VALUES + 0 File found + 1 No database file or could not open it - for ( ln=buf; ln<pe; ) +*/ + +static bool load_db_opt(const char *path, HA_CREATE_INFO *create) +{ + File file; + char buf[256]; + DBUG_ENTER("load_db_opt"); + bool error=1; + uint nbytes; + + bzero((char*) create,sizeof(*create)); + if ((file=my_open(path, O_RDONLY | O_SHARE, MYF(0))) >= 0) + { + IO_CACHE cache; + init_io_cache(&cache, file, IO_SIZE, READ_CACHE, 0, 0, MYF(0)); + + while ((int) (nbytes= my_b_gets(&cache, (byte*) buf, sizeof(buf))) > 0) + { + char *pos= buf+nbytes-1; + /* Remove end space and control characters */ + while (pos > buf && !my_isgraph(system_charset_info, pos[-1])) + pos--; + *pos=0; + if ((pos= strchr(buf, '='))) { - char *le,*val; - for ( le=ln, val=0 ; le<pe ; le++ ) + if (!strncmp(buf,"default-character-set", (pos-buf))) { - switch(le[0]) + if (!(create->table_charset=get_charset_by_name(pos+1, MYF(0)))) { - case '=': - le[0]='\0'; - val=le+1; - le++; - break; - case '\r': - case '\n': - le[0]='\0'; - le++; - for( ; (le[0]=='\r' || le[0]=='\n') ; le++); - if (!strcmp(ln,"default-character-set") && val && val[0]) - { - create->table_charset=get_charset_by_name(val, MYF(0)); - } - goto cnt; - break; + sql_print_error(ER(ER_UNKNOWN_CHARACTER_SET), + pos+1); } } -cnt: - ln=le; } } + error=0; + end_io_cache(&cache); my_close(file,MYF(0)); } - return 0; + DBUG_RETURN(error); } -/* db-name is already validated when we come here */ -int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info, bool silent) +/* + Create a database + + SYNOPSIS + mysql_create_db() + thd Thread handler + db Name of database to create + Function assumes that this is already validated. + create_info Database create options (like character set) + silent Used by replication when internally creating a database. + In this case the entry should not be logged. + + RETURN VALUES + 0 ok + -1 Error + +*/ + +int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info, + bool silent) { char path[FN_REFLEN+16]; MY_DIR *dirp; long result=1; int error = 0; uint create_options = create_info ? create_info->options : 0; - DBUG_ENTER("mysql_create_db"); VOID(pthread_mutex_lock(&LOCK_mysql_create_db)); @@ -167,34 +193,49 @@ int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info, bool silent } } - strcat(path,"/"); - unpack_dirname(path,path); + unpack_dirname(path, path); strcat(path,MY_DB_OPT_FILE); - if ((error=write_db_opt(thd,db,create_info,path))) - goto exit; + if (write_db_opt(path, create_info)) + { + /* + Could not create options file. + Restore things to beginning. + */ + if (rmdir(path) >= 0) + { + error= -1; + goto exit; + } + /* + We come here when we managed to create the database, but not the option + file. In this case it's best to just continue as if nothing has + happened. (This is a very unlikely senario) + */ + } if (!silent) { - if (!thd->query) + char *query; + uint query_length; + + if (!thd->query) // Only in replication { - thd->query = path; - thd->query_length = (uint) (strxmov(path,"create database ", db, NullS)- - path); + query= path; + query_length= (uint) (strxmov(path,"create database ", db, NullS) - + path); } + else { - mysql_update_log.write(thd,thd->query, thd->query_length); - if (mysql_bin_log.is_open()) - { - Query_log_event qinfo(thd, thd->query); - mysql_bin_log.write(&qinfo); - } + query= thd->query; + query_length= thd->query_length; } - if (thd->query == path) + mysql_update_log.write(thd, query, query_length); + if (mysql_bin_log.is_open()) { - thd->query = 0; // just in case - thd->query_length = 0; + Query_log_event qinfo(thd, query, query_length); + mysql_bin_log.write(&qinfo); } - send_ok(&thd->net, result); + send_ok(thd, result); } exit: @@ -207,15 +248,15 @@ exit2: /* db-name is already validated when we come here */ -int mysql_alter_db(THD *thd, char *db, HA_CREATE_INFO *create_info, bool silent) +int mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info) { - char path[FN_REFLEN+16]; + char path[FN_REFLEN+16]; MY_DIR *dirp; long result=1; int error = 0; - DBUG_ENTER("mysql_create_db"); register File file; uint create_options = create_info ? create_info->options : 0; + DBUG_ENTER("mysql_alter_db"); VOID(pthread_mutex_lock(&LOCK_mysql_create_db)); @@ -227,45 +268,27 @@ int mysql_alter_db(THD *thd, char *db, HA_CREATE_INFO *create_info, bool silent) } /* Check directory */ - (void)sprintf(path,"%s/%s", mysql_data_home, db); - strcat(path,"/"); - unpack_dirname(path,path); // Convert if not unix - strcat(path,MY_DB_OPT_FILE); - if ((error=write_db_opt(thd,db,create_info,path))) + (void)sprintf(path,"%s/%s/%s", mysql_data_home, db, MY_DB_OPT_FILE); + fn_format(path, path, "", "", MYF(MY_UNPACK_FILENAME)); + if ((error=write_db_opt(path, create_info))) goto exit; /* - Change options if current - database is being altered + Change options if current database is being altered + TODO: Delete this code */ if (thd->db && !strcmp(thd->db,db)) { thd->db_charset= create_info ? create_info->table_charset : NULL; } - if (!silent) + mysql_update_log.write(thd,thd->query, thd->query_length); + if (mysql_bin_log.is_open()) { - if (!thd->query) - { - thd->query = path; - thd->query_length = (uint) (strxmov(path,"alter database ", db, NullS)- - path); - } - { - mysql_update_log.write(thd,thd->query, thd->query_length); - if (mysql_bin_log.is_open()) - { - Query_log_event qinfo(thd, thd->query, thd->query_length); - mysql_bin_log.write(&qinfo); - } - } - if (thd->query == path) - { - thd->query = 0; // just in case - thd->query_length = 0; - } - send_ok(&thd->net, result); + Query_log_event qinfo(thd, thd->query, thd->query_length); + mysql_bin_log.write(&qinfo); } + send_ok(thd, result); exit: start_waiting_global_read_lock(thd); @@ -275,18 +298,6 @@ exit2: } - - - -const char *del_exts[]= {".frm", ".BAK", ".TMD",".opt", NullS}; -static TYPELIB deletable_extentions= -{array_elements(del_exts)-1,"del_exts", del_exts}; - -const char *known_exts[]= -{".ISM",".ISD",".ISM",".MRG",".MYI",".MYD",".db",NullS}; -static TYPELIB known_extentions= -{array_elements(known_exts)-1,"known_exts", known_exts}; - /* Drop all tables in a database. @@ -324,7 +335,7 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) my_error(ER_DB_DROP_EXISTS,MYF(0),db); } else if (!silent) - send_ok(&thd->net,0); + send_ok(thd,0); goto exit; } pthread_mutex_lock(&LOCK_open); @@ -355,7 +366,7 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) thd->query = 0; // just in case thd->query_length = 0; } - send_ok(&thd->net,(ulong) deleted); + send_ok(thd,(ulong) deleted); } error = 0; } @@ -503,30 +514,47 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db, } -bool mysql_change_db(THD *thd,const char *name) +/* + Change default database. + + SYNOPSIS + mysql_change_db() + thd Thread handler + name Databasename + + DESCRIPTION + Becasue the database name may have been given directly from the + communication packet (in case of 'connect' or 'COM_INIT_DB') + we have to do end space removal in this function. + + RETURN VALUES + 0 ok + 1 error +*/ + +bool mysql_change_db(THD *thd, const char *name) { int length, db_length; char *dbname=my_strdup((char*) name,MYF(MY_WME)); char path[FN_REFLEN]; uint db_access; HA_CREATE_INFO create; - DBUG_ENTER("mysql_change_db"); if (!dbname || !(db_length=strip_sp(dbname))) { x_free(dbname); /* purecov: inspected */ - send_error(&thd->net,ER_NO_DB_ERROR); /* purecov: inspected */ + send_error(thd,ER_NO_DB_ERROR); /* purecov: inspected */ DBUG_RETURN(1); /* purecov: inspected */ } if ((db_length > NAME_LEN) || check_db_name(dbname)) { - net_printf(&thd->net,ER_WRONG_DB_NAME, dbname); + net_printf(thd,ER_WRONG_DB_NAME, dbname); x_free(dbname); DBUG_RETURN(1); } if (lower_case_table_names) - casedn_str(dbname); + my_casedn_str(system_charset_info, dbname); DBUG_PRINT("info",("Use database: %s", dbname)); if (test_all_bits(thd->master_access,DB_ACLS)) db_access=DB_ACLS; @@ -536,7 +564,7 @@ bool mysql_change_db(THD *thd,const char *name) thd->master_access); if (!(db_access & DB_ACLS) && (!grant_option || check_grant_db(thd,dbname))) { - net_printf(&thd->net,ER_DBACCESS_DENIED_ERROR, + net_printf(thd,ER_DBACCESS_DENIED_ERROR, thd->priv_user, thd->host_or_ip, dbname); @@ -554,49 +582,37 @@ bool mysql_change_db(THD *thd,const char *name) path[length-1]=0; // remove ending '\' if (access(path,F_OK)) { - net_printf(&thd->net,ER_BAD_DB_ERROR,dbname); + net_printf(thd,ER_BAD_DB_ERROR,dbname); my_free(dbname,MYF(0)); DBUG_RETURN(1); } - send_ok(&thd->net); + send_ok(thd); x_free(thd->db); - thd->db=dbname; + thd->db=dbname; // THD::~THD will free this thd->db_length=db_length; thd->db_access=db_access; - strcat(path,"/"); - unpack_dirname(path,path); - strcat(path,MY_DB_OPT_FILE); - bzero(&create,sizeof(create)); - load_db_opt(thd,name,&create,path); + strmov(path+unpack_dirname(path,path), MY_DB_OPT_FILE); + load_db_opt(path, &create); thd->db_charset=create.table_charset; DBUG_RETURN(0); } -int mysqld_show_create_db(THD *thd,const char *name) +int mysqld_show_create_db(THD *thd, const char *dbname) { int length, db_length; - char *dbname=my_strdup((char*) name,MYF(MY_WME)); - char path[FN_REFLEN]; + char path[FN_REFLEN], *to; uint db_access; + bool found_libchar; HA_CREATE_INFO create; - CONVERT *convert=thd->convert_set; - + CONVERT *convert=thd->variables.convert_set; DBUG_ENTER("mysql_show_create_db"); - if (!dbname || !(db_length=strip_sp(dbname))) + if (check_db_name(dbname)) { - x_free(dbname); /* purecov: inspected */ - send_error(&thd->net,ER_NO_DB_ERROR); /* purecov: inspected */ - DBUG_RETURN(1); /* purecov: inspected */ - } - - if ((db_length > NAME_LEN) || check_db_name(dbname)) - { - net_printf(&thd->net,ER_WRONG_DB_NAME, dbname); - x_free(dbname); + net_printf(thd,ER_WRONG_DB_NAME, dbname); DBUG_RETURN(1); } @@ -608,7 +624,7 @@ int mysqld_show_create_db(THD *thd,const char *name) thd->master_access); if (!(db_access & DB_ACLS) && (!grant_option || check_grant_db(thd,dbname))) { - net_printf(&thd->net,ER_DBACCESS_DENIED_ERROR, + net_printf(thd,ER_DBACCESS_DENIED_ERROR, thd->priv_user, thd->host_or_ip, dbname); @@ -616,26 +632,26 @@ int mysqld_show_create_db(THD *thd,const char *name) thd->priv_user, thd->host_or_ip, dbname); - my_free(dbname,MYF(0)); DBUG_RETURN(1); } - (void) sprintf(path,"%s/%s",mysql_data_home,dbname); + (void) sprintf(path,"%s/%s",mysql_data_home, dbname); length=unpack_dirname(path,path); // Convert if not unix + found_libchar= 0; if (length && path[length-1] == FN_LIBCHAR) + { + found_libchar= 1; path[length-1]=0; // remove ending '\' + } if (access(path,F_OK)) { - net_printf(&thd->net,ER_BAD_DB_ERROR,dbname); - my_free(dbname,MYF(0)); + net_printf(thd,ER_BAD_DB_ERROR,dbname); DBUG_RETURN(1); } - - strcat(path,"/"); - unpack_dirname(path,path); - strcat(path,MY_DB_OPT_FILE); - bzero(&create,sizeof(create)); - load_db_opt(thd,name,&create,path); + if (found_libchar) + path[length-1]= FN_LIBCHAR; + strmov(path+length, MY_DB_OPT_FILE); + load_db_opt(path, &create); List<Item> field_list; field_list.push_back(new Item_empty_string("Database",NAME_LEN)); @@ -646,19 +662,16 @@ int mysqld_show_create_db(THD *thd,const char *name) String *packet = &thd->packet; packet->length(0); - net_store_data(packet, convert, name); - sprintf(path, "CREATE DATABASE %s", name); + net_store_data(packet, convert, dbname); + to= strxmov(path, "CREATE DATABASE `", dbname, "`", NullS); if (create.table_charset) - { - strcat(path," DEFAULT CHARACTER SET "); - strcat(path,create.table_charset->name); - } - net_store_data(packet, convert, path); - - if (my_net_write(&thd->net,(char*) packet->ptr(),packet->length())) + to= strxmov(to," DEFAULT CHARACTER SET ", create.table_charset->name, + NullS); + net_store_data(packet, convert, path, (uint) (to-path)); + + if (my_net_write(&thd->net,(char*) packet->ptr(), packet->length())) DBUG_RETURN(1); - send_eof(&thd->net); - + send_eof(thd); DBUG_RETURN(0); } diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index fc98cfb90c5..0581e0b5a3b 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -43,7 +43,7 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order, table_list->db=thd->db; if ((thd->options & OPTION_SAFE_UPDATES) && !conds) { - send_error(&thd->net,ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE); + send_error(thd,ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE); DBUG_RETURN(1); } @@ -83,7 +83,7 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order, !limit) { delete select; - send_ok(&thd->net,0L); + send_ok(thd,0L); DBUG_RETURN(0); // Nothing to delete } @@ -94,7 +94,7 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order, if ((thd->options & OPTION_SAFE_UPDATES) && limit == HA_POS_ERROR) { delete select; - send_error(&thd->net,ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE); + send_error(thd,ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE); DBUG_RETURN(1); } } @@ -188,10 +188,10 @@ cleanup: } delete select; if (error >= 0) // Fatal error - send_error(&thd->net,thd->killed ? ER_SERVER_SHUTDOWN: 0); + send_error(thd,thd->killed ? ER_SERVER_SHUTDOWN: 0); else { - send_ok(&thd->net,deleted); + send_ok(thd,deleted); DBUG_PRINT("info",("%d records deleted",deleted)); } DBUG_RETURN(0); @@ -354,7 +354,7 @@ void multi_delete::send_error(uint errcode,const char *err) DBUG_ENTER("multi_delete::send_error"); /* First send error what ever it is ... */ - ::send_error(&thd->net,errcode,err); + ::send_error(thd,errcode,err); /* If nothing deleted return */ if (!deleted) @@ -456,7 +456,7 @@ bool multi_delete::send_eof() thd->proc_info="end"; if (error) { - ::send_error(&thd->net); + ::send_error(thd); return 1; } @@ -483,7 +483,7 @@ bool multi_delete::send_eof() { query_cache_invalidate3(thd, delete_tables, 1); } - ::send_ok(&thd->net,deleted); + ::send_ok(thd,deleted); return 0; } @@ -580,7 +580,7 @@ end: Query_log_event qinfo(thd, thd->query, thd->query_length); mysql_bin_log.write(&qinfo); } - send_ok(&thd->net); // This should return record count + send_ok(thd); // This should return record count } VOID(pthread_mutex_lock(&LOCK_open)); unlock_table_name(thd, table_list); diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index fb40a85fd91..6b144d36f53 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -120,7 +120,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t) exit: close_thread_tables(thd); if (res > 0) - send_error(&thd->net, ER_UNKNOWN_COM_ERROR); // temporary only ... + send_error(thd, ER_UNKNOWN_COM_ERROR); // temporary only ... } DBUG_RETURN(res); } diff --git a/sql/sql_do.cc b/sql/sql_do.cc index 70124c2d796..2eef088da5b 100644 --- a/sql/sql_do.cc +++ b/sql/sql_do.cc @@ -29,6 +29,6 @@ int mysql_do(THD *thd, List<Item> &values) DBUG_RETURN(-1); while ((value = li++)) value->val_int(); - send_ok(&thd->net); + send_ok(thd); DBUG_RETURN(0); } diff --git a/sql/sql_error.cc b/sql/sql_error.cc index 13466f454c5..3d6a0fa24aa 100644 --- a/sql/sql_error.cc +++ b/sql/sql_error.cc @@ -18,202 +18,136 @@ /********************************************************************** 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. + - Whenever an error or warning occurred, it pushes it to a warning list + that the user can retrieve with SHOW WARNINGS or SHOW ERRORS. + + - For each statement, we return the number of warnings generated from this + command. Note that this can be different from @@warning_count as + we reset the warning list only for questions that uses a table. + This is done to allow on to do: + INSERT ...; + SELECT @@warning_count; + SHOW WARNINGS; + (If we would reset after each command, we could not retrieve the number + of warnings) - 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] + Supported syntaxes: + + SHOW [COUNT(*)] ERRORS [LIMIT [offset,] rows] + SHOW [COUNT(*)] WARNINGS [LIMIT [offset,] rows] + SELECT @@warning_count, @@error_count; ***********************************************************************/ -/* Handles errors and warnings .. */ #include "mysql_priv.h" -/* - Push the error to error list -*/ +/* + Reset all warnings for the thread -void push_error(uint code, const char *msg) -{ - THD *thd=current_thd; + SYNOPSIS + mysql_reset_errors() + thd Thread handle +*/ - 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); +void mysql_reset_errors(THD *thd) +{ + free_root(&thd->warn_root,MYF(0)); + bzero((char*) thd->warn_count, sizeof(thd->warn_count)); + thd->warn_list.empty(); } + /* - Push the warning to warning list + Push the warning/error to error list if there is still room in the list + + SYNOPSIS + push_warning() + thd Thread handle + level Severity of warning (note, warning, error ...) + code Error number + msg Clear error message */ -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) +void push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level, uint code, + const char *msg) +{ + if (thd->warn_list.elements < thd->variables.max_error_count) { - /* Remove the old elements and always maintian the max size - equal to sql_error_count + /* + The following code is here to change the allocation to not + use the thd->mem_root, which is freed after each query */ - 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); + MEM_ROOT *old_root=my_pthread_getspecific_ptr(MEM_ROOT*,THR_MALLOC); + my_pthread_setspecific_ptr(THR_MALLOC, &thd->warn_root); + MYSQL_ERROR *err= new MYSQL_ERROR(code, level, msg); + if (err) + thd->warn_list.push_back(err); + my_pthread_setspecific_ptr(THR_MALLOC, old_root); } - send_eof(&thd->net); - DBUG_RETURN(0); + thd->warn_count[(uint) level]++; + thd->total_warn_count++; } -/* - Return errors count -*/ -int mysqld_show_errors_count(THD *thd) -{ - List<Item> field_list; - DBUG_ENTER("mysqld_show_errors_count"); +/* + Send all notes, errors or warnings to the client in a result set - field_list.push_back(new Item_int("COUNT(*)",0,4)); + SYNOPSIS + mysqld_show_warnings() + thd Thread handler + levels_to_show Bitmap for which levels to show - if (send_fields(thd,field_list,1)) - DBUG_RETURN(1); + DESCRIPTION + Takes into account the current LIMIT - thd->packet.length(0); - net_store_data(&thd->packet,(uint32)thd->err_list.elements); + RETURN VALUES + 0 ok + 1 Error sending data to client +*/ - if (my_net_write(&thd->net,(char*) thd->packet.ptr(),thd->packet.length())) - DBUG_RETURN(-1); +static const char *warning_level_names[]= {"Note", "Warning", "Error", "?"}; - send_eof(&thd->net); - DBUG_RETURN(0); -} -/* - List all warnings -*/ - -int mysqld_show_warnings(THD *thd) -{ +my_bool mysqld_show_warnings(THD *thd, ulong levels_to_show) +{ List<Item> field_list; - DBUG_ENTER("mysqld_show_warnings"); + DBUG_ENTER("mysqld_show_errors"); - 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)); + field_list.push_back(new Item_empty_string("Level", 7)); + field_list.push_back(new Item_int("Code",0,4)); + field_list.push_back(new Item_empty_string("Message",MYSQL_ERRMSG_SIZE)); if (send_fields(thd,field_list,1)) DBUG_RETURN(1); - mysql_st_error *warn; - + MYSQL_ERROR *err; + SELECT_LEX *sel= &thd->lex.select_lex; + ha_rows offset= sel->offset_limit, limit= sel->select_limit; - 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++)) + List_iterator_fast<MYSQL_ERROR> it(thd->warn_list); + while ((err= it++)) { + /* Skip levels that the user is not interested in */ + if (!(levels_to_show & ((ulong) 1 << err->level))) + continue; + if (offset) + { + offset--; + continue; + } 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); + 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())) + DBUG_RETURN(1); + if (!--limit) + break; } - 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); + send_eof(thd); DBUG_RETURN(0); } - diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index 7fa24faf6c4..4191973b325 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -62,7 +62,7 @@ int mysql_ha_open(THD *thd, TABLE_LIST *tables) return -1; } - send_ok(&thd->net); + send_ok(thd); return 0; } @@ -83,7 +83,7 @@ int mysql_ha_close(THD *thd, TABLE_LIST *tables, bool dont_send_ok) return -1; } if (!dont_send_ok) - send_ok(&thd->net); + send_ok(thd); return 0; } @@ -185,7 +185,7 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables, } if (!(key= (byte*) sql_calloc(ALIGN_SIZE(key_len)))) { - send_error(&thd->net,ER_OUTOFMEMORY); + send_error(thd,ER_OUTOFMEMORY); goto err; } key_copy(key, table, keyno, key_len); @@ -195,7 +195,7 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables, break; } default: - send_error(&thd->net,ER_ILLEGAL_HA); + send_error(thd,ER_ILLEGAL_HA); goto err; } @@ -240,7 +240,7 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables, } ok: mysql_unlock_tables(thd,lock); - send_eof(&thd->net); + send_eof(thd); return 0; err: mysql_unlock_tables(thd,lock); diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index b02fd99e358..2852ac8b45d 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -333,7 +333,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields, if (values_list.elements == 1 && (!(thd->options & OPTION_WARNINGS) || !thd->cuted_fields)) - send_ok(&thd->net,info.copied+info.deleted,id); + send_ok(thd,info.copied+info.deleted,id); else { char buff[160]; @@ -345,7 +345,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields, else sprintf(buff,ER(ER_INSERT_INFO),info.records,info.deleted, thd->cuted_fields); - ::send_ok(&thd->net,info.copied+info.deleted,(ulonglong)id,buff); + ::send_ok(thd,info.copied+info.deleted,(ulonglong)id,buff); } DBUG_RETURN(0); @@ -667,7 +667,7 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list) delete tmp; thd->fatal_error=1; pthread_mutex_unlock(&LOCK_delayed_create); - net_printf(&thd->net,ER_CANT_CREATE_THREAD,error); + net_printf(thd,ER_CANT_CREATE_THREAD,error); DBUG_RETURN(0); } @@ -1334,7 +1334,7 @@ bool select_insert::send_data(List<Item> &values) void select_insert::send_error(uint errcode,const char *err) { - ::send_error(&thd->net,errcode,err); + ::send_error(thd,errcode,err); table->file->extra(HA_EXTRA_NO_CACHE); table->file->activate_all_index(thd); ha_rollback_stmt(thd); @@ -1360,7 +1360,7 @@ bool select_insert::send_eof() if (error) { table->file->print_error(error,MYF(0)); - ::send_error(&thd->net); + ::send_error(thd); return 1; } else @@ -1374,7 +1374,7 @@ bool select_insert::send_eof() thd->cuted_fields); if (last_insert_id) thd->insert_id(last_insert_id); // For update log - ::send_ok(&thd->net,info.copied,last_insert_id,buff); + ::send_ok(thd,info.copied,last_insert_id,buff); mysql_update_log.write(thd,thd->query,thd->query_length); if (mysql_bin_log.is_open()) { diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index dc9019de2c8..1af8d363fda 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1064,7 +1064,7 @@ bool st_select_lex_unit::create_total_list_n_last_return(THD *thd, st_lex *lex, // check usage of ORDER BY in union if (sl->order_list.first && sl->next_select() && !sl->braces) { - net_printf(&thd->net,ER_WRONG_USAGE,"UNION","ORDER BY"); + net_printf(thd,ER_WRONG_USAGE,"UNION","ORDER BY"); return 1; } for (SELECT_LEX_UNIT *inner= sl->first_inner_unit(); @@ -1092,7 +1092,7 @@ bool st_select_lex_unit::create_total_list_n_last_return(THD *thd, st_lex *lex, if (!(cursor= (TABLE_LIST *) thd->memdup((char*) aux, sizeof(*aux)))) { - send_error(&thd->net,0); + send_error(thd,0); return 1; } *new_table_list= cursor; diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 6aef99886e9..dba8216e94c 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -238,7 +238,8 @@ typedef class st_select_lex_unit SELECT_LEX_UNIT; SELECT_LEX - store information of parsed SELECT_LEX statment */ class JOIN; -class st_select_lex: public st_select_lex_node { +class st_select_lex: public st_select_lex_node +{ public: char *db, *db1, *table1, *db2, *table2; /* For outer join using .. */ Item *where, *having; /* WHERE & HAVING clauses */ @@ -342,6 +343,7 @@ typedef struct st_lex enum enum_var_type option_type; uint grant, grant_tot_col, which_columns, union_option; uint fk_delete_opt, fk_update_opt, fk_match_option; + uint param_count; bool drop_primary, drop_if_exists, local_file, olap; bool in_comment, ignore_space, verbose, simple_alter; bool derived_tables; diff --git a/sql/sql_list.h b/sql/sql_list.h index ef8a0c41a1b..56e6528f214 100644 --- a/sql/sql_list.h +++ b/sql/sql_list.h @@ -362,120 +362,3 @@ public: I_List_iterator(I_List<T> &a) : base_ilist_iterator(a) {} 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) : base_list(tmp) - { - 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(); } -}; - diff --git a/sql/sql_load.cc b/sql/sql_load.cc index ad25ef85e75..fe556be98f5 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -293,7 +293,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, } sprintf(name,ER(ER_LOAD_INFO),info.records,info.deleted, info.records-info.copied,thd->cuted_fields); - send_ok(&thd->net,info.copied+info.deleted,0L,name); + send_ok(thd,info.copied+info.deleted,0L,name); // on the slave thd->query is never initialized if (!thd->slave_thread) mysql_update_log.write(thd,thd->query,thd->query_length); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index b889b9ee29f..461276900a5 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -57,7 +57,7 @@ extern "C" pthread_mutex_t THR_LOCK_keycache; extern "C" int gethostname(char *name, int namelen); #endif -static int check_for_max_user_connections(USER_CONN *uc); +static int check_for_max_user_connections(THD *thd, USER_CONN *uc); static void decrease_user_connections(USER_CONN *uc); static bool check_db_used(THD *thd,TABLE_LIST *tables); static bool check_merge_table_access(THD *thd, char *db, TABLE_LIST *tables); @@ -77,7 +77,7 @@ const char *command_name[]={ "Prepare", "Prepare Execute", "Long Data" }; -bool volatile abort_slave = 0; +static char empty_c_string[1]= {0}; // Used for not defined 'db' #ifdef HAVE_OPENSSL extern struct st_VioSSLAcceptorFd * ssl_acceptor_fd; @@ -144,7 +144,7 @@ static int get_or_create_user_conn(THD *thd, const char *user, my_malloc(sizeof(struct user_conn) + temp_len+1, MYF(MY_WME))))) { - send_error(¤t_thd->net, 0, NullS); // Out of memory + send_error(thd, 0, NullS); // Out of memory return_val=1; goto end; } @@ -162,7 +162,7 @@ static int get_or_create_user_conn(THD *thd, const char *user, if (hash_insert(&hash_user_connections, (byte*) uc)) { my_free((char*) uc,0); - send_error(¤t_thd->net, 0, NullS); // Out of memory + send_error(thd, 0, NullS); // Out of memory return_val=1; goto end; } @@ -184,14 +184,13 @@ end: static bool check_user(THD *thd,enum_server_command command, const char *user, const char *passwd, const char *db, bool check_count) { - NET *net= &thd->net; thd->db=0; thd->db_length=0; USER_RESOURCES ur; if (!(thd->user = my_strdup(user, MYF(0)))) { - send_error(net,ER_OUT_OF_RESOURCES); + send_error(thd,ER_OUT_OF_RESOURCES); return 1; } thd->master_access=acl_getroot(thd, thd->host, thd->ip, thd->user, @@ -207,7 +206,7 @@ static bool check_user(THD *thd,enum_server_command command, const char *user, thd->master_access, thd->db ? thd->db : "*none*")); if (thd->master_access & NO_ACCESS) { - net_printf(net, ER_ACCESS_DENIED_ERROR, + net_printf(thd, ER_ACCESS_DENIED_ERROR, thd->user, thd->host_or_ip, passwd[0] ? ER(ER_YES) : ER(ER_NO)); @@ -225,7 +224,7 @@ static bool check_user(THD *thd,enum_server_command command, const char *user, VOID(pthread_mutex_unlock(&LOCK_thread_count)); if (tmp) { // Too many connections - send_error(net, ER_CON_COUNT_ERROR); + send_error(thd, ER_CON_COUNT_ERROR); return(1); } } @@ -242,7 +241,7 @@ static bool check_user(THD *thd,enum_server_command command, const char *user, get_or_create_user_conn(thd,user,thd->host_or_ip,&ur)) return -1; if (thd->user_connect && thd->user_connect->user_resources.connections && - check_for_max_user_connections(thd->user_connect)) + check_for_max_user_connections(thd, thd->user_connect)) return -1; if (db && db[0]) { @@ -252,7 +251,7 @@ static bool check_user(THD *thd,enum_server_command command, const char *user, return error; } else - send_ok(net); // Ready to handle questions + send_ok(thd); // Ready to handle questions return 0; // ok } @@ -283,7 +282,7 @@ void init_max_user_conn(void) } -static int check_for_max_user_connections(USER_CONN *uc) +static int check_for_max_user_connections(THD *thd, USER_CONN *uc) { int error=0; DBUG_ENTER("check_for_max_user_connections"); @@ -291,7 +290,7 @@ static int check_for_max_user_connections(USER_CONN *uc) if (max_user_connections && (max_user_connections <= (uint) uc->connections)) { - net_printf(&(current_thd->net),ER_TOO_MANY_USER_CONNECTIONS, uc->user); + net_printf(thd,ER_TOO_MANY_USER_CONNECTIONS, uc->user); error=1; goto end; } @@ -299,11 +298,10 @@ static int check_for_max_user_connections(USER_CONN *uc) if (uc->user_resources.connections && uc->conn_per_hour++ >= uc->user_resources.connections) { - net_printf(¤t_thd->net, ER_USER_LIMIT_REACHED, uc->user, + net_printf(thd, ER_USER_LIMIT_REACHED, uc->user, "max_connections", (long) uc->user_resources.connections); error=1; - goto end; } end: DBUG_RETURN(error); @@ -363,7 +361,7 @@ static bool check_mqh(THD *thd, uint check_command) if (uc->user_resources.questions && uc->questions++ >= uc->user_resources.questions) { - net_printf(&thd->net, ER_USER_LIMIT_REACHED, uc->user, "max_questions", + net_printf(thd, ER_USER_LIMIT_REACHED, uc->user, "max_questions", (long) uc->user_resources.questions); error=1; goto end; @@ -374,7 +372,7 @@ static bool check_mqh(THD *thd, uint check_command) if (uc->user_resources.updates && uc_update_queries[check_command] && uc->updates++ >= uc->user_resources.updates) { - net_printf(&thd->net, ER_USER_LIMIT_REACHED, uc->user, "max_updates", + net_printf(thd, ER_USER_LIMIT_REACHED, uc->user, "max_updates", (long) uc->user_resources.updates); error=1; goto end; @@ -501,7 +499,7 @@ check_connections(THD *thd) int2store(end+3,thd->server_status); bzero(end+5,13); end+=18; - if (net_write_command(net,(uchar) protocol_version, buff, + if (net_write_command(net,(uchar) protocol_version, "", 0, buff, (uint) (end-buff)) || (pkt_len= my_net_read(net)) == packet_error || pkt_len < MIN_HANDSHAKE_SIZE) @@ -629,7 +627,7 @@ pthread_handler_decl(handle_one_connection,arg) if ((error=check_connections(thd))) { // Wrong permissions if (error > 0) - net_printf(net,error,thd->host_or_ip); + net_printf(thd,error,thd->host_or_ip); #ifdef __NT__ if (vio_type(net->vio) == VIO_TYPE_NAMEDPIPE) sleep(1); /* must wait after eof() */ @@ -667,7 +665,7 @@ pthread_handler_decl(handle_one_connection,arg) thd->host_or_ip, (net->last_errno ? ER(net->last_errno) : ER(ER_UNKNOWN_ERROR))); - send_error(net,net->last_errno,NullS); + send_error(thd,net->last_errno,NullS); thread_safe_increment(aborted_threads,&LOCK_status); } @@ -765,11 +763,11 @@ end: DBUG_RETURN(0); // Never reached } + /* This works because items are allocated with sql_alloc() */ -inline void free_items(THD *thd) +void free_items(Item *item) { - /* This works because items are allocated with sql_alloc() */ - for (Item *item=thd->free_list ; item ; item=item->next) + for (; item ; item=item->next) delete item; } @@ -793,7 +791,7 @@ int mysql_table_dump(THD* thd, char* db, char* tbl_name, int fd) if (!db || check_db_name(db)) { - net_printf(&thd->net,ER_WRONG_DB_NAME, db ? db : "NULL"); + net_printf(thd,ER_WRONG_DB_NAME, db ? db : "NULL"); goto err; } if (check_access(thd, SELECT_ACL, db, &table_list->grant.privilege)) @@ -891,7 +889,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, case COM_REGISTER_SLAVE: { if (!register_slave(thd, (uchar*)packet, packet_length)) - send_ok(&thd->net); + send_ok(thd); break; } case COM_TABLE_DUMP: @@ -907,7 +905,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, memcpy(tbl_name, packet + db_len + 2, tbl_len); tbl_name[tbl_len] = 0; if (mysql_table_dump(thd, db, tbl_name, -1)) - send_error(&thd->net); // dump to NET + send_error(thd); // dump to NET break; } @@ -929,7 +927,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, if ((uint) ((uchar*) db - net->read_pos) > packet_length) { // Check if protocol is ok - send_error(net, ER_UNKNOWN_COM_ERROR); + send_error(thd, ER_UNKNOWN_COM_ERROR); break; } if (check_user(thd, COM_CHANGE_USER, user, passwd, db, 0)) @@ -953,48 +951,26 @@ bool dispatch_command(enum enum_server_command command, THD *thd, } case COM_EXECUTE: { - mysql_com_execute(thd); + mysql_stmt_execute(thd, packet); break; } case COM_LONG_DATA: { - mysql_com_longdata(thd); + mysql_stmt_get_longdata(thd, packet, packet_length); break; } case COM_PREPARE: { - mysql_com_prepare(thd,packet,packet_length); + mysql_stmt_prepare(thd, packet, packet_length); break; } case COM_QUERY: { - packet_length--; // Remove end null - /* Remove garage at start and end of query */ - while (my_isspace(system_charset_info,packet[0]) && packet_length > 0) - { - packet++; - packet_length--; - } - char *pos=packet+packet_length; // Point at end null - while (packet_length > 0 && - (pos[-1] == ';' || my_isspace(system_charset_info,pos[-1]))) - { - pos--; - packet_length--; - } - /* We must allocate some extra memory for query cache */ - if (!(thd->query= (char*) thd->memdup_w_gap((gptr) (packet), - packet_length, - thd->db_length+2))) - break; - thd->query[packet_length]=0; - thd->packet.shrink(thd->variables.net_buffer_length);// Reclaim some memory - if (!(specialflag & SPECIAL_NO_PRIOR)) - my_pthread_setprio(pthread_self(),QUERY_PRIOR); + if (alloc_query(thd, packet, packet_length)) + break; // fatal error is set mysql_log.write(thd,command,"%s",thd->query); DBUG_PRINT("query",("%s",thd->query)); - /* thd->query_length is set by mysql_parse() */ - mysql_parse(thd,thd->query,packet_length); + mysql_parse(thd,thd->query, thd->query_length); if (!(specialflag & SPECIAL_NO_PRIOR)) my_pthread_setprio(pthread_self(),WAIT_PRIOR); DBUG_PRINT("info",("query ready")); @@ -1002,7 +978,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, } case COM_FIELD_LIST: // This isn't actually needed #ifdef DONT_ALLOW_SHOW_COMMANDS - send_error(&thd->net,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */ + send_error(thd,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */ break; #else { @@ -1012,7 +988,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, bzero((char*) &table_list,sizeof(table_list)); if (!(table_list.db=thd->db)) { - send_error(net,ER_NO_DB_ERROR); + send_error(thd,ER_NO_DB_ERROR); break; } thd->free_list=0; @@ -1030,7 +1006,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, if (grant_option && check_grant(thd,SELECT_ACL,&table_list,2)) break; mysqld_list_fields(thd,&table_list,fields); - free_items(thd); + free_items(thd->free_list); break; } #endif @@ -1048,11 +1024,11 @@ bool dispatch_command(enum enum_server_command command, THD *thd, // null test to handle EOM if (!db || !strip_sp(db) || check_db_name(db)) { - net_printf(&thd->net,ER_WRONG_DB_NAME, db ? db : "NULL"); + net_printf(thd,ER_WRONG_DB_NAME, db ? db : "NULL"); break; } if (lower_case_table_names) - casedn_str(db); + my_casedn_str(system_charset_info, db); if (check_access(thd,CREATE_ACL,db,0,1)) break; mysql_log.write(thd,command,packet); @@ -1066,14 +1042,14 @@ bool dispatch_command(enum enum_server_command command, THD *thd, // null test to handle EOM if (!db || !strip_sp(db) || check_db_name(db)) { - net_printf(&thd->net,ER_WRONG_DB_NAME, db ? db : "NULL"); + net_printf(thd,ER_WRONG_DB_NAME, db ? db : "NULL"); break; } if (lower_case_table_names) - casedn_str(db); + my_casedn_str(system_charset_info, db); if (thd->locked_tables || thd->active_transaction()) { - send_error(&thd->net,ER_LOCK_OR_ACTIVE_TRANSACTION); + send_error(thd,ER_LOCK_OR_ACTIVE_TRANSACTION); break; } mysql_log.write(thd,command,db); @@ -1112,9 +1088,9 @@ bool dispatch_command(enum enum_server_command command, THD *thd, break; mysql_log.write(thd,command,NullS); if (reload_acl_and_cache(thd, options, (TABLE_LIST*) 0)) - send_error(net,0); + send_error(thd,0); else - send_eof(net); + send_eof(thd); break; } case COM_SHUTDOWN: @@ -1123,12 +1099,12 @@ bool dispatch_command(enum enum_server_command command, THD *thd, break; /* purecov: inspected */ DBUG_PRINT("quit",("Got shutdown command")); mysql_log.write(thd,command,NullS); - send_eof(net); + send_eof(thd); #ifdef __WIN__ sleep(1); // must wait after eof() #endif #ifndef OS2 - send_eof(net); // This is for 'quit request' + send_eof(thd); // This is for 'quit request' #endif close_connection(net); close_thread_tables(thd); // Free before kill @@ -1161,7 +1137,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, } case COM_PING: thread_safe_increment(com_other,&LOCK_status); - send_ok(net); // Tell client we are alive + send_ok(thd); // Tell client we are alive break; case COM_PROCESS_INFO: thread_safe_increment(com_stat[SQLCOM_SHOW_PROCESSLIST],&LOCK_status); @@ -1184,14 +1160,14 @@ bool dispatch_command(enum enum_server_command command, THD *thd, break; /* purecov: inspected */ mysql_print_status(thd); mysql_log.write(thd,command,NullS); - send_eof(net); + send_eof(thd); break; case COM_SLEEP: case COM_CONNECT: // Impossible here case COM_TIME: // Impossible from client case COM_DELAYED_INSERT: default: - send_error(net, ER_UNKNOWN_COM_ERROR); + send_error(thd, ER_UNKNOWN_COM_ERROR); break; } if (thd->lock || thd->open_tables) @@ -1201,7 +1177,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, } if (thd->fatal_error) - send_error(net,0); // End of memory ? + send_error(thd,0); // End of memory ? time_t start_of_query=thd->start_time; thd->end_time(); // Set start time @@ -1233,22 +1209,80 @@ bool dispatch_command(enum enum_server_command command, THD *thd, DBUG_RETURN(error); } + +/* + Read query from packet and store in thd->query + Used in COM_QUERY and COM_PREPARE + + DESCRIPTION + Sets the following THD variables: + query + query_length + + RETURN VALUES + 0 ok + 1 error; In this case thd->fatal_error is set +*/ + +bool alloc_query(THD *thd, char *packet, ulong packet_length) +{ + packet_length--; // Remove end null + /* Remove garage at start and end of query */ + while (my_isspace(system_charset_info,packet[0]) && packet_length > 0) + { + packet++; + packet_length--; + } + char *pos=packet+packet_length; // Point at end null + while (packet_length > 0 && + (pos[-1] == ';' || my_isspace(system_charset_info,pos[-1]))) + { + pos--; + packet_length--; + } + /* We must allocate some extra memory for query cache */ + if (!(thd->query= (char*) thd->memdup_w_gap((gptr) (packet), + packet_length, + thd->db_length+2))) + return 1; + thd->query[packet_length]=0; + thd->query_length= packet_length; + thd->packet.shrink(thd->variables.net_buffer_length);// Reclaim some memory + + if (!(specialflag & SPECIAL_NO_PRIOR)) + my_pthread_setprio(pthread_self(),QUERY_PRIOR); + return 0; +} + /**************************************************************************** ** mysql_execute_command ** Execute command saved in thd and current_lex->sql_command ****************************************************************************/ void -mysql_execute_command(void) +mysql_execute_command(THD *thd) { int res= 0; - THD *thd= current_thd; LEX *lex= &thd->lex; TABLE_LIST *tables= (TABLE_LIST*) lex->select_lex.table_list.first; SELECT_LEX *select_lex= lex->select; SELECT_LEX_UNIT *unit= &lex->unit; DBUG_ENTER("mysql_execute_command"); + /* + Reset warning count for each query that uses tables + A better approach would be to reset this for any commands + that is not a SHOW command or a select that only access local + variables, but for now this is probably good enough. + */ + if (tables) + mysql_reset_errors(thd); + /* + Save old warning count to be able to send to client how many warnings we + got + */ + thd->old_total_warn_count= thd->total_warn_count; + if (thd->slave_thread) { /* @@ -1376,7 +1410,7 @@ mysql_execute_command(void) break; case SQLCOM_EMPTY_QUERY: - send_ok(&thd->net); + send_ok(thd); break; case SQLCOM_PURGE: @@ -1388,12 +1422,15 @@ mysql_execute_command(void) } case SQLCOM_SHOW_WARNS: { - res = mysqld_show_warnings(thd); + res= mysqld_show_warnings(thd, (ulong) + ((1L << (uint) MYSQL_ERROR::WARN_LEVEL_NOTE) | + (1L << (uint) MYSQL_ERROR::WARN_LEVEL_WARN))); break; } case SQLCOM_SHOW_ERRORS: { - res = mysqld_show_errors(thd); + res= mysqld_show_warnings(thd, (ulong) + (1L << (uint) MYSQL_ERROR::WARN_LEVEL_ERROR)); break; } case SQLCOM_SHOW_NEW_MASTER: @@ -1499,7 +1536,7 @@ mysql_execute_command(void) } if (strlen(tables->name) > NAME_LEN) { - net_printf(&thd->net,ER_WRONG_TABLE_NAME,tables->name); + net_printf(thd,ER_WRONG_TABLE_NAME,tables->name); break; } LOCK_ACTIVE_MI; @@ -1507,7 +1544,7 @@ mysql_execute_command(void) if (!fetch_master_table(thd, tables->db, tables->real_name, active_mi, 0)) { - send_ok(&thd->net); + send_ok(thd); } UNLOCK_ACTIVE_MI; break; @@ -1535,7 +1572,7 @@ mysql_execute_command(void) } if (strlen(tables->name) > NAME_LEN) { - net_printf(&thd->net,ER_WRONG_TABLE_NAME,tables->name); + net_printf(thd,ER_WRONG_TABLE_NAME,tables->name); res=0; break; } @@ -1559,7 +1596,7 @@ mysql_execute_command(void) if (!(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) && check_dup(tables->db, tables->real_name, tables->next)) { - net_printf(&thd->net,ER_INSERT_TABLE_USED,tables->real_name); + net_printf(thd,ER_INSERT_TABLE_USED,tables->real_name); DBUG_VOID_RETURN; } if (tables->next) @@ -1598,7 +1635,7 @@ mysql_execute_command(void) lex->create_list, lex->key_list,0,0,0); // do logging if (!res) - send_ok(&thd->net); + send_ok(thd); } break; } @@ -1631,14 +1668,14 @@ mysql_execute_command(void) } case SQLCOM_ALTER_TABLE: #if defined(DONT_ALLOW_SHOW_COMMANDS) - send_error(&thd->net,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */ + send_error(thd,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */ break; #else { ulong priv=0; if (lex->name && strlen(lex->name) > NAME_LEN) { - net_printf(&thd->net,ER_WRONG_TABLE_NAME,lex->name); + net_printf(thd,ER_WRONG_TABLE_NAME,lex->name); res=0; break; } @@ -1721,7 +1758,7 @@ mysql_execute_command(void) } case SQLCOM_SHOW_BINLOGS: #ifdef DONT_ALLOW_SHOW_COMMANDS - send_error(&thd->net,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */ + send_error(thd,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */ DBUG_VOID_RETURN; #else { @@ -1733,7 +1770,7 @@ mysql_execute_command(void) #endif case SQLCOM_SHOW_CREATE: #ifdef DONT_ALLOW_SHOW_COMMANDS - send_error(&thd->net,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */ + send_error(thd,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */ DBUG_VOID_RETURN; #else { @@ -1805,7 +1842,7 @@ mysql_execute_command(void) goto error; if (select_lex->item_list.elements != lex->value_list.elements) { - send_error(&thd->net,ER_WRONG_VALUE_COUNT); + send_error(thd,ER_WRONG_VALUE_COUNT); DBUG_VOID_RETURN; } if (select_lex->table_list.elements == 1) @@ -1844,7 +1881,7 @@ mysql_execute_command(void) msg="LIMIT"; if (msg) { - net_printf(&thd->net, ER_WRONG_USAGE, "UPDATE", msg); + net_printf(thd, ER_WRONG_USAGE, "UPDATE", msg); res= 1; break; } @@ -1934,7 +1971,7 @@ mysql_execute_command(void) if (check_dup(tables->db, tables->real_name, tables->next)) { - net_printf(&thd->net,ER_INSERT_TABLE_USED,tables->real_name); + net_printf(thd,ER_INSERT_TABLE_USED,tables->real_name); DBUG_VOID_RETURN; } tables->lock_type=TL_WRITE; // update first table @@ -1966,7 +2003,7 @@ mysql_execute_command(void) */ if (thd->locked_tables || thd->active_transaction()) { - send_error(&thd->net,ER_LOCK_OR_ACTIVE_TRANSACTION,NullS); + send_error(thd,ER_LOCK_OR_ACTIVE_TRANSACTION,NullS); goto error; } res=mysql_truncate(thd,tables); @@ -2003,7 +2040,7 @@ mysql_execute_command(void) goto error; if ((thd->options & OPTION_SAFE_UPDATES) && !select_lex->where) { - send_error(&thd->net,ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE); + send_error(thd,ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE); goto error; } for (auxi=(TABLE_LIST*) aux_tables ; auxi ; auxi=auxi->next) @@ -2019,7 +2056,7 @@ mysql_execute_command(void) } if (!walk) { - net_printf(&thd->net,ER_NONUNIQ_TABLE,auxi->real_name); + net_printf(thd,ER_NONUNIQ_TABLE,auxi->real_name); goto error; } auxi->lock_type=walk->lock_type=TL_WRITE; @@ -2078,7 +2115,7 @@ mysql_execute_command(void) break; case SQLCOM_SHOW_DATABASES: #if defined(DONT_ALLOW_SHOW_COMMANDS) - send_error(&thd->net,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */ + send_error(thd,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */ DBUG_VOID_RETURN; #else if ((specialflag & SPECIAL_SKIP_SHOW_DB) && @@ -2112,7 +2149,7 @@ mysql_execute_command(void) break; case SQLCOM_SHOW_LOGS: #ifdef DONT_ALLOW_SHOW_COMMANDS - send_error(&thd->net,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */ + send_error(thd,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */ DBUG_VOID_RETURN; #else { @@ -2125,20 +2162,20 @@ mysql_execute_command(void) case SQLCOM_SHOW_TABLES: /* FALL THROUGH */ #ifdef DONT_ALLOW_SHOW_COMMANDS - send_error(&thd->net,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */ + send_error(thd,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */ DBUG_VOID_RETURN; #else { char *db=select_lex->db ? select_lex->db : thd->db; if (!db) { - send_error(&thd->net,ER_NO_DB_ERROR); /* purecov: inspected */ + send_error(thd,ER_NO_DB_ERROR); /* purecov: inspected */ goto error; /* purecov: inspected */ } remove_escape(db); // Fix escaped '_' if (check_db_name(db)) { - net_printf(&thd->net,ER_WRONG_DB_NAME, db); + net_printf(thd,ER_WRONG_DB_NAME, db); goto error; } if (check_access(thd,SELECT_ACL,db,&thd->col_access)) @@ -2161,14 +2198,14 @@ mysql_execute_command(void) break; case SQLCOM_SHOW_FIELDS: #ifdef DONT_ALLOW_SHOW_COMMANDS - send_error(&thd->net,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */ + send_error(thd,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */ DBUG_VOID_RETURN; #else { char *db=tables->db; if (!*db) { - send_error(&thd->net,ER_NO_DB_ERROR); /* purecov: inspected */ + send_error(thd,ER_NO_DB_ERROR); /* purecov: inspected */ goto error; /* purecov: inspected */ } remove_escape(db); // Fix escaped '_' @@ -2186,14 +2223,14 @@ mysql_execute_command(void) #endif case SQLCOM_SHOW_KEYS: #ifdef DONT_ALLOW_SHOW_COMMANDS - send_error(&thd->net,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */ + send_error(thd,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */ DBUG_VOID_RETURN; #else { char *db=tables->db; if (!db) { - send_error(&thd->net,ER_NO_DB_ERROR); /* purecov: inspected */ + send_error(thd,ER_NO_DB_ERROR); /* purecov: inspected */ goto error; /* purecov: inspected */ } remove_escape(db); // Fix escaped '_' @@ -2227,7 +2264,7 @@ mysql_execute_command(void) if (!(thd->client_capabilities & CLIENT_LOCAL_FILES) || ! opt_local_infile) { - send_error(&thd->net,ER_NOT_ALLOWED_COMMAND); + send_error(thd,ER_NOT_ALLOWED_COMMAND); goto error; } if (check_access(thd,privilege,tables->db,&tables->grant.privilege) || @@ -2242,7 +2279,7 @@ mysql_execute_command(void) if (sql_set_variables(thd, &lex->var_list)) res= -1; else - send_ok(&thd->net); + send_ok(thd); break; case SQLCOM_UNLOCK_TABLES: if (thd->locked_tables) @@ -2257,7 +2294,7 @@ mysql_execute_command(void) } if (thd->global_read_lock) unlock_global_read_lock(thd); - send_ok(&thd->net); + send_ok(thd); break; case SQLCOM_LOCK_TABLES: if (thd->locked_tables) @@ -2276,7 +2313,7 @@ mysql_execute_command(void) { thd->locked_tables=thd->lock; thd->lock=0; - send_ok(&thd->net); + send_ok(thd); } else thd->options&= ~(ulong) (OPTION_TABLE_LOCK); @@ -2286,11 +2323,11 @@ mysql_execute_command(void) { if (!strip_sp(lex->name) || check_db_name(lex->name)) { - net_printf(&thd->net,ER_WRONG_DB_NAME, lex->name); + net_printf(thd,ER_WRONG_DB_NAME, lex->name); break; } if (lower_case_table_names) - casedn_str(lex->name); + my_casedn_str(system_charset_info, lex->name); if (check_access(thd,CREATE_ACL,lex->name,0,1)) break; res=mysql_create_db(thd,lex->name,&lex->create_info,0); @@ -2300,16 +2337,16 @@ mysql_execute_command(void) { if (!strip_sp(lex->name) || check_db_name(lex->name)) { - net_printf(&thd->net,ER_WRONG_DB_NAME, lex->name); + net_printf(thd,ER_WRONG_DB_NAME, lex->name); break; } if (lower_case_table_names) - casedn_str(lex->name); + my_casedn_str(system_charset_info, lex->name); if (check_access(thd,DROP_ACL,lex->name,0,1)) break; if (thd->locked_tables || thd->active_transaction()) { - send_error(&thd->net,ER_LOCK_OR_ACTIVE_TRANSACTION); + send_error(thd,ER_LOCK_OR_ACTIVE_TRANSACTION); goto error; } res=mysql_rm_db(thd,lex->name,lex->drop_if_exists,0); @@ -2319,31 +2356,31 @@ mysql_execute_command(void) { if (!strip_sp(lex->name) || check_db_name(lex->name)) { - net_printf(&thd->net,ER_WRONG_DB_NAME, lex->name); + net_printf(thd,ER_WRONG_DB_NAME, lex->name); break; } if (check_access(thd,ALTER_ACL,lex->name,0,1)) break; if (thd->locked_tables || thd->active_transaction()) { - send_error(&thd->net,ER_LOCK_OR_ACTIVE_TRANSACTION); + send_error(thd,ER_LOCK_OR_ACTIVE_TRANSACTION); goto error; } - res=mysql_alter_db(thd,lex->name,&lex->create_info,0); + res=mysql_alter_db(thd,lex->name,&lex->create_info); break; } case SQLCOM_SHOW_CREATE_DB: { if (!strip_sp(lex->name) || check_db_name(lex->name)) { - net_printf(&thd->net,ER_WRONG_DB_NAME, lex->name); + net_printf(thd,ER_WRONG_DB_NAME, lex->name); break; } if (check_access(thd,DROP_ACL,lex->name,0,1)) break; if (thd->locked_tables || thd->active_transaction()) { - send_error(&thd->net,ER_LOCK_OR_ACTIVE_TRANSACTION); + send_error(thd,ER_LOCK_OR_ACTIVE_TRANSACTION); goto error; } res=mysqld_show_create_db(thd,lex->name); @@ -2354,7 +2391,7 @@ mysql_execute_command(void) break; #ifdef HAVE_DLOPEN if (!(res = mysql_create_function(thd,&lex->udf))) - send_ok(&thd->net); + send_ok(thd); #else res= -1; #endif @@ -2364,7 +2401,7 @@ mysql_execute_command(void) break; #ifdef HAVE_DLOPEN if (!(res = mysql_drop_function(thd,lex->udf.name))) - send_ok(&thd->net); + send_ok(thd); #else res= -1; #endif @@ -2424,7 +2461,7 @@ mysql_execute_command(void) { if (lex->columns.elements) { - send_error(&thd->net,ER_ILLEGAL_GRANT_FOR_TABLE); + send_error(thd,ER_ILLEGAL_GRANT_FOR_TABLE); res=1; } else @@ -2454,9 +2491,9 @@ mysql_execute_command(void) if (check_global_access(thd,RELOAD_ACL) || check_db_used(thd, tables)) goto error; if (reload_acl_and_cache(thd, lex->type, tables)) - send_error(&thd->net,0); + send_error(thd,0); else - send_ok(&thd->net); + send_ok(thd); break; case SQLCOM_KILL: kill_one_thread(thd,lex->thread_id); @@ -2506,7 +2543,7 @@ mysql_execute_command(void) thd->options= ((thd->options & (ulong) ~(OPTION_STATUS_NO_TRANS_UPDATE)) | OPTION_BEGIN); thd->server_status|= SERVER_STATUS_IN_TRANS; - send_ok(&thd->net); + send_ok(thd); } break; case SQLCOM_COMMIT: @@ -2520,7 +2557,7 @@ mysql_execute_command(void) thd->server_status&= ~SERVER_STATUS_IN_TRANS; if (!ha_commit(thd)) { - send_ok(&thd->net); + send_ok(thd); } else res= -1; @@ -2531,21 +2568,21 @@ mysql_execute_command(void) if (!ha_rollback(thd)) { if (thd->options & OPTION_STATUS_NO_TRANS_UPDATE) - send_warning(&thd->net,ER_WARNING_NOT_COMPLETE_ROLLBACK,0); + send_warning(thd,ER_WARNING_NOT_COMPLETE_ROLLBACK,0); else - send_ok(&thd->net); + send_ok(thd); } else res= -1; thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE); break; default: /* Impossible */ - send_ok(&thd->net); + send_ok(thd); break; } thd->proc_info="query end"; // QQ if (res < 0) - send_error(&thd->net,thd->killed ? ER_SERVER_SHUTDOWN : 0); + send_error(thd,thd->killed ? ER_SERVER_SHUTDOWN : 0); error: DBUG_VOID_RETURN; @@ -2578,7 +2615,7 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv, if ((!db || !db[0]) && !thd->db && !dont_check_global_grants) { if (!no_errors) - send_error(&thd->net,ER_NO_DB_ERROR); /* purecov: tested */ + send_error(thd,ER_NO_DB_ERROR); /* purecov: tested */ DBUG_RETURN(TRUE); /* purecov: tested */ } @@ -2591,7 +2628,7 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv, ! db && dont_check_global_grants) { // We can never grant this if (!no_errors) - net_printf(&thd->net,ER_ACCESS_DENIED_ERROR, + net_printf(thd,ER_ACCESS_DENIED_ERROR, thd->priv_user, thd->host_or_ip, thd->password ? ER(ER_YES) : ER(ER_NO));/* purecov: tested */ @@ -2616,7 +2653,7 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv, !(want_access & ~TABLE_ACLS))) DBUG_RETURN(FALSE); /* Ok */ if (!no_errors) - net_printf(&thd->net,ER_DBACCESS_DENIED_ERROR, + net_printf(thd,ER_DBACCESS_DENIED_ERROR, thd->priv_user, thd->host_or_ip, db ? db : thd->db ? thd->db : "unknown"); /* purecov: tested */ @@ -2632,7 +2669,7 @@ bool check_global_access(THD *thd, ulong want_access) if ((thd->master_access & want_access) == want_access) return 0; get_privilege_desc(command, sizeof(command), want_access); - net_printf(&thd->net,ER_SPECIFIC_ACCESS_DENIED_ERROR, + net_printf(thd,ER_SPECIFIC_ACCESS_DENIED_ERROR, command); return 1; } @@ -2687,7 +2724,7 @@ static bool check_db_used(THD *thd,TABLE_LIST *tables) { if (!(tables->db=thd->db)) { - send_error(&thd->net,ER_NO_DB_ERROR); /* purecov: tested */ + send_error(thd,ER_NO_DB_ERROR); /* purecov: tested */ return TRUE; /* purecov: tested */ } } @@ -2710,7 +2747,7 @@ static bool check_merge_table_access(THD *thd, char *db, tmp->db=db; else if (strcmp(tmp->db,db)) { - send_error(&thd->net,ER_UNION_TABLES_IN_DIFFERENT_DIR); + send_error(thd,ER_UNION_TABLES_IN_DIFFERENT_DIR); return 1; } } @@ -2799,11 +2836,10 @@ mysql_init_query(THD *thd) thd->lex.olap=0; thd->lex.select->olap= UNSPECIFIED_OLAP_TYPE; thd->fatal_error= 0; // Safety + thd->total_warn_count=0; // Warnings for this query thd->last_insert_id_used= thd->query_start_used= thd->insert_id_used=0; thd->sent_row_count= thd->examined_row_count= 0; thd->safe_to_cache_query= 1; - thd->param_count=0; - thd->prepare_command=false; thd->lex.param_list.empty(); DBUG_VOID_RETURN; } @@ -2850,6 +2886,33 @@ mysql_new_select(LEX *lex, bool move_down) return 0; } +/* + Create a select to return the same output as 'SELECT @@var_name'. + + SYNOPSIS + create_select_for_variable() + var_name Variable name + + DESCRIPTION + Used for SHOW COUNT(*) [ WARNINGS | ERROR] + + This will crash with a core dump if the variable doesn't exists +*/ + +void create_select_for_variable(const char *var_name) +{ + LEX *lex; + LEX_STRING tmp; + DBUG_ENTER("create_select_for_variable"); + lex= current_lex; + mysql_init_select(lex); + lex->sql_command= SQLCOM_SELECT; + tmp.str= (char*) var_name; + tmp.length=strlen(var_name); + add_item_to_list(get_system_var(OPT_SESSION, tmp)); + DBUG_VOID_RETURN; +} + void mysql_init_multi_delete(LEX *lex) { @@ -2881,7 +2944,7 @@ mysql_parse(THD *thd, char *inBuf, uint length) } else { - mysql_execute_command(); + mysql_execute_command(thd); query_cache_end_of_result(&thd->net); } } @@ -2892,7 +2955,7 @@ mysql_parse(THD *thd, char *inBuf, uint length) query_cache_abort(&thd->net); } thd->proc_info="freeing items"; - free_items(thd); /* Free strings used by items */ + free_items(thd->free_list); /* Free strings used by items */ lex_end(lex); } DBUG_VOID_RETURN; @@ -2928,7 +2991,7 @@ bool add_field_to_list(char *field_name, enum_field_types type, if (strlen(field_name) > NAME_LEN) { - net_printf(&thd->net, ER_TOO_LONG_IDENT, field_name); /* purecov: inspected */ + net_printf(thd, ER_TOO_LONG_IDENT, field_name); /* purecov: inspected */ DBUG_RETURN(1); /* purecov: inspected */ } if (type_modifier & PRI_KEY_FLAG) @@ -2951,7 +3014,7 @@ bool add_field_to_list(char *field_name, enum_field_types type, if ((type_modifier & (NOT_NULL_FLAG | AUTO_INCREMENT_FLAG)) == NOT_NULL_FLAG) { - net_printf(&thd->net,ER_INVALID_DEFAULT,field_name); + net_printf(thd,ER_INVALID_DEFAULT,field_name); DBUG_RETURN(1); } default_value=0; @@ -3037,7 +3100,7 @@ bool add_field_to_list(char *field_name, enum_field_types type, res=default_value->val_str(&str); if (res->length()) { - net_printf(&thd->net,ER_BLOB_CANT_HAVE_DEFAULT,field_name); /* purecov: inspected */ + net_printf(thd,ER_BLOB_CANT_HAVE_DEFAULT,field_name); /* purecov: inspected */ DBUG_RETURN(1); /* purecov: inspected */ } new_field->def=0; @@ -3057,7 +3120,7 @@ bool add_field_to_list(char *field_name, enum_field_types type, uint tmp_length=new_field->length; if (tmp_length > PRECISION_FOR_DOUBLE) { - net_printf(&thd->net,ER_WRONG_FIELD_SPEC,field_name); + net_printf(thd,ER_WRONG_FIELD_SPEC,field_name); DBUG_RETURN(1); } else if (tmp_length > PRECISION_FOR_FLOAT) @@ -3111,7 +3174,7 @@ bool add_field_to_list(char *field_name, enum_field_types type, { if (interval->count > sizeof(longlong)*8) { - net_printf(&thd->net,ER_TOO_BIG_SET,field_name); /* purecov: inspected */ + net_printf(thd,ER_TOO_BIG_SET,field_name); /* purecov: inspected */ DBUG_RETURN(1); /* purecov: inspected */ } new_field->pack_length=(interval->count+7)/8; @@ -3133,7 +3196,7 @@ bool add_field_to_list(char *field_name, enum_field_types type, (void) find_set(interval,res->ptr(),res->length()); if (thd->cuted_fields) { - net_printf(&thd->net,ER_INVALID_DEFAULT,field_name); + net_printf(thd,ER_INVALID_DEFAULT,field_name); DBUG_RETURN(1); } } @@ -3156,7 +3219,7 @@ bool add_field_to_list(char *field_name, enum_field_types type, res=default_value->val_str(&str); if (!find_enum(interval,res->ptr(),res->length())) { - net_printf(&thd->net,ER_INVALID_DEFAULT,field_name); + net_printf(thd,ER_INVALID_DEFAULT,field_name); DBUG_RETURN(1); } } @@ -3168,14 +3231,14 @@ bool add_field_to_list(char *field_name, enum_field_types type, (!new_field->length && !(new_field->flags & BLOB_FLAG) && type != FIELD_TYPE_STRING && type != FIELD_TYPE_VAR_STRING)) { - net_printf(&thd->net,ER_TOO_BIG_FIELDLENGTH,field_name, + net_printf(thd,ER_TOO_BIG_FIELDLENGTH,field_name, MAX_FIELD_WIDTH-1); /* purecov: inspected */ DBUG_RETURN(1); /* purecov: inspected */ } type_modifier&= AUTO_INCREMENT_FLAG; if ((~allowed_type_modifier) & type_modifier) { - net_printf(&thd->net,ER_WRONG_FIELD_SPEC,field_name); + net_printf(thd,ER_WRONG_FIELD_SPEC,field_name); DBUG_RETURN(1); } if (!new_field->pack_length) @@ -3286,7 +3349,7 @@ TABLE_LIST *add_table_to_list(Table_ident *table, LEX_STRING *alias, (table->table.length && check_table_name(table->table.str,table->table.length)) || table->db.str && check_db_name(table->db.str)) { - net_printf(&thd->net,ER_WRONG_TABLE_NAME,table->table.str); + net_printf(thd,ER_WRONG_TABLE_NAME,table->table.str); DBUG_RETURN(0); } @@ -3308,7 +3371,8 @@ TABLE_LIST *add_table_to_list(Table_ident *table, LEX_STRING *alias, } else { - ptr->db= (char*) ""; + /* The following can't be "" as we may do 'casedn_str()' on it */ + ptr->db= empty_c_string; ptr->db_length= 0; } @@ -3339,7 +3403,7 @@ TABLE_LIST *add_table_to_list(Table_ident *table, LEX_STRING *alias, { if (!strcmp(alias_str,tables->name) && !strcmp(ptr->db, tables->db)) { - net_printf(&thd->net,ER_NONUNIQ_TABLE,alias_str); /* purecov: tested */ + net_printf(thd,ER_NONUNIQ_TABLE,alias_str); /* purecov: tested */ DBUG_RETURN(0); /* purecov: tested */ } } @@ -3487,9 +3551,9 @@ void kill_one_thread(THD *thd, ulong id) } if (!error) - send_ok(&thd->net); + send_ok(thd); else - net_printf(&thd->net,error,id); + net_printf(thd,error,id); } /* Clear most status variables */ @@ -3552,7 +3616,7 @@ bool check_simple_select() char command[80]; strmake(command, thd->lex.yylval->symbol.str, min(thd->lex.yylval->symbol.length, sizeof(command)-1)); - net_printf(&thd->net, ER_CANT_USE_OPTION_HERE, command); + net_printf(thd, ER_CANT_USE_OPTION_HERE, command); return 1; } return 0; diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index d41aca21fb8..05b3f360caa 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -25,7 +25,7 @@ Prepare: store its information list lex->param_list - Without executing the query, return back to client the total number of parameters along with result-set metadata information - (if any ) + (if any) Prepare-execute: @@ -38,46 +38,132 @@ Prepare-execute: to client Long data handling: - - Server gets the long data in pieces with command type 'COM_LONG_DATA'. - The packet recieved will have the format as: - [type_spec_exists][type][length][data] + [COM_LONG_DATA:1][parameter_number:2][type:2][data] - Checks if the type is specified by client, and if yes reads the type, and stores the data in that format. - - If length == MYSQL_END_OF_DATA, then server sets up the data read ended. + - It's up to the client to check for read data ended. The server doesn't + care. + ***********************************************************************/ #include "mysql_priv.h" #include "sql_acl.h" #include <assert.h> // for DEBUG_ASSERT() -#include <ctype.h> // for isspace() +#include <m_ctype.h> // for isspace() -/**************************************************************************/ extern int yyparse(void); static ulong get_param_length(uchar **packet); static uint get_buffer_type(uchar **packet); static bool param_is_null(uchar **packet); static bool setup_param_fields(THD *thd,List<Item> ¶ms); -static uchar* setup_param_field(Item_param *item_param, uchar *pos, uint buffer_type); +static uchar* setup_param_field(Item_param *item_param, uchar *pos, + uint buffer_type); static void setup_longdata_field(Item_param *item_param, uchar *pos); static bool setup_longdata(THD *thd,List<Item> ¶ms); -static void send_prepare_results(THD *thd); -static void mysql_parse_prepare_query(THD *thd,char *packet,uint length); -static bool mysql_send_insert_fields(THD *thd,TABLE_LIST *table_list, +static bool send_prepare_results(PREP_STMT *stmt); +static bool parse_prepare_query(PREP_STMT *stmt, char *packet, uint length); +static bool mysql_send_insert_fields(PREP_STMT *stmt, TABLE_LIST *table_list, List<Item> &fields, - List<List_item> &values_list,thr_lock_type lock_type); -static bool mysql_test_insert_fields(THD *thd,TABLE_LIST *table_list, + List<List_item> &values_list, + thr_lock_type lock_type); +static bool mysql_test_insert_fields(PREP_STMT *stmt, TABLE_LIST *table_list, List<Item> &fields, - List<List_item> &values_list,thr_lock_type lock_type); -static bool mysql_test_upd_fields(THD *thd,TABLE_LIST *table_list, + List<List_item> &values_list, + thr_lock_type lock_type); +static bool mysql_test_upd_fields(PREP_STMT *stmt, TABLE_LIST *table_list, List<Item> &fields, List<Item> &values, COND *conds,thr_lock_type lock_type); -static bool mysql_test_select_fields(THD *thd, TABLE_LIST *tables, - List<Item> &fields, List<Item> &values, - COND *conds, ORDER *order, ORDER *group, - Item *having,thr_lock_type lock_type); -extern const char *any_db; -/**************************************************************************/ +static bool mysql_test_select_fields(PREP_STMT *stmt, TABLE_LIST *tables, + List<Item> &fields, List<Item> &values, + COND *conds, ORDER *order, ORDER *group, + Item *having,thr_lock_type lock_type); + + +/* + Find prepared statement in thd + + SYNOPSIS + find_prepared_statement() + thd Thread handler + stmt_id Statement id server specified to the client on prepare + + RETURN VALUES + 0 error. In this case the error is sent with my_error() + ptr Pointer to statement +*/ + +static PREP_STMT *find_prepared_statement(THD *thd, ulong stmt_id, + const char *when) +{ + PREP_STMT *stmt; + DBUG_ENTER("find_prepared_statement"); + DBUG_PRINT("enter",("stmt_id: %d", stmt_id)); + + if (thd->last_prepared_stmt && thd->last_prepared_stmt->stmt_id == stmt_id) + DBUG_RETURN(thd->last_prepared_stmt); + if ((stmt= (PREP_STMT*) tree_search(&thd->prepared_statements, &stmt_id, + (void*) 0))) + DBUG_RETURN (thd->last_prepared_stmt= stmt); + my_error(ER_UNKNOWN_STMT_HANDLER, MYF(0), stmt_id, when); + DBUG_RETURN(0); +} + +/* + Compare two prepared statements; Used to find a prepared statement +*/ + +int compare_prep_stmt(PREP_STMT *a, PREP_STMT *b, void *not_used) +{ + return (a->stmt_id < b->stmt_id) ? -1 : (a->stmt_id == b->stmt_id) ? 0 : 1; +} + + +/* + Free prepared statement. + + SYNOPSIS + standard tree_element_free function. + + DESCRIPTION + We don't have to free the stmt itself as this was stored in the tree + and will be freed when the node is deleted +*/ + +void free_prep_stmt(PREP_STMT *stmt, TREE_FREE mode, void *not_used) +{ + free_root(&stmt->mem_root, MYF(0)); + free_items(stmt->free_list); +} + +/* + Send prepared stmt info to client after prepare +*/ + +bool send_prep_stmt(PREP_STMT *stmt, uint columns) +{ + char buff[8]; + int4store(buff, stmt->stmt_id); + int2store(buff+4, columns); + int2store(buff+6, stmt->param_count); + return my_net_write(&stmt->thd->net, buff, sizeof(buff)); +} + +/* + Send information about all item parameters + + TODO: Not yet ready +*/ + +bool send_item_params(PREP_STMT *stmt) +{ + char buff[1]; + buff[0]=0; + return my_net_write(&stmt->thd->net, buff, sizeof(buff)); +} + + /* Read the buffer type, this happens only first time @@ -90,8 +176,13 @@ static uint get_buffer_type(uchar **packet) return (uint) uint2korr(pos); } + /* Check for NULL param data + + RETURN VALUES + 0 Value was not NULL + 1 Value was NULL */ static bool param_is_null(uchar **packet) @@ -144,8 +235,7 @@ static uchar* setup_param_field(Item_param *item_param, item_param->set_null(); return(pos); } - switch (buffer_type) - { + switch (buffer_type) { case FIELD_TYPE_TINY: item_param->set_int((longlong)(*pos)); pos += 1; @@ -169,7 +259,7 @@ static uchar* setup_param_field(Item_param *item_param, case FIELD_TYPE_FLOAT: float data; float4get(data,pos); - item_param->set_double(data); + item_param->set_double((double) data); pos += 4; break; case FIELD_TYPE_DOUBLE: @@ -193,20 +283,19 @@ static uchar* setup_param_field(Item_param *item_param, from client .. */ -static bool setup_param_fields(THD *thd, List<Item> ¶ms) +static bool setup_param_fields(THD *thd, PREP_STMT *stmt) { - reg2 Item_param *item_param; - List_iterator<Item> it(params); - NET *net = &thd->net; DBUG_ENTER("setup_param_fields"); - +#ifdef READY_TO_BE_USED + Item_param *item_param; ulong param_count=0; - uchar *pos=(uchar*)net->read_pos+1;// skip command type - - if(*pos++) // No types supplied, read only param data + uchar *pos=(uchar*) thd->net.read_pos+1;// skip command type + + + if (*pos++) // No types supplied, read only param data { while ((item_param=(Item_param *)it++) && - (param_count++ < thd->param_count)) + (param_count++ < stmt->param_count)) { if (item_param->long_data_supplied) continue; @@ -224,68 +313,15 @@ static bool setup_param_fields(THD *thd, List<Item> ¶ms) continue; if (!(pos=setup_param_field(item_param,pos, - item_param->buffer_type=(enum_field_types)get_buffer_type(&pos)))) + item_param->buffer_type= + (enum_field_types) get_buffer_type(&pos)))) DBUG_RETURN(1); } } +#endif DBUG_RETURN(0); } -/* - Buffer the long data and update the flags -*/ - -static void setup_longdata_field(Item_param *item_param, uchar *pos) -{ - ulong len; - - if (!*pos++) - item_param->buffer_type=(enum_field_types)get_buffer_type(&pos); - - if (*pos == MYSQL_LONG_DATA_END) - item_param->set_long_end(); - - else - { - len = get_param_length(&pos); - item_param->set_longdata((const char *)pos, len); - } -} - -/* - Store the long data from client in pieces -*/ - -static bool setup_longdata(THD *thd, List<Item> ¶ms) -{ - NET *net=&thd->net; - List_iterator<Item> it(params); - DBUG_ENTER("setup_longdata"); - - uchar *pos=(uchar*)net->read_pos+1;// skip command type at first position - ulong param_number = get_param_length(&pos); - Item_param *item_param = thd->current_param; - - if (thd->current_param_number != param_number) - { - thd->current_param_number = param_number; - while (param_number--) /* TODO: - Change this loop by either having operator '+' - overloaded to point to desired 'item' or - add another memeber in list as 'goto' with - location count as parameter number, but what - is the best way to traverse ? - */ - { - it++; - } - thd->current_param = item_param = (Item_param *)it++; - } - setup_longdata_field(item_param,pos); - DBUG_RETURN(0); -} - - /* Validates insert fields @@ -337,16 +373,15 @@ static int check_prepare_fields(THD *thd,TABLE *table, List<Item> &fields, Validate the following information for INSERT statement: - field existance - fields count - - If there is no column list spec exists, then update the field_list - with all columns from the table, and send fields info back to client */ -static bool mysql_test_insert_fields(THD *thd, TABLE_LIST *table_list, +static bool mysql_test_insert_fields(PREP_STMT *stmt, + TABLE_LIST *table_list, List<Item> &fields, List<List_item> &values_list, thr_lock_type lock_type) { + THD *thd= stmt->thd; TABLE *table; List_iterator_fast<List_item> its(values_list); List_item *values; @@ -358,7 +393,7 @@ static bool mysql_test_insert_fields(THD *thd, TABLE_LIST *table_list, if ((values= its++)) { uint value_count; - ulong counter=0; + ulong counter= 0; if (check_insert_fields(thd,table,fields,*values,1)) DBUG_RETURN(1); @@ -366,35 +401,20 @@ static bool mysql_test_insert_fields(THD *thd, TABLE_LIST *table_list, value_count= values->elements; its.rewind(); - while ((values = its++)) + while ((values= its++)) { counter++; if (values->elements != value_count) { my_printf_error(ER_WRONG_VALUE_COUNT_ON_ROW, ER(ER_WRONG_VALUE_COUNT_ON_ROW), - MYF(0),counter); + MYF(0), counter); DBUG_RETURN(1); } } - if (fields.elements == 0) - { - /* No field listing, so setup all fields */ - List<Item> all_fields; - Field **ptr,*field; - for (ptr=table->field; (field= *ptr) ; ptr++) - { - all_fields.push_back(new Item_field(table->table_cache_key, - table->real_name, - field->field_name)); - } - if ((setup_fields(thd,table_list,all_fields,1,0,0) || - send_fields(thd,all_fields,1))) - DBUG_RETURN(1); - } - else if (send_fields(thd,fields,1)) - DBUG_RETURN(1); } + if (send_prep_stmt(stmt, 0) || send_item_params(stmt)) + DBUG_RETURN(1); DBUG_RETURN(0); } @@ -403,15 +423,16 @@ static bool mysql_test_insert_fields(THD *thd, TABLE_LIST *table_list, Validate the following information UPDATE - set and where clause DELETE - where clause - And send update-set cluase column list fields info - back to client. For DELETE, just validate where cluase + And send update-set clause column list fields info + back to client. For DELETE, just validate where clause and return no fields information back to client. */ -static bool mysql_test_upd_fields(THD *thd, TABLE_LIST *table_list, +static bool mysql_test_upd_fields(PREP_STMT *stmt, TABLE_LIST *table_list, List<Item> &fields, List<Item> &values, COND *conds, thr_lock_type lock_type) { + THD *thd= stmt->thd; TABLE *table; DBUG_ENTER("mysql_test_upd_fields"); @@ -426,9 +447,8 @@ static bool mysql_test_upd_fields(THD *thd, TABLE_LIST *table_list, Currently return only column list info only, and we are not sending any info on where clause. */ - if (fields.elements && send_fields(thd,fields,1)) + if (send_prep_stmt(stmt, 0) || send_item_params(stmt)) DBUG_RETURN(1); - DBUG_RETURN(0); } @@ -437,7 +457,7 @@ static bool mysql_test_upd_fields(THD *thd, TABLE_LIST *table_list, SELECT - column list - where clause - - orderr clause + - order clause - having clause - group by clause - if no column spec i.e. '*', then setup all fields @@ -445,13 +465,14 @@ static bool mysql_test_upd_fields(THD *thd, TABLE_LIST *table_list, And send column list fields info back to client. */ -static bool mysql_test_select_fields(THD *thd, TABLE_LIST *tables, +static bool mysql_test_select_fields(PREP_STMT *stmt, TABLE_LIST *tables, List<Item> &fields, List<Item> &values, COND *conds, ORDER *order, ORDER *group, Item *having, thr_lock_type lock_type) { TABLE *table; bool hidden_group_fields; + THD *thd= stmt->thd; List<Item> all_fields(fields); DBUG_ENTER("mysql_test_select_fields"); @@ -482,13 +503,15 @@ static bool mysql_test_select_fields(THD *thd, TABLE_LIST *tables, Currently return only column list info only, and we are not sending any info on where clause. */ - if (fields.elements && send_fields(thd,fields,1)) + if (send_prep_stmt(stmt, fields.elements) || + send_fields(thd,fields,0) || send_item_params(stmt)) DBUG_RETURN(1); DBUG_RETURN(0); } + /* - Check the access privileges + Check the access privileges */ static bool check_prepare_access(THD *thd, TABLE_LIST *tables, @@ -505,42 +528,47 @@ static bool check_prepare_access(THD *thd, TABLE_LIST *tables, Send the prepare query results back to client */ -static void send_prepare_results(THD *thd) +static bool send_prepare_results(PREP_STMT *stmt) { - DBUG_ENTER("send_prepare_results"); + THD *thd= stmt->thd; + LEX *lex= &thd->lex; enum enum_sql_command sql_command = thd->lex.sql_command; - - DBUG_PRINT("enter",("command :%d, param_count :%ld", - sql_command,thd->param_count)); + DBUG_ENTER("send_prepare_results"); + DBUG_PRINT("enter",("command: %d, param_count: %ld", + sql_command, lex->param_count)); - LEX *lex=&thd->lex; + /* Setup prepared stmt */ + stmt->param_count= lex->param_count; + stmt->free_list= thd->free_list; // Save items used in stmt + thd->free_list= 0; + SELECT_LEX *select_lex = lex->select; TABLE_LIST *tables=(TABLE_LIST*) select_lex->table_list.first; - switch(sql_command) { + switch (sql_command) { case SQLCOM_INSERT: - if (mysql_test_insert_fields(thd,tables, lex->field_list, + if (mysql_test_insert_fields(stmt, tables, lex->field_list, lex->many_values, lex->lock_option)) goto abort; break; case SQLCOM_UPDATE: - if (mysql_test_upd_fields(thd,tables, select_lex->item_list, + if (mysql_test_upd_fields(stmt, tables, select_lex->item_list, lex->value_list, select_lex->where, lex->lock_option)) goto abort; break; case SQLCOM_DELETE: - if (mysql_test_upd_fields(thd,tables, select_lex->item_list, + if (mysql_test_upd_fields(stmt, tables, select_lex->item_list, lex->value_list, select_lex->where, lex->lock_option)) goto abort; break; case SQLCOM_SELECT: - if (mysql_test_select_fields(thd,tables, select_lex->item_list, + if (mysql_test_select_fields(stmt, tables, select_lex->item_list, lex->value_list, select_lex->where, (ORDER*) select_lex->order_list.first, (ORDER*) select_lex->group_list.first, @@ -556,42 +584,37 @@ static void send_prepare_results(THD *thd) */ } } - send_ok(&thd->net,thd->param_count,0); - DBUG_VOID_RETURN; + DBUG_RETURN(0); abort: - send_error(&thd->net,thd->killed ? ER_SERVER_SHUTDOWN : 0); - DBUG_VOID_RETURN; + send_error(thd,thd->killed ? ER_SERVER_SHUTDOWN : 0); + DBUG_RETURN(1); } /* Parse the prepare query */ -static void mysql_parse_prepare_query(THD *thd, char *packet, uint length) +static bool parse_prepare_query(PREP_STMT *stmt, + char *packet, uint length) { - DBUG_ENTER("mysql_parse_prepare_query"); + bool error= 1; + THD *thd= stmt->thd; + DBUG_ENTER("parse_prepare_query"); mysql_log.write(thd,COM_PREPARE,"%s",packet); mysql_init_query(thd); thd->prepare_command=true; + thd->safe_to_cache_query= 0; - if (query_cache.send_result_to_client(thd, packet, length) <= 0) - { - LEX *lex=lex_start(thd, (uchar*)packet, length); - - if (!yyparse() && !thd->fatal_error) - { - send_prepare_results(thd); - query_cache_end_of_result(&thd->net); - } - else - query_cache_abort(&thd->net); - lex_end(lex); - } - DBUG_VOID_RETURN; + LEX *lex=lex_start(thd, (uchar*) packet, length); + if (!yyparse() && !thd->fatal_error) + error= send_prepare_results(stmt); + lex_end(lex); + DBUG_RETURN(error); } + /* Parse the query and send the total number of parameters and resultset metadata information back to client (if any), @@ -606,52 +629,36 @@ static void mysql_parse_prepare_query(THD *thd, char *packet, uint length) items. */ -void mysql_com_prepare(THD *thd, char *packet, uint packet_length) +bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length) { MEM_ROOT thd_root = thd->mem_root; - DBUG_ENTER("mysql_com_prepare"); - - packet_length--; - - while (isspace(packet[0]) && packet_length > 0) - { - packet++; - packet_length--; - } - char *pos=packet+packet_length; - while (packet_length > 0 && (pos[-1] == ';' || isspace(pos[-1]))) - { - pos--; - packet_length--; - } - /* - Have the prepare items to have a connection level scope or - till next prepare statement by doing all allocations using - connection level memory allocator 'con_root' from THD. - */ - free_root(&thd->con_root,MYF(0)); - init_sql_alloc(&thd->con_root,8192,8192); - thd->mem_root = thd->con_root; - - if (!(thd->query= (char*) thd->memdup_w_gap((gptr) (packet), - packet_length, - thd->db_length+2))) - DBUG_VOID_RETURN; - thd->query[packet_length]=0; - thd->packet.shrink(net_buffer_length); - thd->query_length = packet_length; + PREP_STMT stmt; + bool error; + DBUG_ENTER("mysql_stmt_prepare"); - if (!(specialflag & SPECIAL_NO_PRIOR)) - my_pthread_setprio(pthread_self(),QUERY_PRIOR); - - mysql_parse_prepare_query(thd,thd->query,packet_length); + bzero((char*) &stmt, sizeof(stmt)); + stmt.thd= thd; + stmt.stmt_id= ++thd->current_stmt_id; + init_sql_alloc(&stmt.mem_root, 8192, 8192); + + thd->mem_root= stmt.mem_root; + if (alloc_query(thd, packet, packet_length)) + goto err; + if (parse_prepare_query(&stmt, thd->query, thd->query_length)) + goto err; if (!(specialflag & SPECIAL_NO_PRIOR)) my_pthread_setprio(pthread_self(),WAIT_PRIOR); - thd->mem_root = thd_root; // restore main mem_root - DBUG_PRINT("exit",("prepare query ready")); - DBUG_VOID_RETURN; + stmt.mem_root= thd->mem_root; + thd->mem_root= thd_root; // restore main mem_root + DBUG_RETURN(0); + +err: + stmt.mem_root= thd->mem_root; + free_prep_stmt(&stmt, free_free, (void*) 0); + thd->mem_root = thd_root; // restore main mem_root + DBUG_RETURN(1); } @@ -663,47 +670,166 @@ void mysql_com_prepare(THD *thd, char *packet, uint packet_length) execute the query */ -void mysql_com_execute(THD *thd) +void mysql_stmt_execute(THD *thd, char *packet) { - MEM_ROOT thd_root=thd->mem_root; - DBUG_ENTER("mysql_com_execute"); - DBUG_PRINT("enter", ("parameters : %ld", thd->param_count)); + ulong stmt_id= uint4korr(packet); + PREP_STMT *stmt; + DBUG_ENTER("mysql_stmt_execute"); - thd->mem_root = thd->con_root; - if (thd->param_count && setup_param_fields(thd, thd->lex.param_list)) + if (!(stmt=find_prepared_statement(thd, stmt_id, "execute"))) + { + send_error(thd); + DBUG_VOID_RETURN; + } + + /* Check if we got an error when sending long data */ + if (stmt->error_in_prepare) + { + send_error(thd); + DBUG_VOID_RETURN; + } + + if (stmt->param_count && setup_param_fields(thd, stmt)) DBUG_VOID_RETURN; - + + MEM_ROOT thd_root= thd->mem_root; + thd->mem_root = thd->con_root; if (!(specialflag & SPECIAL_NO_PRIOR)) my_pthread_setprio(pthread_self(),QUERY_PRIOR); - /* TODO: + /* + TODO: Also, have checks on basic executions such as mysql_insert(), mysql_delete(), mysql_update() and mysql_select() to not to have re-check on setup_* and other things .. */ - mysql_execute_command(); + mysql_execute_command(thd); if (!(specialflag & SPECIAL_NO_PRIOR)) - my_pthread_setprio(pthread_self(),WAIT_PRIOR); + my_pthread_setprio(pthread_self(), WAIT_PRIOR); - thd->mem_root = (MEM_ROOT )thd_root; - DBUG_PRINT("exit",("prepare-execute done!")); + thd->mem_root= thd_root; DBUG_VOID_RETURN; } + /* - Long data in pieces from client + Reset a prepared statement + + SYNOPSIS + mysql_stmt_reset() + thd Thread handle + packet Packet with stmt handle + + DESCRIPTION + This function is useful when one gets an error after calling + mysql_stmt_getlongdata() and one wants to reset the handle + so that one can call execute again. */ -void mysql_com_longdata(THD *thd) +void mysql_stmt_reset(THD *thd, char *packet) { - DBUG_ENTER("mysql_com_execute"); + ulong stmt_id= uint4korr(packet); + PREP_STMT *stmt; + DBUG_ENTER("mysql_stmt_reset"); - if(thd->param_count && setup_longdata(thd,thd->lex.param_list)) - DBUG_VOID_RETURN; - - send_ok(&thd->net,0,0);// ok status to client - DBUG_PRINT("exit",("longdata-buffering done!")); + if (!(stmt=find_prepared_statement(thd, stmt_id, "close"))) + { + send_error(thd); + DBUG_VOID_RETURN; + } + + stmt->error_in_prepare=0; + Item_param *item= stmt->param, *end= item + stmt->param_count; + + /* Free long data if used */ + if (stmt->long_data_used) + { + stmt->long_data_used= 0; + for (; item < end ; item++) + item->reset(); + } + DBUG_VOID_RETURN; +} + + +/* + Delete a prepared statement from memory +*/ + +void mysql_stmt_close(THD *thd, char *packet) +{ + ulong stmt_id= uint4korr(packet); + PREP_STMT *stmt; + DBUG_ENTER("mysql_stmt_close"); + + if (!(stmt=find_prepared_statement(thd, stmt_id, "close"))) + { + send_error(thd); + DBUG_VOID_RETURN; + } + /* Will call free_prep_stmt() */ + tree_delete(&thd->prepared_statements, (void*) stmt, NULL); + thd->last_prepared_stmt=0; DBUG_VOID_RETURN; } + +/* + Long data in pieces from client + + SYNOPSIS + mysql_stmt_get_longdata() + thd Thread handle + pos String to append + packet_length Length of string + + DESCRIPTION + Get a part of a long data. + To make the protocol efficient, we are not sending any return packages + here. + If something goes wrong, then we will send the error on 'execute' + + We assume that the client takes care of checking that all parts are sent + to the server. (No checking that we get a 'end of column' in the server) +*/ + +void mysql_stmt_get_longdata(THD *thd, char *pos, ulong packet_length) +{ + PREP_STMT *stmt; + DBUG_ENTER("mysql_stmt_get_longdata"); + + /* The following should never happen */ + if (packet_length < 9) + { + my_error(ER_WRONG_ARGUMENTS, MYF(0), "get_longdata"); + DBUG_VOID_RETURN; + } + + pos++; // skip command type at first position + ulong stmt_id= uint4korr(pos); + uint param_number= uint2korr(pos+4); + uint param_type= uint2korr(pos+6); + pos+=8; // Point to data + + if (!(stmt=find_prepared_statement(thd, stmt_id, "get_longdata"))) + { + /* + There is a chance that the client will never see this as + it doesn't expect an answer from this call... + */ + send_error(thd); + DBUG_VOID_RETURN; + } + + if (param_number >= stmt->param_count) + { + stmt->error_in_prepare=1; + stmt->last_errno=ER_WRONG_ARGUMENTS; + sprintf(stmt->last_error, ER(ER_WRONG_ARGUMENTS), "get_longdata"); + DBUG_VOID_RETURN; + } + stmt->param[param_number].set_longdata(pos, packet_length-9); + stmt->long_data_used= 1; + DBUG_VOID_RETURN; +} diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc index 049690eb318..a9ab1776e19 100644 --- a/sql/sql_rename.cc +++ b/sql/sql_rename.cc @@ -97,7 +97,7 @@ end: Query_log_event qinfo(thd, thd->query, thd->query_length); mysql_bin_log.write(&qinfo); } - send_ok(&thd->net); + send_ok(thd); } for (TABLE_LIST *table=table_list ; table != lock_table ; table=table->next) diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 628b1775778..03b840aebf9 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -283,11 +283,11 @@ binlog purge"; break; if (errmsg) { - send_error(&thd->net, 0, errmsg); + send_error(thd, 0, errmsg); return 1; } else - send_ok(&thd->net); + send_ok(thd); return 0; } @@ -372,7 +372,7 @@ impossible position"; We need to start a packet with something other than 255 to distiquish it from error */ - packet->set("\0", 1); + packet->set("\0", 1, system_charset_info); // if we are at the start of the log if (pos == BIN_LOG_HEADER_SIZE) @@ -383,7 +383,7 @@ impossible position"; my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG; goto err; } - packet->set("\0", 1); + packet->set("\0", 1, system_charset_info); } while (!net->error && net->vio != 0 && !thd->killed) @@ -418,7 +418,7 @@ impossible position"; goto err; } } - packet->set("\0", 1); + packet->set("\0", 1, system_charset_info); } /* TODO: now that we are logging the offset, check to make sure @@ -538,7 +538,7 @@ Increase max_allowed_packet on master"; goto err; } } - packet->set("\0", 1); + packet->set("\0", 1, system_charset_info); /* No need to net_flush because we will get to flush later when we hit EOF pretty quick @@ -593,7 +593,7 @@ Increase max_allowed_packet on master"; end_io_cache(&log); (void)my_close(file, MYF(MY_WME)); - send_eof(&thd->net); + send_eof(thd); thd->proc_info = "waiting to finalize termination"; pthread_mutex_lock(&LOCK_thread_count); thd->current_linfo = 0; @@ -615,15 +615,15 @@ Increase max_allowed_packet on master"; pthread_mutex_unlock(&LOCK_thread_count); if (file >= 0) (void) my_close(file, MYF(MY_WME)); - send_error(&thd->net, my_errno, errmsg); + send_error(thd, my_errno, errmsg); DBUG_VOID_RETURN; } int start_slave(THD* thd , MASTER_INFO* mi, bool net_report) { int slave_errno = 0; - if (!thd) thd = current_thd; - NET* net = &thd->net; + if (!thd) + thd = current_thd; int thread_mask; DBUG_ENTER("start_slave"); @@ -654,20 +654,21 @@ int start_slave(THD* thd , MASTER_INFO* mi, bool net_report) if (slave_errno) { if (net_report) - send_error(net, slave_errno); + send_error(thd, slave_errno); DBUG_RETURN(1); } else if (net_report) - send_ok(net); + send_ok(thd); DBUG_RETURN(0); } + int stop_slave(THD* thd, MASTER_INFO* mi, bool net_report ) { int slave_errno = 0; - if (!thd) thd = current_thd; - NET* net = &thd->net; + if (!thd) + thd = current_thd; if (check_access(thd, SUPER_ACL, any_db)) return 1; @@ -686,11 +687,11 @@ int stop_slave(THD* thd, MASTER_INFO* mi, bool net_report ) if (slave_errno) { if (net_report) - send_error(net, slave_errno); + send_error(thd, slave_errno); return 1; } else if (net_report) - send_ok(net); + send_ok(thd); return 0; } @@ -779,7 +780,7 @@ int change_master(THD* thd, MASTER_INFO* mi) restart_thread_mask, 1 /*skip lock*/))) { - send_error(&thd->net,error); + send_error(thd,error); unlock_slave_threads(mi); DBUG_RETURN(1); } @@ -788,7 +789,7 @@ int change_master(THD* thd, MASTER_INFO* mi) // TODO: see if needs re-write if (init_master_info(mi, master_info_file, relay_log_info_file, 0)) { - send_error(&thd->net, 0, "Could not initialize master info"); + send_error(thd, 0, "Could not initialize master info"); unlock_slave_threads(mi); DBUG_RETURN(1); } @@ -850,7 +851,7 @@ int change_master(THD* thd, MASTER_INFO* mi) 0 /* not only reset, but also reinit */, &errmsg)) { - net_printf(&thd->net, 0, "Failed purging old relay logs: %s",errmsg); + net_printf(thd, 0, "Failed purging old relay logs: %s",errmsg); DBUG_RETURN(1); } } @@ -864,7 +865,7 @@ int change_master(THD* thd, MASTER_INFO* mi) 0 /*no data lock*/, &msg)) { - net_printf(&thd->net,0,"Failed initializing relay log position: %s",msg); + net_printf(thd,0,"Failed initializing relay log position: %s",msg); unlock_slave_threads(mi); DBUG_RETURN(1); } @@ -890,9 +891,9 @@ int change_master(THD* thd, MASTER_INFO* mi) unlock_slave_threads(mi); thd->proc_info = 0; if (error) - send_error(&thd->net,error); + send_error(thd,error); else - send_ok(&thd->net); + send_ok(thd); DBUG_RETURN(0); } @@ -1010,12 +1011,12 @@ err: if (errmsg) { - net_printf(&thd->net, ER_ERROR_WHEN_EXECUTING_COMMAND, + net_printf(thd, ER_ERROR_WHEN_EXECUTING_COMMAND, "SHOW BINLOG EVENTS", errmsg); DBUG_RETURN(1); } - send_eof(&thd->net); + send_eof(thd); DBUG_RETURN(0); } @@ -1045,7 +1046,7 @@ int show_binlog_info(THD* thd) if (my_net_write(&thd->net, (char*)thd->packet.ptr(), packet->length())) DBUG_RETURN(-1); } - send_eof(&thd->net); + send_eof(thd); DBUG_RETURN(0); } @@ -1098,11 +1099,11 @@ int show_binlogs(THD* thd) goto err; } mysql_bin_log.unlock_index(); - send_eof(net); + send_eof(thd); return 0; err_with_msg: - send_error(net, 0, errmsg); + send_error(thd, ER_UNKNOWN_ERROR, errmsg); err: mysql_bin_log.unlock_index(); return 1; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 8a64fbf968c..2b737ab65d7 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -164,13 +164,7 @@ int handle_select(THD *thd, LEX *lex, select_result *result) for (TABLE_LIST *cursor= (TABLE_LIST *)sl->table_list.first; cursor; cursor=cursor->next) - { - if (cursor->do_redirect) // False if CUBE/ROLLUP - { - cursor->do_redirect=false; - cursor->table= ((TABLE_LIST*) cursor->table)->table; - } - } + cursor->table= ((TABLE_LIST*) cursor->table)->table; } } @@ -226,7 +220,7 @@ int JOIN::prepare(TABLE_LIST *tables_init, COND *conds_init, ORDER *order_init, ORDER *group_init, Item *having_init, - ORDER *proc_param_init, SELECT_LEX *select_lex, + ORDER *proc_param_init, SELECT_LEX *select, SELECT_LEX_UNIT *unit) { DBUG_ENTER("JOIN::prepare"); @@ -237,7 +231,8 @@ JOIN::prepare(TABLE_LIST *tables_init, having= having_init; proc_param= proc_param_init; tables_list= tables_init; - select->join= this; + select_lex= select; + select_lex->join= this; union_part= (unit->first_select()->next_select() != 0); /* Check that all tables, fields, conds and order are ok */ @@ -679,16 +674,16 @@ JOIN::exec() result->send_fields(fields_list,1); if (!having || having->val_int()) { - if (do_send_rows && result->send_data(fields_list)) - { - result->send_error(0,NullS); /* purecov: inspected */ - error=1; - } - else - error=(int) result->send_eof(); + if (do_send_rows && result->send_data(fields_list)) + { + result->send_error(0,NullS); /* purecov: inspected */ + error=1; + } + else + error=(int) result->send_eof(); } else - error=(int) result->send_eof(); + error=(int) result->send_eof(); } delete procedure; DBUG_VOID_RETURN; @@ -696,6 +691,7 @@ JOIN::exec() if (zero_result_cause) { + error=0; (void) return_zero_rows(this, result, tables_list, fields_list, tmp_table_param.sum_func_count != 0 && !group_list, @@ -739,7 +735,7 @@ JOIN::exec() thd->proc_info="Creating tmp table"; tmp_table_param.hidden_field_count= (all_fields.elements- - fields.elements); + fields_list.elements); if (!(exec_tmp_table = create_tmp_table(thd, &tmp_table_param, all_fields, ((!simple_group && !procedure && @@ -996,6 +992,8 @@ JOIN::exec() int JOIN::cleanup(THD *thd) { + DBUG_ENTER("JOIN::cleanup"); + lock=0; // It's faster to unlock later join_free(this); if (exec_tmp_table) @@ -1006,6 +1004,7 @@ JOIN::cleanup(THD *thd) for (SELECT_LEX_UNIT *unit= select_lex->first_inner_unit(); unit != 0; unit= unit->next_unit()) + { for (SELECT_LEX *sl= unit->first_select(); sl != 0; sl= sl->next_select()) @@ -1018,7 +1017,8 @@ JOIN::cleanup(THD *thd) sl->join= 0; } } - return error; + } + DBUG_RETURN(error); } int @@ -1044,7 +1044,7 @@ mysql_select(THD *thd, TABLE_LIST *tables, List<Item> &fields, COND *conds, goto err; } - if(join->global_optimize()) + if (join->global_optimize()) goto err; join->exec(); @@ -7276,7 +7276,8 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, { KEY *key_info=table->key_info+ tab->ref.key; item_list.push_back(new Item_string(key_info->name, - strlen(key_info->name))); + strlen(key_info->name), + system_charset_info)); item_list.push_back(new Item_int((int32) tab->ref.key_length)); for (store_key **ref=tab->ref.key_copy ; *ref ; ref++) { @@ -7416,5 +7417,5 @@ static void describe_info(JOIN *join, const char *info) packet->length(0); net_store_data(packet,info); if (!my_net_write(&thd->net,(char*) packet->ptr(),packet->length())) - send_eof(&thd->net); + send_eof(thd); } diff --git a/sql/sql_select.h b/sql/sql_select.h index f651f069c13..89dee2a4019 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -149,7 +149,8 @@ class TMP_TABLE_PARAM { } }; -class JOIN :public Sql_alloc{ +class JOIN :public Sql_alloc +{ public: JOIN_TAB *join_tab,**best_ref,**map2table; TABLE **table,**all_tables,*sort_by_table; @@ -222,6 +223,7 @@ class JOIN :public Sql_alloc{ !test(select_options & OPTION_FOUND_ROWS)), all_fields(fields), fields_list(fields), + error(0), select(0), exec_tmp_table(0), test_function_query(0), diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 5899fe86024..fb9db707c16 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB +/* Copyright (C) 2000 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 @@ -76,6 +76,8 @@ mysqld_show_dbs(THD *thd,const char *wild) if (mysql_find_files(thd,&files,NullS,mysql_data_home,wild,1)) DBUG_RETURN(1); List_iterator_fast<char> it(files); + + String *packet= &thd->packet; while ((file_name=it++)) { if (thd->master_access & (DB_ACLS | SHOW_DB_ACL) || @@ -83,19 +85,20 @@ mysqld_show_dbs(THD *thd,const char *wild) thd->priv_user, file_name) || (grant_option && !check_grant_db(thd, file_name))) { - thd->packet.length(0); - net_store_data(&thd->packet, thd->variables.convert_set, file_name); - if (my_net_write(&thd->net, (char*) thd->packet.ptr(), - thd->packet.length())) + packet->length(0); + net_store_data(packet, thd->variables.convert_set, file_name); + if (my_net_write(&thd->net, (char*) packet->ptr(), + packet->length())) DBUG_RETURN(-1); } } - send_eof(&thd->net); + send_eof(thd); DBUG_RETURN(0); } + /*************************************************************************** -** List all open tables in a database + List all open tables in a database ***************************************************************************/ int mysqld_show_open_tables(THD *thd,const char *wild) @@ -116,19 +119,20 @@ int mysqld_show_open_tables(THD *thd,const char *wild) if (!(open_list=list_open_tables(thd,wild)) && thd->fatal_error) DBUG_RETURN(-1); + String *packet= &thd->packet; for (; open_list ; open_list=open_list->next) { - thd->packet.length(0); - net_store_data(&thd->packet,convert, open_list->db); - net_store_data(&thd->packet,convert, open_list->table); - net_store_data(&thd->packet,open_list->in_use); - net_store_data(&thd->packet,open_list->locked); - if (my_net_write(&thd->net,(char*) thd->packet.ptr(),thd->packet.length())) + packet->length(0); + net_store_data(packet,convert, open_list->db); + net_store_data(packet,convert, open_list->table); + net_store_data(packet,open_list->in_use); + net_store_data(packet,open_list->locked); + if (my_net_write(&thd->net,(char*) packet->ptr(),packet->length())) { DBUG_RETURN(-1); } } - send_eof(&thd->net); + send_eof(thd); DBUG_RETURN(0); } @@ -160,14 +164,15 @@ int mysqld_show_tables(THD *thd,const char *db,const char *wild) if (mysql_find_files(thd,&files,db,path,wild,0)) DBUG_RETURN(-1); List_iterator_fast<char> it(files); + String *packet= &thd->packet; while ((file_name=it++)) { - thd->packet.length(0); - net_store_data(&thd->packet, thd->variables.convert_set, file_name); - if (my_net_write(&thd->net,(char*) thd->packet.ptr(),thd->packet.length())) + packet->length(0); + net_store_data(packet, thd->variables.convert_set, file_name); + if (my_net_write(&thd->net,(char*) packet->ptr(),packet->length())) DBUG_RETURN(-1); } - send_eof(&thd->net); + send_eof(thd); DBUG_RETURN(0); } @@ -175,15 +180,33 @@ int mysqld_show_tables(THD *thd,const char *db,const char *wild) ** 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"}, +struct show_table_type_st { + const char *type; + SHOW_COMP_OPTION *value; + const char *comment; +}; + + +SHOW_COMP_OPTION have_yes= SHOW_OPTION_YES; + +static struct show_table_type_st sys_table_types[]= +{ + {"MyISAM", &have_yes, + "Default type from 3.23 with great performance"}, + {"HEAP" , &have_yes, + "Hash based, stored in memory, useful for temporary tables"}, + {"MERGE", &have_yes, + "Collection of identical MyISAM tables"}, + {"ISAM", &have_isam, + "Obsolete table type; Is replaced by MyISAM"}, + {"InnoDB", &have_innodb, + "Supports transactions, row-level locking and foreign keys"}, + {"BDB", &have_berkeley_db, + "Supports transactions and page-level locking"}, + {NullS, NULL, NullS} }; + int mysqld_show_table_types(THD *thd) { List<Item> field_list; @@ -191,76 +214,68 @@ int mysqld_show_table_types(THD *thd) 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)); + field_list.push_back(new Item_empty_string("Comment",80)); 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); - } + const char *default_type_name= ha_table_typelib.type_names[thd->variables.table_type]; - for (; i < sizeof(sys_table_types)/sizeof(sys_table_types[0]); i++) + show_table_type_st *types; + String *packet= &thd->packet; + for (types= sys_table_types; types->type; types++) { - 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())) + packet->length(0); + net_store_data(packet, types->type); + const char *option_name= show_comp_option_name[(int) *types->value]; + + if (*types->value == SHOW_OPTION_YES && + !strcasecmp(default_type_name, types->type)) + option_name= "DEFAULT"; + net_store_data(packet, option_name); + net_store_data(packet, types->comment); + if (my_net_write(&thd->net, (char*) packet->ptr(), packet->length())) DBUG_RETURN(-1); } - send_eof(&thd->net); + send_eof(thd); DBUG_RETURN(0); } + /*************************************************************************** -** List all privileges supported + 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"}, +struct show_privileges_st { + const char *privilege; + const char *context; + const char *comment; }; + +/* + TODO: Update with new privileges +*/ +static struct show_privileges_st sys_privileges[]= +{ + {"Select", "Tables", "To retrieve rows from table"}, + {"Insert", "Tables", "To insert data into tables"}, + {"Update", "Tables", "To update existing rows "}, + {"Delete", "Tables", "To delete existing rows"}, + {"Index", "Tables", "To create or drop indexes"}, + {"Alter", "Tables", "To alter the table"}, + {"Create", "Databases,Tables,Indexes", "To create new databases and tables"}, + {"Drop", "Databases,Tables", "To drop databases and tables"}, + {"Grant", "Databases,Tables", "To give to other users those privileges you possess"}, + {"References", "Databases,Tables", "To have references on tables"}, + {"Reload", "Server Admin", "To reload or refresh tables, logs and privileges"}, + {"Shutdown","Server Admin", "To shutdown the server"}, + {"Process", "Server Admin", "To view the plain text of currently executing queries"}, + {"File", "File access on server", "To read and write files on the server"}, + {NullS, NullS, NullS} +}; + + int mysqld_show_privileges(THD *thd) { List<Item> field_list; @@ -273,43 +288,48 @@ int mysqld_show_privileges(THD *thd) if (send_fields(thd,field_list,1)) DBUG_RETURN(1); - for (uint i=0; i < sizeof(sys_privileges)/sizeof(sys_privileges[0]); i++) + show_privileges_st *privilege= sys_privileges; + String *packet= &thd->packet; + for (privilege= sys_privileges; privilege->privilege ; privilege++) { - 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())) + packet->length(0); + net_store_data(packet,privilege->privilege); + net_store_data(packet,privilege->context); + net_store_data(packet,privilege->comment); + if (my_net_write(&thd->net,(char*) packet->ptr(),packet->length())) DBUG_RETURN(-1); } - send_eof(&thd->net); + send_eof(thd); DBUG_RETURN(0); } /*************************************************************************** -** List all column types + List all column types ***************************************************************************/ -#if 0 -struct show_column_type_st { +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; + 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; }; -#endif -static struct show_column_type_st sys_column_types[]= { + +/* TODO: Add remaning types */ + +static struct show_column_type_st sys_column_types[]= +{ {"tinyint", 1, "-128", "127", 0, 0, "YES", "YES", "NO", "YES", "YES", "NO", "NULL,0", @@ -343,30 +363,33 @@ int mysqld_show_column_types(THD *thd) if (send_fields(thd,field_list,1)) DBUG_RETURN(1); + /* TODO: Change the loop to not use 'i' */ + String *packet= &thd->packet; for (uint i=0; i < sizeof(sys_column_types)/sizeof(sys_column_types[0]); i++) { - 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())) + packet->length(0); + net_store_data(packet,sys_column_types[i].type); + net_store_data(packet,(longlong)sys_column_types[i].size); + net_store_data(packet,sys_column_types[i].min_value); + net_store_data(packet,sys_column_types[i].max_value); + net_store_data(packet,(uint32)sys_column_types[i].precision); + net_store_data(packet,(uint32)sys_column_types[i].scale); + net_store_data(packet,sys_column_types[i].nullable); + net_store_data(packet,sys_column_types[i].auto_increment); + net_store_data(packet,sys_column_types[i].unsigned_attr); + net_store_data(packet,sys_column_types[i].zerofill); + net_store_data(packet,sys_column_types[i].searchable); + net_store_data(packet,sys_column_types[i].case_sensitivity); + net_store_data(packet,sys_column_types[i].default_value); + net_store_data(packet,sys_column_types[i].comment); + if (my_net_write(&thd->net,(char*) packet->ptr(),packet->length())) DBUG_RETURN(-1); } - send_eof(&thd->net); + send_eof(thd); DBUG_RETURN(0); } + static int mysql_find_files(THD *thd,List<char> *files, const char *db,const char *path, const char *wild, bool dir) @@ -441,8 +464,9 @@ mysql_find_files(THD *thd,List<char> *files, const char *db,const char *path, DBUG_RETURN(0); } + /*************************************************************************** -** Extended version of mysqld_show_tables + Extended version of mysqld_show_tables ***************************************************************************/ int mysqld_extend_show_tables(THD *thd,const char *db,const char *wild) @@ -459,7 +483,6 @@ int mysqld_extend_show_tables(THD *thd,const char *db,const char *wild) (void) sprintf(path,"%s/%s",mysql_data_home,db); (void) unpack_dirname(path,path); -//,default_charset_info field_list.push_back(item=new Item_empty_string("Name",NAME_LEN)); item->maybe_null=1; field_list.push_back(item=new Item_empty_string("Type",10)); @@ -612,14 +635,13 @@ int mysqld_extend_show_tables(THD *thd,const char *db,const char *wild) packet->length())) DBUG_RETURN(-1); } - send_eof(&thd->net); + send_eof(thd); DBUG_RETURN(0); } - /*************************************************************************** -** List all columns in a table + List all columns in a table ***************************************************************************/ int @@ -637,7 +659,7 @@ mysqld_show_fields(THD *thd, TABLE_LIST *table_list,const char *wild, if (!(table = open_ltable(thd, table_list, TL_UNLOCK))) { - send_error(&thd->net); + send_error(thd); DBUG_RETURN(1); } file=table->file; @@ -742,10 +764,11 @@ mysqld_show_fields(THD *thd, TABLE_LIST *table_list,const char *wild, } } } - send_eof(&thd->net); + send_eof(thd); DBUG_RETURN(0); } + int mysqld_show_create(THD *thd, TABLE_LIST *table_list) { @@ -758,7 +781,7 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list) /* Only one table for now */ if (!(table = open_ltable(thd, table_list, TL_UNLOCK))) { - send_error(&thd->net); + send_error(thd); DBUG_RETURN(1); } @@ -809,7 +832,7 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list) if (my_net_write(&thd->net, (char*)packet->ptr(), packet->length())) DBUG_RETURN(1); } - send_eof(&thd->net); + send_eof(thd); DBUG_RETURN(0); } @@ -832,7 +855,7 @@ mysqld_show_logs(THD *thd) DBUG_RETURN(-1); #endif - send_eof(&thd->net); + send_eof(thd); DBUG_RETURN(0); } @@ -849,7 +872,7 @@ mysqld_show_keys(THD *thd, TABLE_LIST *table_list) if (!(table = open_ltable(thd, table_list, TL_UNLOCK))) { - send_error(&thd->net); + send_error(thd); DBUG_RETURN(1); } @@ -933,14 +956,14 @@ mysqld_show_keys(THD *thd, TABLE_LIST *table_list) DBUG_RETURN(1); /* purecov: inspected */ } } - send_eof(&thd->net); + send_eof(thd); DBUG_RETURN(0); } /**************************************************************************** -** Return only fields for API mysql_list_fields -** Use "show table wildcard" in mysql instead of this + Return only fields for API mysql_list_fields + Use "show table wildcard" in mysql instead of this ****************************************************************************/ void @@ -952,7 +975,7 @@ mysqld_list_fields(THD *thd, TABLE_LIST *table_list, const char *wild) if (!(table = open_ltable(thd, table_list, TL_UNLOCK))) { - send_error(&thd->net); + send_error(thd); DBUG_VOID_RETURN; } List<Item> field_list; @@ -971,6 +994,7 @@ mysqld_list_fields(THD *thd, TABLE_LIST *table_list, const char *wild) DBUG_VOID_RETURN; } + int mysqld_dump_create_info(THD *thd, TABLE *table, int fd) { @@ -978,7 +1002,7 @@ mysqld_dump_create_info(THD *thd, TABLE *table, int fd) DBUG_ENTER("mysqld_dump_create_info"); DBUG_PRINT("enter",("table: %s",table->real_name)); - String* packet = &thd->packet; + String *packet = &thd->packet; packet->length(0); if (store_create_info(thd,table,packet)) DBUG_RETURN(-1); @@ -1000,6 +1024,7 @@ mysqld_dump_create_info(THD *thd, TABLE *table, int fd) DBUG_RETURN(0); } + static void append_identifier(THD *thd, String *packet, const char *name) { @@ -1015,6 +1040,7 @@ append_identifier(THD *thd, String *packet, const char *name) } } + static int store_create_info(THD *thd, TABLE *table, String *packet) { @@ -1215,8 +1241,8 @@ store_create_info(THD *thd, TABLE *table, String *packet) /**************************************************************************** -** Return info about all processes -** returns for each thread: thread id, user, host, db, command, info + Return info about all processes + returns for each thread: thread id, user, host, db, command, info ****************************************************************************/ class thread_info :public ilink { @@ -1357,7 +1383,7 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose) if (my_net_write(&thd->net,(char*) packet->ptr(),packet->length())) break; /* purecov: inspected */ } - send_eof(&thd->net); + send_eof(thd); DBUG_VOID_RETURN; } @@ -1372,7 +1398,7 @@ int mysqld_show_charsets(THD *thd, const char *wild) char buff[8192]; String packet2(buff,sizeof(buff),default_charset_info); List<Item> field_list; - CONVERT *convert=thd->convert_set; + CONVERT *convert=thd->variables.convert_set; CHARSET_INFO *cs; DBUG_ENTER("mysqld_show_charsets"); @@ -1401,7 +1427,7 @@ int mysqld_show_charsets(THD *thd, const char *wild) goto err; } } - send_eof(&thd->net); + send_eof(thd); DBUG_RETURN(0); err: DBUG_RETURN(1); @@ -1428,7 +1454,7 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables, for (; variables->name; variables++) { if (!(wild && wild[0] && wild_case_compare(system_charset_info, - variables[i].name,wild))) + variables->name,wild))) { packet2.length(0); net_store_data(&packet2,convert,variables->name); @@ -1461,9 +1487,7 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables, case SHOW_HAVE: { SHOW_COMP_OPTION tmp= *(SHOW_COMP_OPTION*) value; - net_store_data(&packet2, (tmp == SHOW_OPTION_NO ? "NO" : - tmp == SHOW_OPTION_YES ? "YES" : - "DISABLED")); + net_store_data(&packet2, show_comp_option_name[(int) tmp]); break; } case SHOW_CHAR: @@ -1663,7 +1687,7 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables, } pthread_mutex_unlock(&LOCK_status); /* pthread_mutex_unlock(&THR_LOCK_keycache); */ - send_eof(&thd->net); + send_eof(thd); DBUG_RETURN(0); err: diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 6b24999763b..fb0815a1a26 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -82,7 +82,7 @@ int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists) if (error) DBUG_RETURN(-1); - send_ok(&thd->net); + send_ok(thd); DBUG_RETURN(0); } @@ -305,8 +305,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, DBUG_RETURN(-1); } - - for(field_no=0; (sql_field=it++) ; field_no++) + for (field_no=0; (sql_field=it++) ; field_no++) { /* Don't pack keys in old tables if the user has requested this */ if ((sql_field->flags & BLOB_FLAG) || @@ -317,28 +316,35 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, } if (!(sql_field->flags & NOT_NULL_FLAG)) null_fields++; - for(dup_no=0; (dup_field=it2++) != sql_field; dup_no++) + + /* Check if we have used the same field name before */ + for (dup_no=0; (dup_field=it2++) != sql_field; dup_no++) { if (my_strcasecmp(system_charset_info, sql_field->field_name, dup_field->field_name) == 0) { - if (field_no<select_field_pos || dup_no>=select_field_pos) + /* + If this was a CREATE ... SELECT statement, accept a field + redefinition if we are changing a field in the SELECT part + */ + if (field_no < select_field_pos || dup_no >= select_field_pos) { my_error(ER_DUP_FIELDNAME,MYF(0),sql_field->field_name); DBUG_RETURN(-1); } else { - sql_field->length=dup_field->length; - sql_field->decimals=dup_field->decimals; - sql_field->flags=dup_field->flags; - sql_field->pack_length=dup_field->pack_length; - sql_field->unireg_check=dup_field->unireg_check; - sql_field->sql_type=dup_field->sql_type; - it2.remove(); - select_field_pos--; - break; + /* Field redefined */ + sql_field->length= dup_field->length; + sql_field->decimals= dup_field->decimals; + sql_field->flags= dup_field->flags; + sql_field->pack_length= dup_field->pack_length; + sql_field->unireg_check= dup_field->unireg_check; + sql_field->sql_type= dup_field->sql_type; + it2.remove(); // Remove first (create) definition + select_field_pos--; + break; } } } @@ -749,7 +755,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, create_info->create_statement = thd->query; create_info->table_options=db_options; - if (rea_create_table(path, create_info, fields, key_count, + if (rea_create_table(thd, path, create_info, fields, key_count, key_info_buffer)) { /* my_error(ER_CANT_CREATE_TABLE,MYF(0),table_name,my_errno); */ @@ -825,7 +831,7 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info, TABLE tmp_table; // Used during 'create_field()' TABLE *table; tmp_table.table_name=0; - uint select_field_count=0; + uint select_field_count= items->elements; DBUG_ENTER("create_table_from_items"); /* Add selected items to field list */ @@ -859,7 +865,6 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info, (Field*) 0)))) DBUG_RETURN(0); extra_fields->push_back(cr_field); - select_field_count++; } /* create and lock table */ /* QQ: This should be done atomic ! */ @@ -1271,7 +1276,7 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables, goto err; } - send_eof(&thd->net); + send_eof(thd); DBUG_RETURN(0); err: close_thread_tables(thd); // Shouldn't be needed @@ -1476,7 +1481,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, Query_log_event qinfo(thd, thd->query, thd->query_length); mysql_bin_log.write(&qinfo); } - send_ok(&thd->net); + send_ok(thd); } DBUG_RETURN(error); } @@ -1994,7 +1999,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, end_temporary: sprintf(tmp_name,ER(ER_INSERT_INFO),(ulong) (copied+deleted), (ulong) deleted, thd->cuted_fields); - send_ok(&thd->net,copied+deleted,0L,tmp_name); + send_ok(thd,copied+deleted,0L,tmp_name); thd->some_tables_deleted=0; DBUG_RETURN(0); diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc index 225c0ea26a4..893f0838a7f 100644 --- a/sql/sql_udf.cc +++ b/sql/sql_udf.cc @@ -342,7 +342,7 @@ int mysql_create_function(THD *thd,udf_func *udf) if (!initialized) { - send_error(&thd->net, ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES)); + send_error(thd, ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES)); DBUG_RETURN(1); } @@ -353,19 +353,19 @@ int mysql_create_function(THD *thd,udf_func *udf) */ if (strchr(udf->dl, '/')) { - send_error(&thd->net, ER_UDF_NO_PATHS,ER(ER_UDF_NO_PATHS)); + send_error(thd, ER_UDF_NO_PATHS,ER(ER_UDF_NO_PATHS)); DBUG_RETURN(1); } if (udf->name_length > NAME_LEN) { - net_printf(&thd->net, ER_TOO_LONG_IDENT,udf->name); + net_printf(thd, ER_TOO_LONG_IDENT,udf->name); DBUG_RETURN(1); } pthread_mutex_lock(&THR_LOCK_udf); if (hash_search(&udf_hash,(byte*) udf->name, udf->name_length)) { - net_printf(&thd->net, ER_UDF_EXISTS, udf->name); + net_printf(thd, ER_UDF_EXISTS, udf->name); goto err; } if (!(dl = find_udf_dl(udf->dl))) @@ -374,7 +374,7 @@ int mysql_create_function(THD *thd,udf_func *udf) { DBUG_PRINT("error",("dlopen of %s failed, error: %d (%s)", udf->dl,errno,dlerror())); - net_printf(&thd->net, ER_CANT_OPEN_LIBRARY, udf->dl, errno, dlerror()); + net_printf(thd, ER_CANT_OPEN_LIBRARY, udf->dl, errno, dlerror()); goto err; } new_dl=1; @@ -384,7 +384,7 @@ int mysql_create_function(THD *thd,udf_func *udf) if (udf->func == NULL) { - net_printf(&thd->net, ER_CANT_FIND_DL_ENTRY, udf->name); + net_printf(thd, ER_CANT_FIND_DL_ENTRY, udf->name); goto err; } udf->name=strdup_root(&mem,udf->name); @@ -392,7 +392,7 @@ int mysql_create_function(THD *thd,udf_func *udf) if (!udf->name || !udf->dl || !(u_d=add_udf(udf->name,udf->returns,udf->dl,udf->type))) { - send_error(&thd->net,0); // End of memory + send_error(thd,0); // End of memory goto err; } u_d->dlhandle = dl; @@ -422,7 +422,7 @@ int mysql_create_function(THD *thd,udf_func *udf) close_thread_tables(thd); if (error) { - net_printf(&thd->net, ER_ERROR_ON_WRITE, "func@mysql",error); + net_printf(thd, ER_ERROR_ON_WRITE, "func@mysql",error); del_udf(u_d); goto err; } @@ -445,13 +445,13 @@ int mysql_drop_function(THD *thd,const char *udf_name) DBUG_ENTER("mysql_drop_function"); if (!initialized) { - send_error(&thd->net, ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES)); + send_error(thd, ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES)); DBUG_RETURN(1); } pthread_mutex_lock(&THR_LOCK_udf); if (!(udf=(udf_func*) hash_search(&udf_hash,(byte*) udf_name, (uint) strlen(udf_name)))) { - net_printf(&thd->net, ER_FUNCTION_NOT_DEFINED, udf_name); + net_printf(thd, ER_FUNCTION_NOT_DEFINED, udf_name); goto err; } del_udf(udf); diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 51f278536de..8244384cc94 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -242,7 +242,7 @@ bool select_union::flush() if ((error=table->file->extra(HA_EXTRA_NO_CACHE))) { table->file->print_error(error,MYF(0)); - ::send_error(&thd->net); + ::send_error(thd); return 1; } return 0; diff --git a/sql/sql_update.cc b/sql/sql_update.cc index f0ca5ad6c7b..ccd4439a9d2 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -127,7 +127,7 @@ int mysql_update(THD *thd, { DBUG_RETURN(-1); // Error in where } - send_ok(&thd->net); // No matching records + send_ok(thd); // No matching records DBUG_RETURN(0); } /* If running in safe sql mode, don't allow updates without keys */ @@ -138,7 +138,7 @@ int mysql_update(THD *thd, { delete select; table->time_stamp=save_time_stamp; - send_error(&thd->net,ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE); + send_error(thd,ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE); DBUG_RETURN(1); } } @@ -329,13 +329,13 @@ int mysql_update(THD *thd, delete select; if (error >= 0) - send_error(&thd->net,thd->killed ? ER_SERVER_SHUTDOWN : 0); /* purecov: inspected */ + send_error(thd,thd->killed ? ER_SERVER_SHUTDOWN : 0); /* purecov: inspected */ else { char buff[80]; sprintf(buff,ER(ER_UPDATE_INFO), (long) found, (long) updated, (long) thd->cuted_fields); - send_ok(&thd->net, + send_ok(thd, (thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated, thd->insert_id_used ? thd->insert_id() : 0L,buff); DBUG_PRINT("info",("%d records updated",updated)); @@ -439,7 +439,7 @@ multi_update::prepare(List<Item> &values, SELECT_LEX_UNIT *u) } if (!table_ref) { - net_printf(&thd->net, ER_NOT_SUPPORTED_YET, "JOIN SYNTAX WITH MULTI-TABLE UPDATES"); + net_printf(thd, ER_NOT_SUPPORTED_YET, "JOIN SYNTAX WITH MULTI-TABLE UPDATES"); DBUG_RETURN(1); } else @@ -447,7 +447,7 @@ multi_update::prepare(List<Item> &values, SELECT_LEX_UNIT *u) } if (!num_updated) { - net_printf(&thd->net, ER_NOT_SUPPORTED_YET, "SET CLAUSE MUST CONTAIN TABLE.FIELD REFERENCE"); + net_printf(thd, ER_NOT_SUPPORTED_YET, "SET CLAUSE MUST CONTAIN TABLE.FIELD REFERENCE"); DBUG_RETURN(1); } @@ -662,7 +662,7 @@ bool multi_update::send_data(List<Item> &values) void multi_update::send_error(uint errcode,const char *err) { /* First send error what ever it is ... */ - ::send_error(&thd->net,errcode,err); + ::send_error(thd,errcode,err); /* reset used flags */ // update_tables->table->no_keyread=0; @@ -821,7 +821,7 @@ bool multi_update::send_eof() { query_cache_invalidate3(thd, update_tables, 1); } - ::send_ok(&thd->net, + ::send_ok(thd, (thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated, thd->insert_id_used ? thd->insert_id() : 0L,buff); } diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 8571cb9af6d..d9662f25c1b 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -26,6 +26,7 @@ #include "slave.h" #include "sql_acl.h" #include "lex_symbol.h" +#include "item_create.h" #include <myisam.h> #include <myisammrg.h> @@ -356,9 +357,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token COMPRESSED_SYM %token ERRORS -%token SQL_ERROR_COUNT %token WARNINGS -%token SQL_WARNING_COUNT %token BIGINT %token BLOB_SYM @@ -642,7 +641,7 @@ query: if (!thd->bootstrap && (!(thd->lex.select_lex.options & OPTION_FOUND_COMMENT))) { - send_error(¤t_thd->net,ER_EMPTY_QUERY); + send_error(current_thd,ER_EMPTY_QUERY); YYABORT; } else @@ -1128,7 +1127,7 @@ charset: { if (!(Lex->charset=get_charset_by_name($1.str,MYF(0)))) { - net_printf(¤t_thd->net,ER_UNKNOWN_CHARACTER_SET,$1.str); + net_printf(current_thd,ER_UNKNOWN_CHARACTER_SET,$1.str); YYABORT; } }; @@ -1690,7 +1689,7 @@ expr_expr: { if (!(Lex->charset=get_charset_by_name($3.str,MYF(0)))) { - net_printf(¤t_thd->net,ER_UNKNOWN_CHARACTER_SET,$3.str); + net_printf(current_thd,ER_UNKNOWN_CHARACTER_SET,$3.str); YYABORT; } $$= new Item_func_set_collation($1,Lex->charset); @@ -1921,9 +1920,8 @@ simple_expr: { $$= new Item_func_interval($3,* $5); } | LAST_INSERT_ID '(' ')' { - $$= new Item_int((char*) "last_insert_id()", - current_thd->insert_id(),21); - current_thd->safe_to_cache_query=0; + $$= get_system_var(OPT_SESSION, "last_insert_id", 14, + "last_insert_id()"); } | LAST_INSERT_ID '(' expr ')' { @@ -2409,7 +2407,7 @@ olap_opt: LEX *lex=Lex; lex->olap = true; lex->select->olap= CUBE_TYPE; - net_printf(&lex->thd->net, ER_NOT_SUPPORTED_YET, "CUBE"); + net_printf(lex->thd, ER_NOT_SUPPORTED_YET, "CUBE"); YYABORT; /* To be deleted in 4.1 */ } | WITH ROLLUP_SYM @@ -2417,7 +2415,7 @@ olap_opt: LEX *lex=Lex; lex->olap = true; lex->select->olap= ROLLUP_TYPE; - net_printf(&lex->thd->net, ER_NOT_SUPPORTED_YET, "ROLLUP"); + net_printf(lex->thd, ER_NOT_SUPPORTED_YET, "ROLLUP"); YYABORT; /* To be deleted in 4.1 */ } ; @@ -2436,12 +2434,12 @@ order_clause: LEX *lex=Lex; if (lex->sql_command == SQLCOM_MULTI_UPDATE) { - net_printf(&lex->thd->net, ER_WRONG_USAGE, "UPDATE", "ORDER BY"); + net_printf(lex->thd, ER_WRONG_USAGE, "UPDATE", "ORDER BY"); YYABORT; } if (lex->select->olap != UNSPECIFIED_OLAP_TYPE) { - net_printf(&lex->thd->net, ER_WRONG_USAGE, + net_printf(lex->thd, ER_WRONG_USAGE, "CUBE/ROLLUP", "ORDER BY"); YYABORT; @@ -2467,7 +2465,7 @@ limit_clause: LEX *lex=Lex; if (lex->select->olap != UNSPECIFIED_OLAP_TYPE) { - net_printf(&lex->thd->net, ER_WRONG_USAGE, "CUBE/ROLLUP", + net_printf(lex->thd, ER_WRONG_USAGE, "CUBE/ROLLUP", "LIMIT"); YYABORT; } @@ -2480,7 +2478,7 @@ limit_clause: LEX *lex=Lex; if (lex->select->olap != UNSPECIFIED_OLAP_TYPE) { - net_printf(&lex->thd->net, ER_WRONG_USAGE, "CUBE/ROLLUP", + net_printf(lex->thd, ER_WRONG_USAGE, "CUBE/ROLLUP", "LIMIT"); YYABORT; } @@ -2495,7 +2493,7 @@ delete_limit_clause: LEX *lex=Lex; if (lex->sql_command == SQLCOM_MULTI_UPDATE) { - net_printf(&lex->thd->net, ER_WRONG_USAGE, "DELETE", "LIMIT"); + net_printf(lex->thd, ER_WRONG_USAGE, "DELETE", "LIMIT"); YYABORT; } lex->select->select_limit= HA_POS_ERROR; @@ -2935,9 +2933,9 @@ show_param: lex->sql_command= SQLCOM_SHOW_PRIVILEGES; } | COUNT_SYM '(' '*' ')' WARNINGS - { Lex->sql_command = SQLCOM_SHOW_WARNS_COUNT;} + { (void) create_select_for_variable("warning_count"); } | COUNT_SYM '(' '*' ')' ERRORS - { Lex->sql_command = SQLCOM_SHOW_ERRORS_COUNT;} + { (void) create_select_for_variable("error_count"); } | WARNINGS {Select->offset_limit=0L;} limit_clause { Lex->sql_command = SQLCOM_SHOW_WARNS;} | ERRORS {Select->offset_limit=0L;} limit_clause @@ -3103,7 +3101,7 @@ kill: LEX *lex=Lex; if ($2->fix_fields(lex->thd, 0, &$2)) { - send_error(&lex->thd->net, ER_SET_CONSTANTS_ONLY); + send_error(lex->thd, ER_SET_CONSTANTS_ONLY); YYABORT; } lex->sql_command=SQLCOM_KILL; @@ -3218,10 +3216,11 @@ text_string: param_marker: '?' { - if(current_thd->prepare_command) + LEX *lex=Lex; + if (current_thd->prepare_command) { - Lex->param_list.push_back($$=new Item_param()); - current_thd->param_count++; + lex->param_list.push_back($$=new Item_param()); + lex->param_count++; } else { @@ -3602,8 +3601,8 @@ text_or_password: set_expr_or_default: expr { $$=$1; } | DEFAULT { $$=0; } - | ON { $$=new Item_string("ON",2); } - | ALL { $$=new Item_string("ALL",3); } + | ON { $$=new Item_string("ON", 2, system_charset_info); } + | ALL { $$=new Item_string("ALL", 3, system_charset_info); } ; @@ -3769,7 +3768,7 @@ require_list_element: SUBJECT_SYM TEXT_STRING LEX *lex=Lex; if (lex->x509_subject) { - net_printf(&lex->thd->net,ER_DUP_ARGUMENT, "SUBJECT"); + net_printf(lex->thd,ER_DUP_ARGUMENT, "SUBJECT"); YYABORT; } lex->x509_subject=$2.str; @@ -3779,7 +3778,7 @@ require_list_element: SUBJECT_SYM TEXT_STRING LEX *lex=Lex; if (lex->x509_issuer) { - net_printf(&lex->thd->net,ER_DUP_ARGUMENT, "ISSUER"); + net_printf(lex->thd,ER_DUP_ARGUMENT, "ISSUER"); YYABORT; } lex->x509_issuer=$2.str; @@ -3789,7 +3788,7 @@ require_list_element: SUBJECT_SYM TEXT_STRING LEX *lex=Lex; if (lex->ssl_cipher) { - net_printf(&lex->thd->net,ER_DUP_ARGUMENT, "CIPHER"); + net_printf(lex->thd,ER_DUP_ARGUMENT, "CIPHER"); YYABORT; } lex->ssl_cipher=$2.str; @@ -3805,7 +3804,7 @@ opt_table: lex->grant = DB_ACLS & ~GRANT_ACL; else if (lex->columns.elements) { - send_error(&lex->thd->net,ER_ILLEGAL_GRANT_FOR_TABLE); + send_error(lex->thd,ER_ILLEGAL_GRANT_FOR_TABLE); YYABORT; } } @@ -3817,7 +3816,7 @@ opt_table: lex->grant = DB_ACLS & ~GRANT_ACL; else if (lex->columns.elements) { - send_error(&lex->thd->net,ER_ILLEGAL_GRANT_FOR_TABLE); + send_error(lex->thd,ER_ILLEGAL_GRANT_FOR_TABLE); YYABORT; } } @@ -3829,7 +3828,7 @@ opt_table: lex->grant= GLOBAL_ACLS & ~GRANT_ACL; else if (lex->columns.elements) { - send_error(&lex->thd->net,ER_ILLEGAL_GRANT_FOR_TABLE); + send_error(lex->thd,ER_ILLEGAL_GRANT_FOR_TABLE); YYABORT; } } @@ -3977,15 +3976,15 @@ union_list: if (lex->exchange) { /* Only the last SELECT can have INTO...... */ - net_printf(&lex->thd->net, ER_WRONG_USAGE, "UNION", "INTO"); + net_printf(lex->thd, ER_WRONG_USAGE, "UNION", "INTO"); YYABORT; } if (lex->select->linkage == GLOBAL_OPTIONS_TYPE) { - send_error(&lex->thd->net, ER_SYNTAX_ERROR); + send_error(lex->thd, ER_SYNTAX_ERROR); YYABORT; } - if (mysql_new_select(lex)) + if (mysql_new_select(lex, 0)) YYABORT; lex->select->linkage=UNION_TYPE; } @@ -4003,7 +4002,7 @@ optional_order_or_limit: LEX *lex=Lex; if (!lex->select->braces) { - send_error(&lex->thd->net, ER_SYNTAX_ERROR); + send_error(lex->thd, ER_SYNTAX_ERROR); YYABORT; } lex->select->master_unit()->global_parameters= @@ -4013,7 +4012,7 @@ optional_order_or_limit: SELECT_LEX fields always check linkage type. */ lex->select= (SELECT_LEX*)lex->select->master_unit(); - lex->select->select_limit=lex->thd->default_select_limit; + lex->select->select_limit=lex->thd->variables.select_limit; } opt_order_clause limit_clause ; diff --git a/sql/structs.h b/sql/structs.h index c2ad4ef527e..7873de4db63 100644 --- a/sql/structs.h +++ b/sql/structs.h @@ -148,36 +148,18 @@ enum SHOW_TYPE }; enum SHOW_COMP_OPTION { SHOW_OPTION_YES, SHOW_OPTION_NO, SHOW_OPTION_DISABLED}; + +extern const char *show_comp_option_name[]; + typedef int *(*update_var)(THD *, struct show_var_st *); + typedef struct show_var_st { const char *name; char *value; SHOW_TYPE type; } SHOW_VAR; -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 { char *str; diff --git a/sql/table.cc b/sql/table.cc index 3e41da73109..2cdd62001f1 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -493,7 +493,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, if (field->key_length() == key_part->length && field->type() != FIELD_TYPE_BLOB) { - if ((index_flags & HA_HAVE_KEY_READ_ONLY) && + if ((index_flags & HA_KEY_READ_ONLY) && (field->key_type() != HA_KEYTYPE_TEXT || (!(ha_option & HA_KEY_READ_WRONG_STR) && !(keyinfo->flags & HA_FULLTEXT)))) @@ -1141,7 +1141,7 @@ bool check_db_name(const char *name) return 1; name++; } - return (uint) (name - start) > NAME_LEN; + return (uint) (name - start) > NAME_LEN || name == start; } diff --git a/sql/uniques.cc b/sql/uniques.cc index 60905567ba0..ed256a4b791 100644 --- a/sql/uniques.cc +++ b/sql/uniques.cc @@ -53,7 +53,8 @@ Unique::Unique(qsort_cmp2 comp_func, void * comp_func_fixed_arg, :max_in_memory_size(max_in_memory_size_arg),elements(0) { my_b_clear(&file); - init_tree(&tree, max_in_memory_size / 16, 0, size, comp_func, 0, NULL, comp_func_fixed_arg); + init_tree(&tree, max_in_memory_size / 16, 0, size, comp_func, 0, NULL, + comp_func_fixed_arg); /* If the following fail's the next add will also fail */ my_init_dynamic_array(&file_ptrs, sizeof(BUFFPEK), 16, 16); max_elements= max_in_memory_size / ALIGN_SIZE(sizeof(TREE_ELEMENT)+size); diff --git a/sql/unireg.cc b/sql/unireg.cc index 8db9b871a39..344583b56f1 100644 --- a/sql/unireg.cc +++ b/sql/unireg.cc @@ -46,7 +46,7 @@ static bool make_empty_rec(int file, enum db_type table_type, uint reclength,uint null_fields); -int rea_create_table(my_string file_name, +int rea_create_table(THD *thd, my_string file_name, HA_CREATE_INFO *create_info, List<create_field> &create_fields, uint keys, KEY *key_info) @@ -67,13 +67,12 @@ int rea_create_table(my_string file_name, if (pack_header(forminfo, create_info->db_type,create_fields,info_length, screens, create_info->table_options, db_file)) { - NET *net=my_pthread_getspecific_ptr(NET*,THR_NET); my_free((gptr) screen_buff,MYF(0)); - if (net->last_errno != ER_TOO_MANY_FIELDS) + if (thd->net.last_errno != ER_TOO_MANY_FIELDS) DBUG_RETURN(1); // Try again without UNIREG screens (to get more columns) - net->last_error[0]=0; + thd->net.last_error[0]=0; if (!(screen_buff=pack_screens(create_fields,&info_length,&screens,1))) DBUG_RETURN(1); if (pack_header(forminfo, create_info->db_type, create_fields,info_length, diff --git a/sql/unireg.h b/sql/unireg.h index 2cfa709bbdc..fd1117a4708 100644 --- a/sql/unireg.h +++ b/sql/unireg.h @@ -63,6 +63,8 @@ #define MAX_SORT_MEMORY (2048*1024-MALLOC_OVERHEAD) #define MIN_SORT_MEMORY (32*1024-MALLOC_OVERHEAD) +#define DEFAULT_ERROR_COUNT 64 +#define DEFAULT_PREP_STMT_COUNT 64 #define EXTRA_RECORDS 10 /* Extra records in sort */ #define SCROLL_EXTRA 5 /* Extra scroll-rows. */ #define FIELD_NAME_USED ((uint) 32768) /* Bit set if fieldname used */ |