summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/field.cc58
-rw-r--r--sql/field.h1
-rw-r--r--sql/gstream.h40
-rw-r--r--sql/ha_innodb.cc2
-rw-r--r--sql/item.cc73
-rw-r--r--sql/item.h35
-rw-r--r--sql/item_func.cc39
-rw-r--r--sql/item_func.h2
-rw-r--r--sql/item_strfunc.cc4
-rw-r--r--sql/item_sum.h17
-rw-r--r--sql/item_timefunc.cc78
-rw-r--r--sql/item_timefunc.h10
-rw-r--r--sql/item_uniq.h2
-rw-r--r--sql/lex.h1
-rw-r--r--sql/log.cc37
-rw-r--r--sql/log_event.cc21
-rw-r--r--sql/mini_client.cc21
-rw-r--r--sql/mysql_priv.h47
-rw-r--r--sql/mysqld.cc45
-rw-r--r--sql/net_pkg.cc174
-rw-r--r--sql/net_serv.cc76
-rw-r--r--sql/repl_failsafe.cc42
-rw-r--r--sql/set_var.cc70
-rw-r--r--sql/set_var.h29
-rw-r--r--sql/share/czech/errmsg.txt2
-rw-r--r--sql/share/english/errmsg.txt3
-rw-r--r--sql/share/greek/errmsg.txt2
-rw-r--r--sql/share/hungarian/errmsg.txt2
-rw-r--r--sql/share/japanese/errmsg.txt2
-rw-r--r--sql/share/korean/errmsg.txt2
-rw-r--r--sql/share/norwegian-ny/errmsg.txt2
-rw-r--r--sql/share/norwegian/errmsg.txt2
-rw-r--r--sql/share/polish/errmsg.txt2
-rw-r--r--sql/share/romanian/errmsg.txt2
-rw-r--r--sql/share/slovak/errmsg.txt2
-rw-r--r--sql/share/swedish/errmsg.txt2
-rw-r--r--sql/slave.cc47
-rw-r--r--sql/spatial.h145
-rw-r--r--sql/sql_acl.cc68
-rw-r--r--sql/sql_analyse.cc15
-rw-r--r--sql/sql_base.cc17
-rw-r--r--sql/sql_class.cc37
-rw-r--r--sql/sql_class.h80
-rw-r--r--sql/sql_db.cc373
-rw-r--r--sql/sql_delete.cc18
-rw-r--r--sql/sql_derived.cc2
-rw-r--r--sql/sql_do.cc2
-rw-r--r--sql/sql_error.cc250
-rw-r--r--sql/sql_handler.cc10
-rw-r--r--sql/sql_insert.cc12
-rw-r--r--sql/sql_lex.cc4
-rw-r--r--sql/sql_lex.h4
-rw-r--r--sql/sql_list.h117
-rw-r--r--sql/sql_load.cc2
-rw-r--r--sql/sql_parse.cc362
-rw-r--r--sql/sql_prepare.cc548
-rw-r--r--sql/sql_rename.cc2
-rw-r--r--sql/sql_repl.cc55
-rw-r--r--sql/sql_select.cc45
-rw-r--r--sql/sql_select.h4
-rw-r--r--sql/sql_show.cc316
-rw-r--r--sql/sql_table.cc45
-rw-r--r--sql/sql_udf.cc20
-rw-r--r--sql/sql_union.cc2
-rw-r--r--sql/sql_update.cc16
-rw-r--r--sql/sql_yacc.yy67
-rw-r--r--sql/structs.h26
-rw-r--r--sql/table.cc4
-rw-r--r--sql/uniques.cc3
-rw-r--r--sql/unireg.cc7
-rw-r--r--sql/unireg.h2
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(&current_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(&current_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(&current_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(&current_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> &params);
-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> &params);
-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> &params)
+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> &params)
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> &params)
-{
- 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(&current_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(&current_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(&current_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 */