summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <monty@mashka.mysql.fi>2002-10-02 13:33:08 +0300
committerunknown <monty@mashka.mysql.fi>2002-10-02 13:33:08 +0300
commit5a28c2caca888be932140d12f87c496398ad4220 (patch)
tree5a27bda6d3f628af7dcb922ad022e84cf8cb351c /sql
parent9421f1dae99e0f2d6100b31a3641b2cd0ad68e58 (diff)
downloadmariadb-git-5a28c2caca888be932140d12f87c496398ad4220.tar.gz
Fixes and code cleanups after merge with 4.0.3
Warning handling and initial prepared statement handling (last not complete yet) Changed a lot of functions that returned 0/1 to my_bool type. GRANT handling now uses read/write locks instead of mutex Change basic net functions to use THD instead of NET (needed for 4.1 protocol) Use my_sprintf instead of sprintf() + strlen() Added alloc_query() to be able to chare query initialization code with prepared statements. Cleanup handling of SHOW COUNT(*) WARNINGS and SELECT LAST_INSERT_ID() Note that the following test fails (will be fixed ASAP): sub_select, union, rpl_rotate_logs and rpl_mystery22 BitKeeper/deleted/.del-README~3449730baf983117: Delete: mysql-test/t/README BitKeeper/deleted/.del-sql_error.cc~2f1caca8d2485dbe: Delete: libmysqld/sql_error.cc BitKeeper/deleted/.del-sql_prepare.cc~f703729793935ed6: Delete: libmysqld/sql_prepare.cc Docs/manual.texi: Updated variable list client/mysql.cc: Show warning count to user. client/mysqltest.c: Add warnings to test results configure.in: New shared library version number include/errmsg.h: Indentation cleanup include/mysql.h: Removed MYSQL_ERROR Indentaion cleanups include/mysql_com.h: Changed functions to returns true/false to my_bool. include/mysqld_error.h: New error messages isam/pack_isam.c: Indentation change libmysql/Makefile.am: Fix of wrong merge libmysql/Makefile.shared: Indentation cleanup libmysql/errmsg.c: Removed not used errors libmysql/libmysql.c: Change functions to return 1 on error (not -1) Change type of functions that returns 0/1 to my_bool Lot of code optimizations. Lot of changes for prepared statements. This now handles sending of binary data to server. Receving of binary data is not yet done (will have to wait until server code for this is ready) mysql_warning_count and mysql_warnings() implemented. libmysql/libmysql.def: Added mysql_warnings and mysql_warning_count libmysql/manager.c: Fixed wrong testing of result from my_connect() libmysqld/lib_sql.cc: Removed global variable THR_NET Change basic net functions to use THD instead of NET GRANT handling now uses read/write locks instead of mutex libmysqld/libmysqld.c: Changed functions to be my_bool myisam/ft_boolean_search.c: Trivial code cleanup myisam/ft_stopwords.c: Trivial code cleanup myisam/mi_check.c: Update to 4.1 structures myisam/myisampack.c: Trivial code cleanup myisam/rt_key.c: Code cleanup myisam/rt_test.c: Code cleanup Removed compiler warnings myisam/sp_key.c: Indentation changes myisam/sp_test.c: Removed compiler warnings mysql-test/README: Updated to reflect the new --external flag. mysql-test/mysql-test-run.sh: --local (start new server) is now default. Use --external to test against external server. mysql-test/r/rollback.result: Updated for 4.1 warnings mysql-test/r/rpl_log.result: Update for 4.1 mysql-test/t/rollback.test: Updated for 4.1 warnings mysql-test/t/rpl_log_pos.test: Portability fix mysys/hash.c: Indentation change mysys/my_error.c: Indentation change mysys/tree.c: Updated file description sql/field.cc: Fixed bugs introduced by merge Use my_sprintf instead of sprintf() + strlen() sql/field.h: Add CHARSET_INFO to field structure sql/gstream.h: Indentation changes. Added GPL copyright header sql/ha_innodb.cc: Updated parameters for net functions. sql/item.cc: Updates of Item_param Indentation changes sql/item.h: Removed size_of() function from item. sql/item_func.cc: Update function usage for 4.1 Added get_system_var() sql/item_func.h: Indentation change sql/item_strfunc.cc: Removed not needed inclusion of gstream.h Update to use system variables (from 4.0) sql/item_sum.h: Removed size_of() functions from item. sql/item_timefunc.cc: Change sprintf() + strlen() -> my_sprintf() Added length parameter to ->append() sql/item_timefunc.h: Removed size_of() functions from item. sql/item_uniq.h: Removed size_of() functions from item. sql/lex.h: Removed SQL_ERROR_COUNT variable sql/log.cc: Change sprintf() + strlen() -> my_sprintf() sql/log_event.cc: Change sprintf() + strlen() -> my_sprintf() sql/mini_client.cc: Added check that one always specifies a length to mc_mysql_query() sql/mysql_priv.h: New prototypes Change of NET -> THD parameter for net functions. sql/mysqld.cc: New startup options: 'max_prepared_statements', 'max_error_count' Updated usage of net functions. sql/net_pkg.cc: Change basic net functions to use THD instead of NET (needed to be able to handle 4.0 and 4.1 protocols) Lots of function comments sql/net_serv.cc: Change int return values -> my_bool Updated net_write_command() to take an extra header block to be added to the packet. (This made the prepared statement code much nicer and more efficient) sql/repl_failsafe.cc: Update net functions to use THD instead of NET sql/set_var.cc: Added @@error_count and @@warning_count variables. Updated to 4.1 function usage sql/set_var.h: Added @@error_count and @@warning_count variables. sql/share/czech/errmsg.txt: Removed Warning: from warning error messages. sql/share/english/errmsg.txt: Removed Warning: from warning error messages. sql/share/greek/errmsg.txt: Removed Warning: from warning error messages. sql/share/hungarian/errmsg.txt: Removed Warning: from warning error messages. sql/share/japanese/errmsg.txt: Removed Warning: from warning error messages. sql/share/korean/errmsg.txt: Removed Warning: from warning error messages. sql/share/norwegian-ny/errmsg.txt: Removed Warning: from warning error messages. sql/share/norwegian/errmsg.txt: Removed Warning: from warning error messages. sql/share/polish/errmsg.txt: Removed Warning: from warning error messages. sql/share/romanian/errmsg.txt: Removed Warning: from warning error messages. sql/share/slovak/errmsg.txt: Removed Warning: from warning error messages. sql/share/swedish/errmsg.txt: Removed Warning: from warning error messages. sql/slave.cc: Change basic net functions to use THD instead of NET skip_load_data_file recoded to fit new client/server protocol sql/spatial.h: Added copyright header Indentation cleanups sql/sql_acl.cc: Change basic net functions to use THD instead of NET GRANT handling now uses read/write locks instead of mutex sql/sql_analyse.cc: Change basic net functions to use THD instead of NET sprintf() + strlen() -> my_sprintf() sql/sql_base.cc: More DBUG statements sql/sql_class.cc: Change basic net functions to use THD instead of NET warning and prepared statement handling sql/sql_class.h: Change basic net functions to use THD instead of NET warning and prepared statement handling sql/sql_db.cc: Code cleanup & optimization. sql/sql_delete.cc: Change basic net functions to use THD instead of NET sql/sql_derived.cc: Change basic net functions to use THD instead of NET sql/sql_do.cc: Change basic net functions to use THD instead of NET sql/sql_error.cc: Big rewrite of error handling. sql/sql_handler.cc: Change basic net functions to use THD instead of NET sql/sql_insert.cc: Change basic net functions to use THD instead of NET sql/sql_lex.cc: Change basic net functions to use THD instead of NET sql/sql_lex.h: Added param_count to st_select_lex_node sql/sql_list.h: Removed not needed error list. sql/sql_load.cc: Change basic net functions to use THD instead of NET sql/sql_parse.cc: Change basic net functions to use THD instead of NET Added alloc_query() to be able to chare query initialization code with prepared statements. Update of warning handling. Added create_select_for_variable() (for SHOW COUNT(*) WARNINGS) sql/sql_prepare.cc: Initial prepared statement handling sql/sql_rename.cc: Change basic net functions to use THD instead of NET sql/sql_repl.cc: Change basic net functions to use THD instead of NET sql/sql_select.cc: Small code cleanups Added missing initialization of error that caused some queries that returned an empty result set to fail sql/sql_select.h: Ensure that JOIN.error is properly initialized sql/sql_show.cc: Change basic net functions to use THD instead of NET A lot of optimization sql/sql_table.cc: Change basic net functions to use THD instead of NET Indentaion cleanup sql/sql_udf.cc: Change basic net functions to use THD instead of NET sql/sql_union.cc: Change basic net functions to use THD instead of NET sql/sql_update.cc: Change basic net functions to use THD instead of NET sql/sql_yacc.yy: Change basic net functions to use THD instead of NET Cleanup handling of SHOW COUNT(*) WARNINGS and SELECT LAST_INSERT_ID() sql/structs.h: Moved structures to files where they was used sql/table.cc: Don't accept empty database names sql/uniques.cc: Indentation cleanup sql/unireg.cc: Change basic net functions to use THD instead of NET sql/unireg.h: Added defaults for warnings and prepared statements strings/ctype-simple.c: optimization tests/client_test.c: Fixed wrong paramaters to printf()
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 */