summaryrefslogtreecommitdiff
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
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()
-rw-r--r--Docs/manual.texi3
-rw-r--r--client/mysql.cc32
-rw-r--r--client/mysqltest.c87
-rw-r--r--configure.in2
-rw-r--r--include/errmsg.h21
-rw-r--r--include/mysql.h133
-rw-r--r--include/mysql_com.h46
-rw-r--r--include/mysqld_error.h3
-rw-r--r--isam/pack_isam.c3
-rw-r--r--libmysql/Makefile.am4
-rw-r--r--libmysql/Makefile.shared5
-rw-r--r--libmysql/errmsg.c18
-rw-r--r--libmysql/libmysql.c1475
-rw-r--r--libmysql/libmysql.def4
-rw-r--r--libmysql/manager.c2
-rw-r--r--libmysqld/lib_sql.cc23
-rw-r--r--libmysqld/libmysqld.c34
-rw-r--r--myisam/ft_boolean_search.c4
-rw-r--r--myisam/ft_stopwords.c4
-rw-r--r--myisam/mi_check.c6
-rw-r--r--myisam/myisampack.c3
-rw-r--r--myisam/rt_key.c63
-rw-r--r--myisam/rt_test.c14
-rw-r--r--myisam/sp_key.c15
-rw-r--r--myisam/sp_test.c11
-rw-r--r--mysql-test/README7
-rw-r--r--mysql-test/mysql-test-run.sh3
-rw-r--r--mysql-test/r/rollback.result19
-rw-r--r--mysql-test/r/rpl_log.result38
-rw-r--r--mysql-test/t/README0
-rw-r--r--mysql-test/t/rollback.test9
-rw-r--r--mysql-test/t/rpl_log_pos.test1
-rw-r--r--mysys/hash.c7
-rw-r--r--mysys/my_error.c2
-rw-r--r--mysys/tree.c25
-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
-rw-r--r--strings/ctype-simple.c16
-rw-r--r--tests/client_test.c124
108 files changed, 3026 insertions, 2916 deletions
diff --git a/Docs/manual.texi b/Docs/manual.texi
index 5d4394a7d66..e8bd1ac53e3 100644
--- a/Docs/manual.texi
+++ b/Docs/manual.texi
@@ -28684,6 +28684,7 @@ and if you can use @code{GLOBAL} or @code{SESSION} with them.
@item delayed_insert_limit @tab num @tab GLOBAL
@item delayed_insert_timeout @tab num @tab GLOBAL
@item delayed_queue_size @tab num @tab GLOBAL
+@item error_count @tab num @tab LOCAL
@item flush @tab bool @tab GLOBAL
@item flush_time @tab num @tab GLOBAL
@item foreign_key_checks @tab bool @tab SESSION
@@ -28702,6 +28703,7 @@ and if you can use @code{GLOBAL} or @code{SESSION} with them.
@item max_binlog_size @tab num @tab GLOBAL
@item max_connect_errors @tab num @tab GLOBAL
@item max_connections @tab num @tab GLOBAL
+@item max_error_count @tab num @tab GLOBAL | SESSION
@item max_delayed_threads @tab num @tab GLOBAL
@item max_heap_table_size @tab num @tab GLOBAL | SESSION
@item max_join_size @tab num @tab GLOBAL | SESSION
@@ -28750,6 +28752,7 @@ and if you can use @code{GLOBAL} or @code{SESSION} with them.
@item tx_isolation @tab enum @tab GLOBAL | SESSION
@item version @tab string @tab GLOBAL
@item wait_timeout @tab num @tab GLOBAL | SESSION
+@item warning_count @tab num @tab LOCAL
@item unique_checks @tab bool @tab SESSION
@end multitable
diff --git a/client/mysql.cc b/client/mysql.cc
index 7fd221f479c..223d4b794d2 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -40,7 +40,7 @@
#include <signal.h>
#include <violite.h>
-const char *VER= "12.12";
+const char *VER= "12.13";
/* Don't try to make a nice table if the data is too big */
#define MAX_COLUMN_LENGTH 1024
@@ -1362,9 +1362,9 @@ com_clear(String *buffer,char *line __attribute__((unused)))
static int
com_go(String *buffer,char *line __attribute__((unused)))
{
- char buff[160],time_buff[32];
+ char buff[200], time_buff[32], *pos;
MYSQL_RES *result;
- ulong timer;
+ ulong timer, warnings;
uint error=0;
if (!status.batch)
@@ -1447,7 +1447,7 @@ com_go(String *buffer,char *line __attribute__((unused)))
{
if (!mysql_num_rows(result) && ! quick)
{
- sprintf(buff,"Empty set%s",time_buff);
+ strmov(buff, "Empty set");
}
else
{
@@ -1462,20 +1462,30 @@ com_go(String *buffer,char *line __attribute__((unused)))
print_tab_data(result);
else
print_table_data(result);
- sprintf(buff,"%ld %s in set%s",
+ sprintf(buff,"%ld %s in set",
(long) mysql_num_rows(result),
- (long) mysql_num_rows(result) == 1 ? "row" : "rows",
- time_buff);
+ (long) mysql_num_rows(result) == 1 ? "row" : "rows");
end_pager();
}
}
else if (mysql_affected_rows(&mysql) == ~(ulonglong) 0)
- sprintf(buff,"Query OK%s",time_buff);
+ strmov(buff,"Query OK");
else
- sprintf(buff,"Query OK, %ld %s affected%s",
+ sprintf(buff,"Query OK, %ld %s affected",
(long) mysql_affected_rows(&mysql),
- (long) mysql_affected_rows(&mysql) == 1 ? "row" : "rows",
- time_buff);
+ (long) mysql_affected_rows(&mysql) == 1 ? "row" : "rows");
+
+ pos=strend(buff);
+ if ((warnings= mysql_warning_count(&mysql)))
+ {
+ *pos++= ',';
+ *pos++= ' ';
+ pos=int2str(warnings, pos, 10);
+ pos=strmov(pos, " warning");
+ if (warnings != 1)
+ *pos++= 's';
+ }
+ strmov(pos, time_buff);
put_info(buff,INFO_RESULT);
if (mysql_info(&mysql))
put_info(mysql_info(&mysql),INFO_RESULT);
diff --git a/client/mysqltest.c b/client/mysqltest.c
index f469a33f063..181a7fb2b8f 100644
--- a/client/mysqltest.c
+++ b/client/mysqltest.c
@@ -311,7 +311,7 @@ static int eval_result = 0;
void mysql_enable_rpl_parse(MYSQL* mysql __attribute__((unused))) {}
void mysql_disable_rpl_parse(MYSQL* mysql __attribute__((unused))) {}
int mysql_rpl_parse_enabled(MYSQL* mysql __attribute__((unused))) { return 1; }
-int mysql_rpl_probe(MYSQL *mysql __attribute__((unused))) { return 1; }
+my_bool mysql_rpl_probe(MYSQL *mysql __attribute__((unused))) { return 1; }
#endif
#define MAX_SERVER_ARGS 20
@@ -1073,7 +1073,7 @@ int do_disable_rpl_parse(struct st_query* q __attribute__((unused)))
}
-int do_sleep(struct st_query* q)
+int do_sleep(struct st_query* q, my_bool real_sleep)
{
char *p=q->first_argument;
struct timeval t;
@@ -2055,6 +2055,36 @@ static void replace_dynstr_append_mem(DYNAMIC_STRING *ds, const char *val,
dynstr_append_mem(ds, val, len);
}
+/*
+ Append all results to the dynamic string separated with '\t'
+*/
+
+static void append_result(DYNAMIC_STRING *ds, MYSQL_RES *res)
+{
+ MYSQL_ROW row;
+ int num_fields= mysql_num_fields(res);
+ unsigned long *lengths;
+ while ((row = mysql_fetch_row(res)))
+ {
+ int i;
+ lengths = mysql_fetch_lengths(res);
+ for (i = 0; i < num_fields; i++)
+ {
+ const char *val= row[i];
+ ulonglong len= lengths[i];
+ if (!val)
+ {
+ val = "NULL";
+ len = 4;
+ }
+ if (i)
+ dynstr_append_mem(ds, "\t", 1);
+ replace_dynstr_append_mem(ds, val, len);
+ }
+ dynstr_append_mem(ds, "\n", 1);
+ }
+}
+
/*
* flags control the phased/stages of query execution to be performed
@@ -2065,12 +2095,7 @@ static void replace_dynstr_append_mem(DYNAMIC_STRING *ds, const char *val,
int run_query(MYSQL* mysql, struct st_query* q, int flags)
{
MYSQL_RES* res = 0;
- MYSQL_FIELD* fields;
- MYSQL_ROW row;
- int num_fields,i, error = 0;
- unsigned long* lengths;
- char* val;
- int len;
+ int i, error = 0;
DYNAMIC_STRING *ds;
DYNAMIC_STRING ds_tmp;
DYNAMIC_STRING eval_query;
@@ -2178,45 +2203,37 @@ int run_query(MYSQL* mysql, struct st_query* q, int flags)
goto end;
}
- if (!res)
- goto end;
-
- if (!disable_result_log)
+ if (!disable_result_log && res)
{
- fields = mysql_fetch_fields(res);
- num_fields = mysql_num_fields(res);
+ int num_fields= mysql_num_fields(res);
+ MYSQL_FIELD *fields= mysql_fetch_fields(res);
for (i = 0; i < num_fields; i++)
{
if (i)
dynstr_append_mem(ds, "\t", 1);
dynstr_append(ds, fields[i].name);
}
-
dynstr_append_mem(ds, "\n", 1);
+ append_result(ds, res);
+ }
- while ((row = mysql_fetch_row(res)))
+ /* Add all warnings to the result */
+ if (!disable_result_log && mysql_warning_count(mysql))
+ {
+ MYSQL_RES *warn_res= mysql_warnings(mysql);
+ if (!warn_res)
+ verbose_msg("Warning count is %d but didn't get any warnings\n",
+ mysql_warning_count(mysql));
+ else
{
- lengths = mysql_fetch_lengths(res);
- for (i = 0; i < num_fields; i++)
- {
- val = (char*)row[i];
- len = lengths[i];
-
- if (!val)
- {
- val = (char*)"NULL";
- len = 4;
- }
-
- if (i)
- dynstr_append_mem(ds, "\t", 1);
- replace_dynstr_append_mem(ds, val, len);
- }
- dynstr_append_mem(ds, "\n", 1);
+ dynstr_append_mem(ds, "Warnings:\n", 10);
+ append_result(ds, warn_res);
+ mysql_free_result(warn_res);
}
- if (glob_replace)
- free_replace();
}
+ if (glob_replace)
+ free_replace();
+
if (record)
{
if (!q->record_file[0] && !result_file)
diff --git a/configure.in b/configure.in
index 5cd299a8ba0..8ca1a0befed 100644
--- a/configure.in
+++ b/configure.in
@@ -10,7 +10,7 @@ AM_CONFIG_HEADER(config.h)
PROTOCOL_VERSION=10
DOT_FRM_VERSION=6
# See the libtool docs for information on how to do shared lib versions.
-SHARED_LIB_VERSION=11:0:0
+SHARED_LIB_VERSION=12:0:0
# Set all version vars based on $VERSION. How do we do this more elegant ?
# Remember that regexps needs to quote [ and ] since this is run through m4
diff --git a/include/errmsg.h b/include/errmsg.h
index 175089ba371..d97522f0972 100644
--- a/include/errmsg.h
+++ b/include/errmsg.h
@@ -63,15 +63,12 @@ extern const char *client_errors[]; /* Error messages */
#define CR_PROBE_MASTER_CONNECT 2025
/* new 4.1 error codes */
-#define CR_INVALID_CONN_HANDLE 2026
-#define CR_NULL_POINTER 2027
-#define CR_MEMORY_ERROR 2028
-#define CR_NO_PREPARE_STMT 2029
-#define CR_NOT_ALL_PARAMS_BOUND 2030
-#define CR_DATA_TRUNCATED 2031
-#define CR_NOT_ALL_BUFFERS_BOUND 2032
-#define CR_FAILED_TO_SET_PARAM_DATA 2033
-#define CR_NO_PARAMETERS_EXISTS 2033
-#define CR_INVALID_PARAMETER_NO 2035
-#define CR_INVALID_BUFFER_USE 2036
-
+#define CR_INVALID_CONN_HANDLE 2026
+#define CR_NULL_POINTER 2027
+#define CR_NO_PREPARE_STMT 2028
+#define CR_NOT_ALL_PARAMS_BOUND 2029
+#define CR_DATA_TRUNCATED 2030
+#define CR_NO_PARAMETERS_EXISTS 2031
+#define CR_INVALID_PARAMETER_NO 2032
+#define CR_INVALID_BUFFER_USE 2033
+#define CR_UNSUPPORTED_PARAM_TYPE 2034
diff --git a/include/mysql.h b/include/mysql.h
index 50543c51f6b..376de1a0e08 100644
--- a/include/mysql.h
+++ b/include/mysql.h
@@ -157,7 +157,8 @@ enum mysql_rpl_type { MYSQL_RPL_MASTER, MYSQL_RPL_SLAVE,
MYSQL_RPL_ADMIN };
-typedef struct st_mysql {
+typedef struct st_mysql
+{
NET net; /* Communication parameters */
gptr connector_fd; /* ConnectorFd for SSL */
char *host,*user,*passwd,*unix_socket,*server_version,*host_info,
@@ -175,6 +176,7 @@ typedef struct st_mysql {
unsigned int field_count;
unsigned int server_status;
unsigned int server_language;
+ unsigned int warning_count;
struct st_mysql_options options;
enum mysql_status status;
my_bool free_me; /* If free in mysql_close */
@@ -273,12 +275,13 @@ my_ulonglong STDCALL mysql_affected_rows(MYSQL *mysql);
my_ulonglong STDCALL mysql_insert_id(MYSQL *mysql);
unsigned int STDCALL mysql_errno(MYSQL *mysql);
const char * STDCALL mysql_error(MYSQL *mysql);
+uint STDCALL mysql_warning_count(MYSQL *mysql);
const char * STDCALL mysql_info(MYSQL *mysql);
unsigned long STDCALL mysql_thread_id(MYSQL *mysql);
const char * STDCALL mysql_character_set_name(MYSQL *mysql);
MYSQL * STDCALL mysql_init(MYSQL *mysql);
-int STDCALL mysql_ssl_set(MYSQL *mysql, const char *key,
+my_bool STDCALL mysql_ssl_set(MYSQL *mysql, const char *key,
const char *cert, const char *ca,
const char *capath, const char *cipher);
my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user,
@@ -295,19 +298,19 @@ int STDCALL mysql_select_db(MYSQL *mysql, const char *db);
int STDCALL mysql_query(MYSQL *mysql, const char *q);
int STDCALL mysql_send_query(MYSQL *mysql, const char *q,
unsigned long length);
-int STDCALL mysql_read_query_result(MYSQL *mysql);
+my_bool STDCALL mysql_read_query_result(MYSQL *mysql);
int STDCALL mysql_real_query(MYSQL *mysql, const char *q,
unsigned long length);
/* perform query on master */
-int STDCALL mysql_master_query(MYSQL *mysql, const char *q,
- unsigned long length);
-int STDCALL mysql_master_send_query(MYSQL *mysql, const char *q,
- unsigned long length);
+my_bool STDCALL mysql_master_query(MYSQL *mysql, const char *q,
+ unsigned long length);
+my_bool STDCALL mysql_master_send_query(MYSQL *mysql, const char *q,
+ unsigned long length);
/* perform query on slave */
-int STDCALL mysql_slave_query(MYSQL *mysql, const char *q,
- unsigned long length);
-int STDCALL mysql_slave_send_query(MYSQL *mysql, const char *q,
- unsigned long length);
+my_bool STDCALL mysql_slave_query(MYSQL *mysql, const char *q,
+ unsigned long length);
+my_bool STDCALL mysql_slave_send_query(MYSQL *mysql, const char *q,
+ unsigned long length);
/*
enable/disable parsing of all queries to decide if they go on master or
@@ -322,12 +325,12 @@ int STDCALL mysql_rpl_parse_enabled(MYSQL* mysql);
void STDCALL mysql_enable_reads_from_master(MYSQL* mysql);
void STDCALL mysql_disable_reads_from_master(MYSQL* mysql);
/* get the value of the master read flag */
-int STDCALL mysql_reads_from_master_enabled(MYSQL* mysql);
+my_bool STDCALL mysql_reads_from_master_enabled(MYSQL* mysql);
enum mysql_rpl_type STDCALL mysql_rpl_query_type(const char* q, int len);
/* discover the master and its slaves */
-int STDCALL mysql_rpl_probe(MYSQL* mysql);
+my_bool STDCALL mysql_rpl_probe(MYSQL* mysql);
/* set the master, close/free the old one, if it is not a pivot */
int STDCALL mysql_set_master(MYSQL* mysql, const char* host,
@@ -357,6 +360,7 @@ MYSQL_RES * STDCALL mysql_list_fields(MYSQL *mysql, const char *table,
MYSQL_RES * STDCALL mysql_list_processes(MYSQL *mysql);
MYSQL_RES * STDCALL mysql_store_result(MYSQL *mysql);
MYSQL_RES * STDCALL mysql_use_result(MYSQL *mysql);
+MYSQL_RES * STDCALL mysql_warnings(MYSQL *mysql);
int STDCALL mysql_options(MYSQL *mysql,enum mysql_option option,
const char *arg);
void STDCALL mysql_free_result(MYSQL_RES *result);
@@ -401,7 +405,6 @@ int STDCALL mysql_manager_fetch_line(MYSQL_MANAGER* con,
int res_buf_size);
-
/*
The following definitions are added for the enhanced
client-server protocol
@@ -411,67 +414,76 @@ int STDCALL mysql_manager_fetch_line(MYSQL_MANAGER* con,
enum MY_STMT_STATE { MY_ST_UNKNOWN, MY_ST_PREPARE, MY_ST_EXECUTE };
/* bind structure */
-typedef struct st_mysql_bind {
-
- enum enum_field_types buffer_type; /* buffer type */
- enum enum_field_types field_type; /* field type */
- gptr buffer; /* buffer */
- long *length; /* output length pointer */
- unsigned long buffer_length; /* buffer length */
- unsigned long bind_length; /* internal use */
- my_bool is_null; /* NULL indicator */
- my_bool is_long_data; /* long data indicator */
- my_bool long_ended; /* internal use */
-
+typedef struct st_mysql_bind
+{
+ long *length; /* output length pointer */
+ gptr buffer; /* buffer */
+ unsigned long buffer_length; /* buffer length */
+ enum enum_field_types buffer_type; /* buffer type */
+ enum enum_field_types field_type; /* field type */
+ my_bool is_null; /* NULL indicator */
+ my_bool is_long_data; /* long data indicator */
+
+ /* The following are for internal use. Set by mysql_bind_param */
+ long bind_length; /* Default length of data */
+ my_bool long_ended; /* All data supplied for long */
+ uint param_number; /* For null count and error messages */
+ void (*store_param_func)(NET *net, struct st_mysql_bind *param);
+ char *(*fetch_result)(struct st_mysql_bind *, const char *row);
} MYSQL_BIND;
-/* statement handler */
-typedef struct st_mysql_stmt {
-
- MYSQL *mysql; /* connection handle */
- MYSQL_BIND *params; /* input parameters */
- MYSQL_RES *result; /* resultset */
- MYSQL_BIND *bind; /* row binding */
- MYSQL_FIELD *fields; /* prepare meta info */
- MEM_ROOT mem_root; /* root allocations */
- unsigned long param_count; /* parameters count */
- unsigned long field_count; /* fields count */
- unsigned long long_length; /* long buffer alloced length */
- uint err_no; /* error code */
- char error[MYSQL_ERRMSG_SIZE]; /* error message */
- char *query; /* query buffer */
- char *long_data; /* long buffer */
- enum MY_STMT_STATE state; /* statement state */
- my_bool long_alloced; /* flag to indicate long alloced */
- my_bool types_supplied; /* to indicate types supply */
+/* statement handler */
+typedef struct st_mysql_stmt
+{
+ MYSQL *mysql; /* connection handle */
+ MYSQL_BIND *params; /* input parameters */
+ MYSQL_RES *result; /* resultset */
+ MYSQL_BIND *bind; /* row binding */
+ MYSQL_FIELD *fields; /* prepare meta info */
+ char *query; /* query buffer */
+ MEM_ROOT mem_root; /* root allocations */
+ MYSQL_RES tmp_result; /* Used by mysql_prepare_result */
+ unsigned long param_count; /* parameters count */
+ unsigned long field_count; /* fields count */
+ unsigned long long_length; /* long buffer alloced length */
+ ulong stmt_id; /* Id for prepared statement */
+ uint last_errno; /* error code */
+ enum MY_STMT_STATE state; /* statement state */
+ char last_error[MYSQL_ERRMSG_SIZE]; /* error message */
+ my_bool long_alloced; /* flag to indicate long alloced */
+ my_bool types_supplied; /* to indicate types supply */
} MYSQL_STMT;
-MYSQL_STMT * STDCALL mysql_prepare(MYSQL * mysql, const char *query);
+MYSQL_STMT * STDCALL mysql_prepare(MYSQL * mysql, const char *query,
+ unsigned long length);
int STDCALL mysql_execute(MYSQL_STMT * stmt);
unsigned long STDCALL mysql_param_count(MYSQL_STMT * stmt);
-int STDCALL mysql_bind_param(MYSQL_STMT * stmt, MYSQL_BIND * bind);
-int STDCALL mysql_bind_result(MYSQL_STMT * stmt, MYSQL_BIND * bind);
-int STDCALL mysql_stmt_close(MYSQL_STMT * stmt);
+my_bool STDCALL mysql_bind_param(MYSQL_STMT * stmt, MYSQL_BIND * bind);
+my_bool STDCALL mysql_bind_result(MYSQL_STMT * stmt, MYSQL_BIND * bind);
+my_bool STDCALL mysql_stmt_close(MYSQL_STMT * stmt);
uint STDCALL mysql_stmt_errno(MYSQL_STMT * stmt);
const char *STDCALL mysql_stmt_error(MYSQL_STMT * stmt);
-int STDCALL mysql_commit(MYSQL * mysql);
-int STDCALL mysql_rollback(MYSQL * mysql);
-int STDCALL mysql_autocommit(MYSQL * mysql, my_bool auto_mode);
-int STDCALL mysql_fetch(MYSQL_STMT *stmt);
+my_bool STDCALL mysql_commit(MYSQL * mysql);
+my_bool STDCALL mysql_rollback(MYSQL * mysql);
+my_bool STDCALL mysql_autocommit(MYSQL * mysql, my_bool auto_mode);
+int STDCALL mysql_fetch(MYSQL_STMT *stmt);
my_bool STDCALL mysql_send_long_data(MYSQL_STMT *stmt,
- uint param_number,gptr data,
- unsigned long length);
-int STDCALL mysql_multi_query(MYSQL *mysql,const char *query,unsigned long len);
+ uint param_number,
+ const char *data,
+ unsigned long length,
+ my_bool last_data);
+int STDCALL mysql_multi_query(MYSQL *mysql,const char *query,
+ unsigned long len);
MYSQL_RES *STDCALL mysql_next_result(MYSQL *mysql);
-MYSQL_RES * STDCALL mysql_prepare_result(MYSQL_STMT *stmt);
+MYSQL_RES *STDCALL mysql_prepare_result(MYSQL_STMT *stmt);
/* new status messages */
#define MYSQL_SUCCESS 0
#define MYSQL_WARNING 1
-#define MYSQL_ERROR -1
+#define MYSQL_STATUS_ERROR 2
#define MYSQL_NO_DATA 100
#define MYSQL_NEED_DATA 99
#define MYSQL_LONG_DATA_END 0xFF
@@ -492,8 +504,9 @@ int STDCALL mysql_drop_db(MYSQL *mysql, const char *DB);
They are not for general usage
*/
-int simple_command(MYSQL *mysql,enum enum_server_command command,
- const char *arg, unsigned long length, my_bool skipp_check);
+my_bool
+simple_command(MYSQL *mysql,enum enum_server_command command, const char *arg,
+ ulong length, my_bool skip_check);
unsigned long net_safe_read(MYSQL* mysql);
#ifdef __cplusplus
diff --git a/include/mysql_com.h b/include/mysql_com.h
index 9743fc4c3f5..1edaa99db28 100644
--- a/include/mysql_com.h
+++ b/include/mysql_com.h
@@ -34,15 +34,15 @@
#define MYSQL_SERVICENAME "MySql"
#endif /* __WIN__ */
-enum enum_server_command {COM_SLEEP,COM_QUIT,COM_INIT_DB,COM_QUERY,
- COM_FIELD_LIST,COM_CREATE_DB,COM_DROP_DB,COM_REFRESH,
- COM_SHUTDOWN,COM_STATISTICS,
- COM_PROCESS_INFO,COM_CONNECT,COM_PROCESS_KILL,
- COM_DEBUG,COM_PING,COM_TIME,COM_DELAYED_INSERT,
- COM_CHANGE_USER, COM_BINLOG_DUMP,
- COM_TABLE_DUMP, COM_CONNECT_OUT,
- COM_REGISTER_SLAVE,
- COM_PREPARE,COM_EXECUTE,COM_LONG_DATA };
+enum enum_server_command
+{
+ COM_SLEEP, COM_QUIT, COM_INIT_DB, COM_QUERY, COM_FIELD_LIST,
+ COM_CREATE_DB, COM_DROP_DB, COM_REFRESH, COM_SHUTDOWN, COM_STATISTICS,
+ COM_PROCESS_INFO, COM_CONNECT, COM_PROCESS_KILL, COM_DEBUG, COM_PING,
+ COM_TIME, COM_DELAYED_INSERT, COM_CHANGE_USER, COM_BINLOG_DUMP,
+ COM_TABLE_DUMP, COM_CONNECT_OUT, COM_REGISTER_SLAVE,
+ COM_PREPARE, COM_EXECUTE, COM_LONG_DATA, COM_CLOSE_STMT
+};
#define NOT_NULL_FLAG 1 /* Field can't be NULL */
#define PRI_KEY_FLAG 2 /* Field is part of a primary key */
@@ -98,8 +98,9 @@ enum enum_server_command {COM_SLEEP,COM_QUIT,COM_INIT_DB,COM_QUERY,
#define CLIENT_TRANSACTIONS 8192 /* Client knows about transactions */
#define CLIENT_PROTOCOL_41 16384 /* New 4.1 protocol */
-#define SERVER_STATUS_IN_TRANS 1 /* Transaction has started */
-#define SERVER_STATUS_AUTOCOMMIT 2 /* Server in auto_commit mode */
+#define SERVER_STATUS_IN_TRANS 1 /* Transaction has started */
+#define SERVER_STATUS_AUTOCOMMIT 2 /* Server in auto_commit mode */
+#define SERVER_STATUS_MORE_RESULTS 4 /* More results on server */
#define MYSQL_ERRMSG_SIZE 200
#define NET_READ_TIMEOUT 30 /* Timeout on read */
@@ -203,21 +204,26 @@ enum enum_field_types { MYSQL_TYPE_DECIMAL, MYSQL_TYPE_TINY,
extern "C" {
#endif
-int my_net_init(NET *net, Vio* vio);
+my_bool my_net_init(NET *net, Vio* vio);
void my_net_local_init(NET *net);
void net_end(NET *net);
void net_clear(NET *net);
-int net_flush(NET *net);
-int my_net_write(NET *net,const char *packet,unsigned long len);
-int net_write_command(NET *net,unsigned char command,const char *packet,
- unsigned long len);
+my_bool net_realloc(NET *net, unsigned long length);
+my_bool net_flush(NET *net);
+my_bool my_net_write(NET *net,const char *packet,unsigned long len);
+my_bool net_write_command(NET *net,unsigned char command,
+ const char *header, unsigned long head_len,
+ const char *packet, unsigned long len);
int net_real_write(NET *net,const char *packet,unsigned long len);
unsigned long my_net_read(NET *net);
-/* The following function is not meant for normal usage */
+/*
+ The following function is not meant for normal usage
+ Currently it's used internally by manager.c
+*/
struct sockaddr;
-int my_connect(my_socket s, const struct sockaddr *name, unsigned int namelen,
- unsigned int timeout);
+my_bool my_connect(my_socket s, const struct sockaddr *name,
+ unsigned int namelen, unsigned int timeout);
struct rand_struct {
unsigned long seed1,seed2,max_value;
@@ -291,6 +297,6 @@ void my_thread_end(void);
#endif
#define NULL_LENGTH ((unsigned long) ~0) /* For net_store_length */
-#define MYSQL_LONG_DATA_END 0xFF /* For indication of long data ending */
+#define MYSQL_LONG_DATA_HEADER 8
#endif
diff --git a/include/mysqld_error.h b/include/mysqld_error.h
index 635d8390c2c..fc5df43f309 100644
--- a/include/mysqld_error.h
+++ b/include/mysqld_error.h
@@ -257,4 +257,5 @@
#define ER_KEY_REF_DO_NOT_MATCH_TABLE_REF 1238
#define ER_SUBSELECT_NO_1_COL 1239
#define ER_SUBSELECT_NO_1_ROW 1240
-#define ER_ERROR_MESSAGES 241
+#define ER_UNKNOWN_STMT_HANDLER 1241
+#define ER_ERROR_MESSAGES 242
diff --git a/isam/pack_isam.c b/isam/pack_isam.c
index 8a00b4c962a..ebe616714f5 100644
--- a/isam/pack_isam.c
+++ b/isam/pack_isam.c
@@ -687,7 +687,8 @@ static HUFF_COUNTS *init_huff_count(N_INFO *info,my_off_t records)
(type == FIELD_NORMAL ||
type == FIELD_SKIP_ZERO))
count[i].max_zero_fill= count[i].field_length;
- init_tree(&count[i].int_tree,0,0,-1,(qsort_cmp2) compare_tree,0,NULL,NULL);
+ init_tree(&count[i].int_tree,0,0,-1,(qsort_cmp2) compare_tree,0,
+ NULL, NULL);
if (records)
count[i].tree_pos=count[i].tree_buff =
my_malloc(count[i].field_length > 1 ? tree_buff_length : 2,
diff --git a/libmysql/Makefile.am b/libmysql/Makefile.am
index fac544ba44d..3d380c14076 100644
--- a/libmysql/Makefile.am
+++ b/libmysql/Makefile.am
@@ -49,10 +49,6 @@ link_sources:
rm -f $(srcdir)/$$f; \
@LN_CP_F@ $(srcdir)/../strings/$$f $(srcdir)/$$f; \
done; \
- for f in $(mystringsgen); do \
- rm -f $(srcdir)/$$f; \
- @LN_CP_F@ ../strings/$$f $(srcdir)/$$f; \
- done; \
for f in $$qs; do \
rm -f $(srcdir)/$$f; \
@LN_CP_F@ $(srcdir)/../sql/$$f $(srcdir)/$$f; \
diff --git a/libmysql/Makefile.shared b/libmysql/Makefile.shared
index a1020709d22..0f7cb713d54 100644
--- a/libmysql/Makefile.shared
+++ b/libmysql/Makefile.shared
@@ -39,9 +39,10 @@ mystringsobjects = strmov.lo strxmov.lo strxnmov.lo strnmov.lo \
bchange.lo bmove.lo bmove_upp.lo longlong2str.lo \
strtoull.lo strtoll.lo llstr.lo \
ctype.lo ctype-simple.lo ctype-mb.lo \
- ctype-big5.lo ctype-czech.lo ctype-euc_kr.lo ctype-win1250ch.lo\
+ ctype-big5.lo ctype-czech.lo ctype-euc_kr.lo \
+ ctype-win1250ch.lo ctype-utf8.lo \
ctype-gb2312.lo ctype-gbk.lo ctype-latin1_de.lo \
- ctype-sjis.lo ctype-tis620.lo ctype-ujis.lo ctype-utf8.lo
+ ctype-sjis.lo ctype-tis620.lo ctype-ujis.lo
mystringsextra= strto.c
dbugobjects = dbug.lo # IT IS IN SAFEMALLOC.C sanity.lo
diff --git a/libmysql/errmsg.c b/libmysql/errmsg.c
index f1cf667f774..581bb184ff3 100644
--- a/libmysql/errmsg.c
+++ b/libmysql/errmsg.c
@@ -52,15 +52,13 @@ const char *client_errors[]=
"Error connecting to master:",
"Invalid connection handle",
"Invalid use of null pointer",
- "Memory allocation error",
"Statement not prepared",
"Not all parameters data supplied",
"Data truncated",
- "Not all parameters bound for the row fetch",
- "Failed to send the parameter data",
"No parameters exists in the statement",
"Invalid parameter number",
- "Can't send long data for non string or binary data types"
+ "Can't send long data for non string or binary data types (parameter: %d)",
+ "Using not supported parameter type: %d (parameter: %d)"
};
/* Start of code added by Roberto M. Serqueira - martinsc@uol.com.br - 05.24.2001 */
@@ -96,15 +94,13 @@ const char *client_errors[]=
"Error connecting to master:",
"Invalid connection handle",
"Invalid use of null pointer",
- "Memory allocation error",
"Statement not prepared",
"Not all parameters data supplied",
"Data truncated",
- "Not all parameters bound for the row fetch",
- "Failed to send the parameter data",
"No parameters exists in the statement",
"Invalid parameter number",
- "Can't send long data for non string or binary data types"
+ "Can't send long data for non string or binary data types (parameter: %d)",
+ "Using not supported parameter type: %d (parameter: %d)"
};
#else /* ENGLISH */
@@ -138,15 +134,13 @@ const char *client_errors[]=
"Error connecting to master:",
"Invalid connection handle",
"Invalid use of null pointer",
- "Memory allocation error",
"Statement not prepared",
"Not all parameters data supplied",
"Data truncated",
- "Not all parameters bound for the row fetch",
- "Failed to send the parameter data",
"No parameters exists in the statement",
"Invalid parameter number",
- "Can't send long data for non string or binary data types"
+ "Can't send long data for non string or binary data types (parameter: %d)",
+ "Using not supported parameter type: %d (parameter: %d)"
};
#endif
diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c
index 052907d8c28..16fecc8038f 100644
--- a/libmysql/libmysql.c
+++ b/libmysql/libmysql.c
@@ -31,6 +31,7 @@
#include <sys/stat.h>
#include <signal.h>
#include <time.h>
+#include <assert.h> /* for DBUG_ASSERT() */
#ifdef HAVE_PWD_H
#include <pwd.h>
#endif
@@ -56,8 +57,6 @@
#define INADDR_NONE -1
#endif
-#include <assert.h> /* for DBUG_ASSERT() */
-
static my_bool mysql_client_init=0;
uint mysql_port=0;
my_string mysql_unix_port=0;
@@ -66,9 +65,9 @@ ulong max_allowed_packet=16*1024*1024L;
ulong net_read_timeout= NET_READ_TIMEOUT;
ulong net_write_timeout= NET_WRITE_TIMEOUT;
-#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG\
- | CLIENT_LOCAL_FILES | CLIENT_TRANSACTIONS\
- | CLIENT_PROTOCOL_41)
+#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG \
+ | CLIENT_LOCAL_FILES | CLIENT_TRANSACTIONS \
+ | CLIENT_PROTOCOL_41)
#ifdef __WIN__
@@ -85,10 +84,11 @@ ulong net_write_timeout= NET_WRITE_TIMEOUT;
#define SOCKET_ERROR -1
#endif /* __WIN__ */
-#define MAX_LONG_DATA_LENGTH 8192 /* if allowed through some
- configuration, then this needs to
- be changed
- */
+/*
+ If allowed through some configuration, then this needs to
+ be changed
+*/
+#define MAX_LONG_DATA_LENGTH 8192
#define protocol_41(A) ((A)->server_capabilities & CLIENT_PROTOCOL_41)
#define unsigned_field(A) ((A)->flags & UNSIGNED_FLAG)
@@ -101,7 +101,7 @@ static void end_server(MYSQL *mysql);
static void read_user_name(char *name);
static void append_wild(char *to,char *end,const char *wild);
static my_bool mysql_reconnect(MYSQL *mysql);
-static int send_file_to_server(MYSQL *mysql,const char *filename);
+static my_bool send_file_to_server(MYSQL *mysql,const char *filename);
static sig_handler pipe_sig_handler(int sig);
static ulong mysql_sub_escape_string(CHARSET_INFO *charset_info, char *to,
const char *from, ulong length);
@@ -160,7 +160,7 @@ static MYSQL* spawn_init(MYSQL* parent, const char* host,
/****************************************************************************
- A modified version of connect(). connect2() allows you to specify
+ A modified version of connect(). my_connect() allows you to specify
a timeout value, in seconds, that we should wait until we
derermine we can't connect to a particular host. If timeout is 0,
my_connect() will behave exactly like connect().
@@ -168,11 +168,11 @@ static MYSQL* spawn_init(MYSQL* parent, const char* host,
Base version coded by Steve Bernacki, Jr. <steve@navinet.net>
*****************************************************************************/
-int my_connect(my_socket s, const struct sockaddr *name, uint namelen,
- uint timeout)
+my_bool my_connect(my_socket s, const struct sockaddr *name,
+ uint namelen, uint timeout)
{
#if defined(__WIN__) || defined(OS2)
- return connect(s, (struct sockaddr*) name, namelen);
+ return connect(s, (struct sockaddr*) name, namelen) != 0;
#else
int flags, res, s_err;
SOCKOPT_OPTLEN_TYPE s_err_size = sizeof(uint);
@@ -185,7 +185,7 @@ int my_connect(my_socket s, const struct sockaddr *name, uint namelen,
*/
if (timeout == 0)
- return connect(s, (struct sockaddr*) name, namelen);
+ return connect(s, (struct sockaddr*) name, namelen) != 0;
flags = fcntl(s, F_GETFL, 0); /* Set socket to not block */
#ifdef O_NONBLOCK
@@ -198,7 +198,7 @@ int my_connect(my_socket s, const struct sockaddr *name, uint namelen,
if ((res != 0) && (s_err != EINPROGRESS))
{
errno = s_err; /* Restore it */
- return(-1);
+ return(1);
}
if (res == 0) /* Connected quickly! */
return(0);
@@ -243,7 +243,7 @@ int my_connect(my_socket s, const struct sockaddr *name, uint namelen,
now_time=time(NULL);
timeout-= (uint) (now_time - start_time);
if (errno != EINTR || (int) timeout <= 0)
- return -1;
+ return 1;
}
/* select() returned something more interesting than zero, let's
@@ -253,12 +253,12 @@ int my_connect(my_socket s, const struct sockaddr *name, uint namelen,
s_err=0;
if (getsockopt(s, SOL_SOCKET, SO_ERROR, (char*) &s_err, &s_err_size) != 0)
- return(-1);
+ return(1);
if (s_err)
{ /* getsockopt could succeed */
errno = s_err;
- return(-1); /* but return an error... */
+ return(1); /* but return an error... */
}
return(0); /* It's all good! */
#endif
@@ -464,44 +464,45 @@ static void free_rows(MYSQL_DATA *cur)
}
-int
-simple_command(MYSQL *mysql,enum enum_server_command command, const char *arg,
- ulong length, my_bool skipp_check)
+static my_bool
+advanced_command(MYSQL *mysql, enum enum_server_command command,
+ const char *header, ulong header_length,
+ const char *arg, ulong arg_length, my_bool skip_check)
{
NET *net= &mysql->net;
- int result= -1;
+ my_bool result= 1;
init_sigpipe_variables
/* Don't give sigpipe errors if the client doesn't want them */
set_sigpipe(mysql);
+
if (mysql->net.vio == 0)
{ /* Do reconnect if possible */
if (mysql_reconnect(mysql))
- goto end;
+ return 1;
}
if (mysql->status != MYSQL_STATUS_READY)
{
strmov(net->last_error,ER(mysql->net.last_errno=CR_COMMANDS_OUT_OF_SYNC));
- goto end;
+ return 1;
}
mysql->net.last_error[0]=0;
mysql->net.last_errno=0;
mysql->info=0;
mysql->affected_rows= ~(my_ulonglong) 0;
- net_clear(net); /* Clear receive buffer */
- if (!arg)
- arg="";
+ net_clear(&mysql->net); /* Clear receive buffer */
- if (net_write_command(net,(uchar) command,arg,
- length ? length : (ulong) strlen(arg)))
+ if (net_write_command(net,(uchar) command, header, header_length,
+ arg, 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));
end_server(mysql);
if (mysql_reconnect(mysql))
goto end;
- if (net_write_command(net,(uchar) command,arg,
- length ? length : (ulong) strlen(arg)))
+ if (net_write_command(net,(uchar) command, header, header_length,
+ arg, arg_length))
{
net->last_errno=CR_SERVER_GONE_ERROR;
strmov(net->last_error,ER(net->last_errno));
@@ -509,15 +510,23 @@ simple_command(MYSQL *mysql,enum enum_server_command command, const char *arg,
}
}
result=0;
- if (!skipp_check)
+ if (!skip_check)
result= ((mysql->packet_length=net_safe_read(mysql)) == packet_error ?
- -1 : 0);
+ 1 : 0);
end:
reset_sigpipe(mysql);
return result;
}
+my_bool
+simple_command(MYSQL *mysql,enum enum_server_command command, const char *arg,
+ ulong length, my_bool skip_check)
+{
+ return advanced_command(mysql, command, NullS, 0, arg, length, skip_check);
+}
+
+
static void free_old_query(MYSQL *mysql)
{
DBUG_ENTER("free_old_query");
@@ -529,6 +538,7 @@ static void free_old_query(MYSQL *mysql)
DBUG_VOID_RETURN;
}
+
#if defined(HAVE_GETPWUID) && defined(NO_GETPWUID_DECL)
struct passwd *getpwuid(uid_t);
char* getlogin(void);
@@ -606,7 +616,6 @@ append_wild(char *to, char *end, const char *wild)
}
-
/**************************************************************************
Init debugging if MYSQL_DEBUG environment variable is found
**************************************************************************/
@@ -691,13 +700,13 @@ mysql_free_result(MYSQL_RES *result)
{
if (result->handle && result->handle->status == MYSQL_STATUS_USE_RESULT)
{
- DBUG_PRINT("warning",("Not all rows in set were read; Ignoring rows"));
+ DBUG_PRINT("warning",("Not all rows in set where read; Ignoring rows"));
for (;;)
{
ulong pkt_len;
if ((pkt_len=net_safe_read(result->handle)) == packet_error)
break;
- if (pkt_len == 1 && result->handle->net.read_pos[0] == 254)
+ if (pkt_len <= 8 && result->handle->net.read_pos[0] == 254)
break; /* End of data */
}
result->handle->status=MYSQL_STATUS_READY;
@@ -906,9 +915,11 @@ unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields,
field=result=(MYSQL_FIELD*) alloc_root(alloc,
(uint) sizeof(MYSQL_FIELD)*fields);
if (!result)
+ {
+ free_rows(data); /* Free old data */
DBUG_RETURN(0);
-
- if(server_capabilities & CLIENT_PROTOCOL_41)
+ }
+ if (server_capabilities & CLIENT_PROTOCOL_41)
{
/* server is 4.1, and returns the new field result format */
for (row=data->data; row ; row = row->next,field++)
@@ -933,8 +944,10 @@ unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields,
field->max_length= 0;
}
}
- else /* old ones, for backward compatibility */
+#ifndef DELETE_SUPPORT_OF_4_0_PROTOCOL
+ else
{
+ /* old protocol, for backward compatibility */
for (row=data->data; row ; row = row->next,field++)
{
field->org_table= field->table= strdup_root(alloc,(char*) row->data[0]);
@@ -961,6 +974,7 @@ unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields,
field->max_length= 0;
}
}
+#endif /* DELETE_SUPPORT_OF_4_0_PROTOCOL */
free_rows(data); /* Free old data */
DBUG_RETURN(result);
}
@@ -996,14 +1010,22 @@ static MYSQL_DATA *read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
result->rows=0;
result->fields=fields;
- while (*(cp=net->read_pos) != 254 || pkt_len != 1)
+ /*
+ The last EOF packet is either a single 254 character or (in MySQL 4.1)
+ 254 followed by 1-7 status bytes.
+
+ This doesn't conflict with normal usage of 254 which stands for a
+ string where the length of the string is 8 bytes. (see net_field_length())
+ */
+
+ while (*(cp=net->read_pos) != 254 || pkt_len >= 8)
{
result->rows++;
if (!(cur= (MYSQL_ROWS*) alloc_root(&result->alloc,
- sizeof(MYSQL_ROWS))) ||
+ sizeof(MYSQL_ROWS))) ||
!(cur->data= ((MYSQL_ROW)
alloc_root(&result->alloc,
- (fields+1)*sizeof(char *)+pkt_len))))
+ (fields+1)*sizeof(char *)+pkt_len))))
{
free_rows(result);
net->last_errno=CR_OUT_OF_MEMORY;
@@ -1040,6 +1062,11 @@ static MYSQL_DATA *read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
}
}
*prev_ptr=0; /* last pointer is null */
+ if (pkt_len > 1) /* MySQL 4.1 protocol */
+ {
+ mysql->warning_count= uint2korr(cp+1);
+ DBUG_PRINT("info",("warning_count: %ld", mysql->warning_count));
+ }
DBUG_PRINT("exit",("Got %d rows",result->rows));
DBUG_RETURN(result);
}
@@ -1060,8 +1087,12 @@ read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row, ulong *lengths)
if ((pkt_len=net_safe_read(mysql)) == packet_error)
return -1;
- if (pkt_len == 1 && mysql->net.read_pos[0] == 254)
+ if (pkt_len <= 8 && mysql->net.read_pos[0] == 254)
+ {
+ if (pkt_len > 1) /* MySQL 4.1 protocol */
+ mysql->warning_count= uint2korr(mysql->net.read_pos+1);
return 1; /* End of data */
+ }
prev_pos= 0; /* allowed to write at packet[-1] */
pos=mysql->net.read_pos;
for (field=0 ; field < fields ; field++)
@@ -1087,7 +1118,7 @@ read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row, ulong *lengths)
}
/* perform query on master */
-int STDCALL mysql_master_query(MYSQL *mysql, const char *q,
+my_bool STDCALL mysql_master_query(MYSQL *mysql, const char *q,
unsigned long length)
{
if (mysql_master_send_query(mysql, q, length))
@@ -1095,8 +1126,8 @@ int STDCALL mysql_master_query(MYSQL *mysql, const char *q,
return mysql_read_query_result(mysql);
}
-int STDCALL mysql_master_send_query(MYSQL *mysql, const char *q,
- unsigned long length)
+my_bool STDCALL mysql_master_send_query(MYSQL *mysql, const char *q,
+ unsigned long length)
{
MYSQL*master = mysql->master;
if (!length)
@@ -1109,15 +1140,16 @@ int STDCALL mysql_master_send_query(MYSQL *mysql, const char *q,
/* perform query on slave */
-int STDCALL mysql_slave_query(MYSQL *mysql, const char *q,
- unsigned long length)
+my_bool STDCALL mysql_slave_query(MYSQL *mysql, const char *q,
+ unsigned long length)
{
if (mysql_slave_send_query(mysql, q, length))
return 1;
return mysql_read_query_result(mysql);
}
-int STDCALL mysql_slave_send_query(MYSQL *mysql, const char *q,
+
+my_bool STDCALL mysql_slave_send_query(MYSQL *mysql, const char *q,
unsigned long length)
{
MYSQL* last_used_slave, *slave_to_use = 0;
@@ -1169,7 +1201,7 @@ void STDCALL mysql_disable_reads_from_master(MYSQL* mysql)
}
/* get the value of the master read flag */
-int STDCALL mysql_reads_from_master_enabled(MYSQL* mysql)
+my_bool STDCALL mysql_reads_from_master_enabled(MYSQL* mysql)
{
return !(mysql->options.no_master_reads);
}
@@ -1198,7 +1230,7 @@ static void expand_error(MYSQL* mysql, int error)
read the given result and row
*/
-static int get_master(MYSQL* mysql, MYSQL_RES* res, MYSQL_ROW row)
+static my_bool get_master(MYSQL* mysql, MYSQL_RES* res, MYSQL_ROW row)
{
MYSQL* master;
DBUG_ENTER("get_master");
@@ -1218,11 +1250,11 @@ static int get_master(MYSQL* mysql, MYSQL_RES* res, MYSQL_ROW row)
retrieve all the slaves
*/
-static int get_slaves_from_master(MYSQL* mysql)
+static my_bool get_slaves_from_master(MYSQL* mysql)
{
MYSQL_RES* res = 0;
MYSQL_ROW row;
- int error = 1;
+ my_bool error = 1;
int has_auth_info;
int port_ind;
DBUG_ENTER("get_slaves_from_master");
@@ -1285,11 +1317,11 @@ err:
}
-int STDCALL mysql_rpl_probe(MYSQL* mysql)
+my_bool STDCALL mysql_rpl_probe(MYSQL* mysql)
{
MYSQL_RES *res= 0;
MYSQL_ROW row;
- int error = 1;
+ my_bool error= 1;
DBUG_ENTER("mysql_rpl_probe");
/*
@@ -1473,7 +1505,7 @@ static void mysql_once_init()
#define strdup_if_not_null(A) (A) == 0 ? 0 : my_strdup((A),MYF(MY_WME))
-int STDCALL
+my_bool STDCALL
mysql_ssl_set(MYSQL *mysql __attribute__((unused)) ,
const char *key __attribute__((unused)),
const char *cert __attribute__((unused)),
@@ -1497,7 +1529,7 @@ mysql_ssl_set(MYSQL *mysql __attribute__((unused)) ,
NB! Errors are not reported until you do mysql_real_connect.
**************************************************************************/
-static int
+static void
mysql_ssl_free(MYSQL *mysql __attribute__((unused)))
{
#ifdef HAVE_OPENSSL
@@ -1515,7 +1547,6 @@ mysql_ssl_free(MYSQL *mysql __attribute__((unused)))
mysql->options.use_ssl = FALSE;
mysql->connector_fd = 0;
#endif /* HAVE_OPENSSL */
- return 0;
}
/**************************************************************************
@@ -1635,7 +1666,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
UNIXaddr.sun_family = AF_UNIX;
strmov(UNIXaddr.sun_path, unix_socket);
if (my_connect(sock,(struct sockaddr *) &UNIXaddr, sizeof(UNIXaddr),
- mysql->options.connect_timeout) <0)
+ mysql->options.connect_timeout))
{
DBUG_PRINT("error",("Got error %d on connect to local server",socket_errno));
net->last_errno=CR_CONNECTION_ERROR;
@@ -2264,7 +2295,7 @@ mysql_send_query(MYSQL* mysql, const char* query, ulong length)
}
-int STDCALL mysql_read_query_result(MYSQL *mysql)
+my_bool STDCALL mysql_read_query_result(MYSQL *mysql)
{
uchar *pos;
ulong field_count;
@@ -2272,13 +2303,14 @@ int STDCALL mysql_read_query_result(MYSQL *mysql)
ulong length;
DBUG_ENTER("mysql_read_query_result");
- /* read from the connection which we actually used, which
- could differ from the original connection if we have slaves
- */
+ /*
+ Read from the connection which we actually used, which
+ could differ from the original connection if we have slaves
+ */
mysql = mysql->last_used_con;
if ((length = net_safe_read(mysql)) == packet_error)
- DBUG_RETURN(-1);
+ DBUG_RETURN(1);
free_old_query(mysql); /* Free old result */
get_info:
pos=(uchar*) mysql->net.read_pos;
@@ -2286,10 +2318,18 @@ get_info:
{
mysql->affected_rows= net_field_length_ll(&pos);
mysql->insert_id= net_field_length_ll(&pos);
- if (mysql->server_capabilities & CLIENT_TRANSACTIONS)
+ if (mysql->server_capabilities & CLIENT_PROTOCOL_41)
{
mysql->server_status=uint2korr(pos); pos+=2;
+ mysql->warning_count=uint2korr(pos); pos+=2;
}
+ else if (mysql->server_capabilities & CLIENT_TRANSACTIONS)
+ {
+ mysql->server_status=uint2korr(pos); pos+=2;
+ mysql->warning_count= 0;
+ }
+ DBUG_PRINT("info",("status: %ld warning_count: %ld",
+ mysql->server_status, mysql->warning_count));
if (pos < mysql->net.read_pos+length && net_field_length(&pos))
mysql->info=(char*) pos;
DBUG_RETURN(0);
@@ -2298,7 +2338,7 @@ get_info:
{
int error=send_file_to_server(mysql,(char*) pos);
if ((length=net_safe_read(mysql)) == packet_error || error)
- DBUG_RETURN(-1);
+ DBUG_RETURN(1);
goto get_info; /* Get info packet */
}
if (!(mysql->server_status & SERVER_STATUS_AUTOCOMMIT))
@@ -2306,14 +2346,15 @@ get_info:
mysql->extra_info= net_field_length_ll(&pos); /* Maybe number of rec */
- if (!(fields=read_rows(mysql,(MYSQL_FIELD*)0,protocol_41(mysql) ? 8:5)))
- DBUG_RETURN(-1);
+ if (!(fields=read_rows(mysql,(MYSQL_FIELD*)0, (protocol_41(mysql) ? 8 : 5))))
+ DBUG_RETURN(1);
if (!(mysql->fields=unpack_fields(fields,&mysql->field_alloc,
(uint) field_count,0,
mysql->server_capabilities)))
- DBUG_RETURN(-1);
- mysql->status=MYSQL_STATUS_GET_RESULT;
+ DBUG_RETURN(1);
+ mysql->status= MYSQL_STATUS_GET_RESULT;
mysql->field_count= (uint) field_count;
+ mysql->warning_count= 0;
DBUG_RETURN(0);
}
@@ -2326,15 +2367,16 @@ mysql_real_query(MYSQL *mysql, const char *query, ulong length)
DBUG_PRINT("query",("Query = \"%s\"",query));
if (mysql_send_query(mysql,query,length))
- DBUG_RETURN(-1);
- DBUG_RETURN(mysql_read_query_result(mysql));
+ DBUG_RETURN(1);
+ DBUG_RETURN((int) mysql_read_query_result(mysql));
}
-static int
+static my_bool
send_file_to_server(MYSQL *mysql, const char *filename)
{
- int fd, readcount, result= -1;
+ int fd, readcount;
+ my_bool result= 1;
uint packet_length=MY_ALIGN(mysql->net.max_packet-16,IO_SIZE);
char *buf, tmp_name[FN_REFLEN];
DBUG_ENTER("send_file_to_server");
@@ -2342,7 +2384,7 @@ send_file_to_server(MYSQL *mysql, const char *filename)
if (!(buf=my_malloc(packet_length,MYF(0))))
{
strmov(mysql->net.last_error, ER(mysql->net.last_errno=CR_OUT_OF_MEMORY));
- DBUG_RETURN(-1);
+ DBUG_RETURN(1);
}
fn_format(tmp_name,filename,"","",4); /* Convert to client format */
@@ -2675,7 +2717,8 @@ mysql_list_fields(MYSQL *mysql, const char *table, const char *wild)
end=strmake(strmake(buff, table,128)+1,wild ? wild : "",128);
if (simple_command(mysql,COM_FIELD_LIST,buff,(ulong) (end-buff),1) ||
- !(query = read_rows(mysql,(MYSQL_FIELD*)0,protocol_41(mysql) ? 9:6)))
+ !(query = read_rows(mysql,(MYSQL_FIELD*) 0,
+ (protocol_41(mysql) ? 9 : 6))))
DBUG_RETURN(NULL);
free_old_query(mysql);
@@ -2689,11 +2732,13 @@ mysql_list_fields(MYSQL *mysql, const char *table, const char *wild)
mysql->fields=0;
result->field_count = (uint) query->rows;
result->fields= unpack_fields(query,&result->field_alloc,
- result->field_count,1,mysql->server_capabilities);
+ result->field_count, 1,
+ mysql->server_capabilities);
result->eof=1;
DBUG_RETURN(result);
}
+
/* List all running processes (threads) in server */
MYSQL_RES * STDCALL
@@ -2869,7 +2914,7 @@ mysql_options(MYSQL *mysql,enum mysql_option option, const char *arg)
mysql->options.charset_name=my_strdup(arg,MYF(MY_WME));
break;
default:
- DBUG_RETURN(-1);
+ DBUG_RETURN(1);
}
DBUG_RETURN(0);
}
@@ -2942,6 +2987,11 @@ const char * STDCALL mysql_error(MYSQL *mysql)
return mysql->net.last_error;
}
+uint STDCALL mysql_warning_count(MYSQL *mysql)
+{
+ return mysql->warning_count;
+}
+
const char *STDCALL mysql_info(MYSQL *mysql)
{
return mysql->info;
@@ -2967,6 +3017,18 @@ uint STDCALL mysql_thread_safe(void)
#endif
}
+MYSQL_RES *STDCALL mysql_warnings(MYSQL *mysql)
+{
+ uint warning_count;
+ DBUG_ENTER("mysql_warnings");
+ /* Save warning count as mysql_real_query may change this */
+ warning_count= mysql->warning_count;
+ if (mysql_real_query(mysql, "SHOW WARNINGS", 13))
+ DBUG_RETURN(0);
+ mysql->warning_count= warning_count;
+ DBUG_RETURN(mysql_store_result(mysql));
+}
+
/****************************************************************************
Some support functions
****************************************************************************/
@@ -3170,7 +3232,6 @@ myodbc_remove_escape(MYSQL *mysql,char *name)
Implementation of new client-server prototypes for 4.1 version
starts from here ..
- my_* and genaral function names are internal implementations
mysql_* are real prototypes used by applications
*********************************************************************/
@@ -3180,212 +3241,169 @@ myodbc_remove_escape(MYSQL *mysql,char *name)
********************************************************************/
/*
- Set the internal stmt error messages
+ Set the internal stmt error messages
*/
static void set_stmt_error(MYSQL_STMT * stmt, int errcode)
{
DBUG_ENTER("set_stmt_error");
- DBUG_PRINT("enter", ("error :[%d][%s]", errcode, ER(errcode)));
+ DBUG_PRINT("enter", ("error: %d '%s'", errcode, ER(errcode)));
DBUG_ASSERT(stmt != 0);
- stmt->err_no = errcode;
- strmov(stmt->error, ER(errcode));
+ stmt->last_errno= errcode;
+ strmov(stmt->last_error, ER(errcode));
DBUG_VOID_RETURN;
}
+
/*
- Copy error message to statement handler
+ Copy error message to statement handler
*/
static void set_stmt_errmsg(MYSQL_STMT * stmt, char *err, int errcode)
{
DBUG_ENTER("set_stmt_error_msg");
- DBUG_PRINT("enter", ("error :[%d][%s]", errcode, err));
+ DBUG_PRINT("enter", ("error: %d '%s'", errcode, err));
DBUG_ASSERT(stmt != 0);
- stmt->err_no = errcode;
-
+ stmt->last_errno= errcode;
if (err && err[0])
- strmov(stmt->error, err);
+ strmov(stmt->last_error, err);
DBUG_VOID_RETURN;
}
+
/*
- Set the internal error message to mysql handler
+ Set the internal error message to mysql handler
*/
static void set_mysql_error(MYSQL * mysql, int errcode)
{
DBUG_ENTER("set_mysql_error");
- DBUG_PRINT("enter", ("error :[%d][%s]", errcode, ER(errcode)));
+ DBUG_PRINT("enter", ("error :%d '%s'", errcode, ER(errcode)));
DBUG_ASSERT(mysql != 0);
- mysql->net.last_errno = errcode;
+ mysql->net.last_errno= errcode;
strmov(mysql->net.last_error, ER(errcode));
}
-/*
- Return the duplicate string by allocating the memory
-*/
-
-static char *my_dupp_str(const char *from, int length)
-{
- char *str;
-
- if ((str = my_malloc(length + 1, MYF(MY_WME))))
- {
- memcpy(str, from, length);
- str[length] = 0;
- }
- return str;
-}
-
/*
- Return the reallocted string
-*/
+ Reallocate the NET package to be at least of 'length' bytes
-static char *my_realloc_str(NET *net, int length)
-{
- char *from = net->buff;
- ulong nead = net->buf_length + length;
- DBUG_ENTER("my_realloc_str");
+ SYNPOSIS
+ my_realloc_str()
+ net The NET structure to modify
+ int length Ensure that net->buff is at least this big
- if ( nead > net->max_packet )
- {
- char *new_buff;
- ulong pkt_length = nead + 8192;
-
- if (pkt_length > max_allowed_packet)
- {
- DBUG_PRINT("error",("Needed %ld but max_allowed_packet is %ld",
- pkt_length,max_allowed_packet));
- DBUG_RETURN(0);
- }
- if (!(new_buff = (char *)my_realloc(from, pkt_length, MYF(MY_WME))))
- DBUG_RETURN(0);
+ RETURN VALUES
+ 0 ok
+ 1 Error
- net->max_packet = pkt_length;
- DBUG_RETURN(new_buff);
- }
- DBUG_RETURN(from);
-}
-
-/*
- Return the type length
*/
-static ulong return_result_length(uint field_type, ulong length)
+static my_bool my_realloc_str(NET *net, ulong length)
{
- switch (field_type) {
- case MYSQL_TYPE_TINY:
- return 1;
- case MYSQL_TYPE_SHORT:
- return 2;
- case MYSQL_TYPE_INT24:
- return 3;
- case MYSQL_TYPE_LONG:
- return 4;
- case MYSQL_TYPE_LONGLONG:
- return 8;
- case MYSQL_TYPE_FLOAT:
- return 4;
- case MYSQL_TYPE_DOUBLE:
- return 8;
- default:
- return length;
- }
-}
-
-/*
- Get the parameter count value
-*/
-
-static ulong my_get_param_count(MYSQL *mysql)
-{
- uchar *pos;
-
- mysql = mysql->last_used_con;
-
- if (net_safe_read(mysql) == packet_error)
- return 0;
-
- pos=(uchar*) mysql->net.read_pos;
- if (!net_field_length(&pos))
+ ulong buf_length= (ulong) (net->write_pos - net->buff);
+ my_bool res=0;
+ DBUG_ENTER("my_realloc_str");
+ if (buf_length + length > net->max_packet)
{
- return (ulong)net_field_length(&pos);
+ res= net_realloc(net, buf_length + length);
+ net->write_pos= net->buff+ buf_length;
}
- return 0;
+ DBUG_RETURN(res);
}
/********************************************************************
- Prepare related implementations
+ Prepare related implementations
********************************************************************/
/*
Read the prepare statement results ..
+
+ NOTE
+ This is only called for connection to servers that supports
+ prepared statements (and thus the 4.1 protocol)
+
+ RETURN VALUES
+ 0 ok
+ 1 error
*/
-int my_read_prepare_result(MYSQL *mysql,MYSQL_STMT *stmt)
+static my_bool read_prepare_result(MYSQL *mysql, MYSQL_STMT *stmt)
{
uchar *pos;
- ulong field_count;
+ uint field_count;
MYSQL_DATA *fields_data;
ulong length;
+ DBUG_ENTER("read_prepare_result");
- DBUG_ENTER("my_read_prepare_result");
+ mysql= mysql->last_used_con;
+ if ((length= net_safe_read(mysql)) == packet_error)
+ DBUG_RETURN(1);
- mysql = mysql->last_used_con;
+ pos=(uchar*) mysql->net.read_pos;
+ stmt->stmt_id= uint4korr(pos); pos+=4;
+ field_count= uint2korr(pos); pos+=2;
+ stmt->param_count=uint2korr(pos); pos+=2;
- if ((length = net_safe_read(mysql)) == packet_error)
- DBUG_RETURN(-1);
-
- if (stmt->fields)
- free_root(&stmt->mem_root,MYF(0));
- init_alloc_root(&stmt->mem_root,8192,0);
- stmt->fields=0;
- stmt->field_count=0;
+ if (field_count != 0)
+ {
+ if (!(mysql->server_status & SERVER_STATUS_AUTOCOMMIT))
+ mysql->server_status|= SERVER_STATUS_IN_TRANS;
- pos=(uchar*) mysql->net.read_pos;
- if ((field_count= net_field_length(&pos)) == 0)
+ mysql->extra_info= net_field_length_ll(&pos);
+ if (!(fields_data= read_rows(mysql, (MYSQL_FIELD*) 0, 8)))
+ DBUG_RETURN(1);
+ if (!(stmt->fields= unpack_fields(fields_data,&stmt->mem_root,
+ field_count,0,
+ mysql->server_capabilities)))
+ DBUG_RETURN(1);
+ }
+ if (!(stmt->params= (MYSQL_BIND *) alloc_root(&stmt->mem_root,
+ sizeof(MYSQL_BIND)*
+ (stmt->param_count +
+ field_count))))
{
- stmt->param_count= (ulong)net_field_length_ll(&pos);
+ set_stmt_error(stmt, CR_OUT_OF_MEMORY);
DBUG_RETURN(0);
}
- if (!(mysql->server_status & SERVER_STATUS_AUTOCOMMIT))
- mysql->server_status|= SERVER_STATUS_IN_TRANS;
-
- mysql->extra_info= net_field_length_ll(&pos);
-
- if (!(fields_data=read_rows(mysql,(MYSQL_FIELD*)0,protocol_41(mysql) ? 8:5)))
- DBUG_RETURN(-1);
-
- if (!(stmt->fields=unpack_fields(fields_data,&stmt->mem_root,
- (uint) field_count,0,
- mysql->server_capabilities)))
- DBUG_RETURN(-1);
- mysql->status = MYSQL_STATUS_READY;
- stmt->field_count= (uint) field_count;
+ stmt->bind= (stmt->params + stmt->param_count);
+ stmt->field_count= (uint) field_count;
+ mysql->status= MYSQL_STATUS_READY;
DBUG_RETURN(0);
}
/*
- Prepare the query and return the new statement handle to
- caller.
-
- Also update the total parameter count along with resultset
- metadata information by reading from server
+ Prepare the query and return the new statement handle to
+ caller.
+
+ Also update the total parameter count along with resultset
+ metadata information by reading from server
*/
-MYSQL_STMT *STDCALL
-mysql_real_prepare(MYSQL *mysql, const char *query, ulong length)
+/* QQ The follwing function will be removed after next merge */
+
+static char *my_strdup_with_length(const byte *from, uint length, myf MyFlags)
+{
+ gptr ptr;
+ if ((ptr=my_malloc(length+1,MyFlags)) != 0)
+ {
+ memcpy((byte*) ptr, (byte*) from,(size_t) length);
+ ((char*) ptr)[length]=0;
+ }
+ return((char*) ptr);
+}
+
+
+MYSQL_STMT *STDCALL
+mysql_prepare(MYSQL *mysql, const char *query, ulong length)
{
MYSQL_STMT *stmt;
-
DBUG_ENTER("mysql_real_prepare");
DBUG_ASSERT(mysql != 0);
@@ -3397,59 +3415,39 @@ mysql_real_prepare(MYSQL *mysql, const char *query, ulong length)
}
#endif
- if (simple_command(mysql, COM_PREPARE, query, length, 1))
+ if (!(stmt= (MYSQL_STMT *) my_malloc(sizeof(MYSQL_STMT),
+ MYF(MY_WME | MY_ZEROFILL))) ||
+ !(stmt->query= my_strdup_with_length((byte *) query, length, MYF(0))))
+ {
+ my_free((gptr) stmt, MYF(MY_ALLOW_ZERO_PTR));
+ set_mysql_error(mysql, CR_OUT_OF_MEMORY);
DBUG_RETURN(0);
-
- if (!(stmt = (MYSQL_STMT *) my_malloc(sizeof(MYSQL_STMT),
- MYF(MY_WME | MY_ZEROFILL))) ||
- !(stmt->query = my_dupp_str((char *)query, length)))
- {
- my_free((gptr)stmt, MY_ALLOW_ZERO_PTR);
- set_mysql_error(mysql, CR_MEMORY_ERROR);
+ }
+ if (simple_command(mysql, COM_PREPARE, query, length, 1))
+ {
+ mysql_stmt_close(stmt);
DBUG_RETURN(0);
}
+ stmt->state= MY_ST_PREPARE;
- DBUG_ASSERT(stmt != 0);
-
- if (my_read_prepare_result(mysql,stmt))
+ init_alloc_root(&stmt->mem_root,8192,0);
+ if (read_prepare_result(mysql, stmt))
{
- my_free((gptr)stmt, MYF(MY_WME));
+ mysql_stmt_close(stmt);
DBUG_RETURN(0);
}
-
- if (stmt->fields)
- stmt->param_count = my_get_param_count(mysql);
-
- stmt->mysql = mysql;
- stmt->state = MY_ST_PREPARE;
- stmt->err_no = 0;
- stmt->types_supplied = 0;
-
+
+ stmt->mysql= mysql;
DBUG_PRINT("info", ("Parameter count: %ld", stmt->param_count));
DBUG_RETURN(stmt);
}
-/*
- Prepare the query and return the new statement handle to
- caller.
-
- Also update the total parameter count along with resultset
- metadata information by reading from server
-*/
-
-MYSQL_STMT *STDCALL mysql_prepare(MYSQL *mysql, const char *query)
-{
- DBUG_ENTER("mysql_prepare");
- DBUG_ASSERT(query != 0);
- DBUG_RETURN(mysql_real_prepare(mysql,query,strlen(query)));
-}
/*
Returns prepared meta information in the form of resultset
- to client..
+ to client.
*/
-
MYSQL_RES * STDCALL
mysql_prepare_result(MYSQL_STMT *stmt)
{
@@ -3458,349 +3456,279 @@ mysql_prepare_result(MYSQL_STMT *stmt)
if (!stmt->fields)
DBUG_RETURN(0);
-
- /* Will be freed during mysql_stmt_close as the prepare
- meta info should live till the stmt life
- */
- if (!(result=(MYSQL_RES*) alloc_root(&stmt->mem_root,
- (uint) (sizeof(MYSQL_RES)+ sizeof(ulong) *
- stmt->field_count))))
- {
- set_stmt_error(stmt, CR_MEMORY_ERROR);
- DBUG_RETURN(0);
- }
+ result= &stmt->tmp_result;
bzero((char*) result, sizeof(MYSQL_RES));
- result->eof=1; /* Marker for buffered */
- result->lengths=(ulong*) (result+1);
- result->row_count= 0;
- result->fields= stmt->fields;
- result->field_count= stmt->field_count;
- DBUG_RETURN(result);
+ result->eof=1; /* Marker for buffered */
+ result->fields= stmt->fields;
+ result->field_count= stmt->field_count;
+ DBUG_RETURN(result);
}
+
/********************************************************************
Prepare-execute, and param handling
*********************************************************************/
-
-/*
- Store the buffer type
+/*
+ Store the buffer type
*/
-static void my_store_param_type(NET *net, uint type)
+static void store_param_type(NET *net, uint type)
{
- int2store(net->buff+net->buf_length, type);
- net->buf_length+=2;
+ int2store(net->write_pos, type);
+ net->write_pos+=2;
}
-/*
+/*
Store the length of parameter data
+ (Same function as in sql/net_pkg.cc)
*/
-static char * my_store_param_length(char *pkg, ulong length)
+
+char *
+net_store_length(char *pkg, ulong length)
{
uchar *packet=(uchar*) pkg;
-
if (length < 251)
{
*packet=(uchar) length;
return (char*) packet+1;
}
- *packet++ = 252;
- int2store(packet,(uint) length);
- return (char*) packet+2;
+ /* 251 is reserved for NULL */
+ if (length < 65536L)
+ {
+ *packet++=252;
+ int2store(packet,(uint) length);
+ return (char*) packet+2;
+ }
+ if (length < 16777216L)
+ {
+ *packet++=253;
+ int3store(packet,(ulong) length);
+ return (char*) packet+3;
+ }
+ *packet++=254;
+ int8store(packet, (ulonglong) length);
+ return (char*) packet+9;
}
-/*
- Store the integer data
-*/
-static bool my_store_param_long(NET *net, longlong *data, uint length)
-{
- char *packet;
+/****************************************************************************
+ Functions to store parameter data from a prepared statement.
- if (!(net->buff = my_realloc_str(net, net->buf_length + length + 1)))
- return 1;
+ All functions has the following characteristics:
- packet = (char *)net->buff+net->buf_length;
-
- switch(length) {
- case 1:
- {
- char value = (char)*data;
- *packet = value;
- }
- break;
- case 2:
- {
- short value = (short)*data;
- int2store(packet,value);
- }
- break;
- case 3:
- {
- int value = (int)*data;
- int3store(packet,value);
- }
- break;
- case 4:
- {
- long value = (long)*data;
- int4store(packet, value);
- }
- break;
- default:
- {
- longlong value = (longlong)*data;
- int8store(packet, value);
- }
- }
- net->buf_length += length;
- return 0;
+ SYNOPSIS
+ store_param_xxx()
+ net MySQL NET connection
+ param MySQL bind param
+
+ RETURN VALUES
+ 0 ok
+ 1 Error (Can't alloc net->buffer)
+****************************************************************************/
+
+
+static void store_param_tinyint(NET *net, MYSQL_BIND *param)
+{
+ *(net->write_pos++)= (uchar) *param->buffer;
}
-/*
- Store the float data
-*/
+static void store_param_short(NET *net, MYSQL_BIND *param)
+{
+ short value= *(short*) param->buffer;
+ int2store(net->write_pos,value);
+ net->write_pos+=2;
+}
-static bool my_store_param_double(NET *net, double *data, uint length)
+static void store_param_int32(NET *net, MYSQL_BIND *param)
{
- char *packet;
+ int32 value= *(int32*) param->buffer;
+ int4store(net->write_pos,value);
+ net->write_pos+=4;
+}
- if (!(net->buff = my_realloc_str(net, net->buf_length + length + 1)))
- return 1;
+static void store_param_int64(NET *net, MYSQL_BIND *param)
+{
+ longlong value= *(longlong*) param->buffer;
+ int8store(net->write_pos,value);
+ net->write_pos+= 8;
+}
- packet = (char *)net->buff+net->buf_length;
- if (length == 4)
- {
- float value = (float)*data;
- float4store(packet, value);
- }
- else
- {
- double value = (double)*data;
- float8store(packet, value);
- }
- net->buf_length += length;
- return 0;
+static void store_param_float(NET *net, MYSQL_BIND *param)
+{
+ float value= *(float*) param->buffer;
+ float4store(net->write_pos, value);
+ net->write_pos+= 4;
}
-/*
- Store NULL data
-*/
+static void store_param_double(NET *net, MYSQL_BIND *param)
+{
+ double value= *(double*) param->buffer;
+ float8store(net->write_pos, value);
+ net->write_pos+= 8;
+}
-static my_bool my_store_param_null(NET * net)
+static void store_param_str(NET *net, MYSQL_BIND *param)
{
- if (!(net->buff = my_realloc_str(net, net->buf_length + 1)))
- return 1; /* Signal error */
-
- net->buff[net->buf_length++] = (char)251;
- return 0;
+ ulong length= *param->length;
+ char *to= (char *) net_store_length((char *) net->write_pos, length);
+ memcpy(to, param->buffer, length);
+ net->write_pos+= length;
}
+
/*
- Store string and binary data
+ Mark if the parameter is NULL.
+
+ SYNOPSIS
+ store_param_null()
+ net MySQL NET connection
+ param MySQL bind param
+
+ DESCRIPTION
+ A data package starts with a string of bits where we set a bit
+ if a parameter is NULL
*/
-static my_bool my_store_param_str(NET * net, const char *from, uint length)
+static void store_param_null(NET *net, MYSQL_BIND *param)
{
- char *to;
+ uint pos= param->param_number;
+ (uchar) net->buff[pos/8]|= (1 << pos & 7);
+}
- if (!(net->buff = my_realloc_str(net, net->buf_length + 5 + length)))
- return 1;
- to = (char *)my_store_param_length((char *)net->buff + net->buf_length,
- (ulong) length);
- memcpy(to, from, length);
- net->buf_length = (ulong) ((char *)(to + length) - (char *)(net->buff));
- return 0;
-}
-
-
/*
Set parameter data by reading from input buffers from the
- client application
+ client application
*/
-static my_bool my_store_param(MYSQL_STMT * stmt, MYSQL_BIND * param)
+static my_bool store_param(MYSQL_STMT *stmt, MYSQL_BIND *param)
{
- MYSQL *mysql = stmt->mysql;
- NET *net = &mysql->net;
-
- DBUG_ENTER("my_store_param");
+ MYSQL *mysql= stmt->mysql;
+ NET *net = &mysql->net;
+ DBUG_ENTER("store_param");
DBUG_PRINT("enter",("type : %d, buffer :%lx", param->buffer_type,
param->buffer));
- if (!stmt->types_supplied)
- my_store_param_type(net, (uint)param->buffer_type);
-
- if (!param->buffer)
- {
- if (my_store_param_null(net))
- goto err;
-
- DBUG_RETURN(0);
- }
- switch (param->buffer_type)
- {
- case MYSQL_TYPE_TINY:
- case MYSQL_TYPE_SHORT:
- case MYSQL_TYPE_INT24:
- case MYSQL_TYPE_LONG:
- case MYSQL_TYPE_LONGLONG:
- if (my_store_param_long(net,(longlong *)param->buffer,param->bind_length))
- goto err;
- break;
-
- case MYSQL_TYPE_FLOAT:
- case MYSQL_TYPE_DOUBLE:
- if (my_store_param_double(net,(double *)param->buffer,param->bind_length))
- goto err;
- break;
-
- case MYSQL_TYPE_TINY_BLOB:
- case MYSQL_TYPE_MEDIUM_BLOB:
- case MYSQL_TYPE_LONG_BLOB:
- case MYSQL_TYPE_BLOB:
- {
- /*
- Binary handling, application should supply valid length else
- will lead into problems
- */
- ulong length = param->buffer_length;
- if(param->length) /* ovverite, if length pointer exists */
- length = *param->length;
- if (my_store_param_str(net, (char *)param->buffer, length))
- goto err;
- }
- break;
-
- default:
- {
- /* All other conversions should fall through to string type .. */
- char *data = param->buffer;
- ulong length;
-
- if (!param->length)
- {
- /*
- This case is not supose to happen, application should
- supply the length for strings and binary data
- */
- if (data)
- length = param->buffer_length ? strnlen(data,param->buffer_length) :
- strlen(data);
- else
- {
- DBUG_PRINT("warning",("data is a null pointer"));
- length=0;
- }
- }
- else
- length= *param->length;
-
- if (my_store_param_str(net,data,length))
- goto err;
- }
- }
- DBUG_RETURN(0);
-
-err:
- set_stmt_error(stmt, CR_MEMORY_ERROR);
+ /* Allocate for worst case (long string) */
+ if ((my_realloc_str(net, 9 + *param->length)))
+ return 1;
+ if (!param->buffer)
+ store_param_null(net, param);
+ else
+ (*param->store_param_func)(net, param);
DBUG_RETURN(1);
}
+
/*
Send the prepare query to server for execution
*/
-static int my_execute(MYSQL_STMT * stmt, char *packet, ulong length)
+static my_bool execute(MYSQL_STMT * stmt, char *packet, ulong length)
{
- MYSQL *mysql = stmt->mysql;
- NET *net = &mysql->net;
-
- DBUG_ENTER("my_execute");
+ MYSQL *mysql= stmt->mysql;
+ NET *net= &mysql->net;
+ char buff[4];
+ DBUG_ENTER("execute");
DBUG_PRINT("enter",("packet: %s, length :%d",packet ? packet :" ", length));
-
- mysql->last_used_con = mysql;
- if (simple_command(mysql, COM_EXECUTE, packet, length, 1) ||
+ mysql->last_used_con= mysql;
+ int4store(buff, stmt->stmt_id); /* Send stmt id to server */
+ if (advanced_command(mysql, COM_EXECUTE, buff, sizeof(buff), packet,
+ length, 1) ||
mysql_read_query_result(mysql))
{
set_stmt_errmsg(stmt, net->last_error, net->last_errno);
- DBUG_RETURN(-1);
+ DBUG_RETURN(1);
}
- stmt->state = MY_ST_EXECUTE;
+ stmt->state= MY_ST_EXECUTE;
if (stmt->bind)
{
mysql_free_result(stmt->result);
- stmt->result = mysql_store_result(mysql);
+ stmt->result= mysql_store_result(mysql);
}
DBUG_RETURN(0);
}
-/*
- Execute the prepare query
+
+/*
+ Execute the prepare query
*/
-int STDCALL mysql_execute(MYSQL_STMT * stmt)
+int STDCALL mysql_execute(MYSQL_STMT *stmt)
{
+ ulong length;
+ uint null_count;
DBUG_ENTER("mysql_execute");
- DBUG_ASSERT(stmt != 0);
if (stmt->state == MY_ST_UNKNOWN)
{
set_stmt_error(stmt, CR_NO_PREPARE_STMT);
- DBUG_RETURN(-1);
+ DBUG_RETURN(1);
}
- stmt->mysql->fields = stmt->fields;
+ stmt->mysql->fields= stmt->fields;
if (stmt->param_count)
{
- NET *net = &stmt->mysql->net;
- MYSQL_BIND *param;
- ulong param_count;
+ NET *net= &stmt->mysql->net;
+ MYSQL_BIND *param, *param_end;
char *param_data;
+ my_bool result;
if (!stmt->params)
{
/* Parameters exists, but no bound buffers */
set_stmt_error(stmt, CR_NOT_ALL_PARAMS_BOUND);
- DBUG_RETURN(-1);
+ DBUG_RETURN(1);
}
- net_clear(net);
- net->buf_length = 0; /* clear net */
-
- /* In case if buffers (type) alterned, indicate to server */
- net->buff[net->buf_length++] = (char)stmt->types_supplied;
-
- for (param=stmt->params, param_count = 0;
- param_count < stmt->param_count; param_count++, param++)
+ net_clear(net); /* Sets net->write_pos */
+ /* Reserve place for null-marker bytes */
+ null_count= (stmt->param_count+7) /8;
+ bzero((char*) net->write_pos, null_count);
+ net->write_pos+= null_count;
+ param_end= stmt->params + stmt->param_count;
+
+ /* In case if buffers (type) altered, indicate to server */
+ *(net->write_pos)++= (uchar) stmt->types_supplied;
+ if (!stmt->types_supplied)
{
- /* Check if any long data, run-time supply exists */
- if (param->is_long_data && !param->long_ended)
- DBUG_RETURN(MYSQL_NEED_DATA);
-
- if (my_store_param(stmt, param))
- DBUG_RETURN(-1);
- }
- if (!(param_data = my_memdup((byte *) net->buff,
- net->buf_length, MYF(MY_WME))))
+ stmt->types_supplied=1;
+ /*
+ Store types of parameters in first in first package
+ that is sent to the server.
+ */
+ for (param= stmt->params; param < param_end ; param++)
+ store_param_type(net, (uint) param->buffer_type);
+ }
+
+ for (param= stmt->params; param < param_end; param++)
{
- set_stmt_error(stmt, CR_MEMORY_ERROR);
- DBUG_RETURN(-1);
+ /* Check for long data which has not been propery given/terminated */
+ if (param->is_long_data)
+ {
+ if (!param->long_ended)
+ DBUG_RETURN(MYSQL_NEED_DATA);
+ }
+ else if (store_param(stmt, param))
+ DBUG_RETURN(1);
}
- if (my_execute(stmt,param_data,net->buf_length))
- {
- my_free(param_data, MYF(MY_WME));
- DBUG_RETURN(-1);
+ length= (ulong) (net->write_pos - net->buff);
+ /* TODO: Look into avoding the following memdup */
+ if (!(param_data= my_memdup((byte *) net->buff, length, MYF(0))))
+ {
+ set_stmt_error(stmt, CR_OUT_OF_MEMORY);
+ DBUG_RETURN(1);
}
+ net->write_pos= net->buff; /* Reset for net_write() */
+ result= execute(stmt, param_data, length);
my_free(param_data, MYF(MY_WME));
- stmt->types_supplied = 1;
- DBUG_RETURN(0);
- }
- DBUG_RETURN(my_execute(stmt,0,0));
+ DBUG_RETURN(result);
+ }
+ DBUG_RETURN((int) execute(stmt,0,0));
}
+
/*
Return total parameters count in the statement
*/
@@ -3808,452 +3736,308 @@ int STDCALL mysql_execute(MYSQL_STMT * stmt)
ulong STDCALL mysql_param_count(MYSQL_STMT * stmt)
{
DBUG_ENTER("mysql_param_count");
- DBUG_ASSERT(stmt != 0);
-
DBUG_RETURN(stmt->param_count);
}
/*
- Setup the parameter data buffers from application
+ Setup the parameter data buffers from application
*/
-int STDCALL mysql_bind_param(MYSQL_STMT * stmt, MYSQL_BIND * bind)
+my_bool STDCALL mysql_bind_param(MYSQL_STMT *stmt, MYSQL_BIND * bind)
{
- MYSQL_BIND *param;
- ulong count;
-
+ uint count=0;
+ MYSQL_BIND *param, *end;
DBUG_ENTER("mysql_bind_param");
- DBUG_ASSERT(stmt != 0);
#ifdef CHECK_EXTRA_ARGUMENTS
- if (!bind)
- {
- set_stmt_error(stmt, CR_NULL_POINTER);
- DBUG_RETURN(-1);
- }
if (stmt->state == MY_ST_UNKNOWN)
{
set_stmt_error(stmt, CR_NO_PREPARE_STMT);
- DBUG_RETURN(-1);
+ DBUG_RETURN(1);
}
if (!stmt->param_count)
{
set_stmt_error(stmt, CR_NO_PARAMETERS_EXISTS);
- DBUG_RETURN(-1);
+ DBUG_RETURN(1);
}
#endif
-
- /* In case if buffers bounded previously, free it */
- my_free((gptr) stmt->params, MY_ALLOW_ZERO_PTR);
- if (!(stmt->params=(MYSQL_BIND *)my_memdup((byte *) bind,
- sizeof(MYSQL_BIND) * stmt->param_count, MYF(MY_WME))))
- {
- set_stmt_error(stmt, CR_MEMORY_ERROR);
- DBUG_RETURN(0);
- }
- for (param=stmt->params, count=0;
- count < stmt->param_count; count++, param++)
+ /* Allocated on prepare */
+ memcpy((char*) stmt->params, (char*) bind,
+ sizeof(MYSQL_BIND) * stmt->param_count);
+
+ for (param= stmt->params, end= param+stmt->param_count;
+ param < end ;
+ param++)
{
- if (!param)
+ param->param_number= count++;
+ if (param->is_long_data &&
+ (param->buffer_type < MYSQL_TYPE_TINY_BLOB ||
+ param->buffer_type > MYSQL_TYPE_STRING))
{
- /* Not all parameters bound by the application */
- my_free((gptr) stmt->params, MY_ALLOW_ZERO_PTR);
- set_stmt_error(stmt, CR_NOT_ALL_PARAMS_BOUND);
- DBUG_RETURN(-1);
- }
- if (param->is_long_data &&
- (param->buffer_type < MYSQL_TYPE_TINY_BLOB ||
- param->buffer_type > MYSQL_TYPE_STRING))
- {
- /*
- Long data handling should be used only for string/binary
- types only
+ /*
+ Long data handling should be used only for string/binary
+ types only
*/
- my_free((gptr) stmt->params, MY_ALLOW_ZERO_PTR);
- set_stmt_error(stmt, CR_INVALID_BUFFER_USE);
- DBUG_RETURN(-1);
+ sprintf(stmt->last_error, ER(stmt->last_errno= CR_INVALID_BUFFER_USE),
+ param->param_number);
+ DBUG_RETURN(1);
+ }
+ /*
+ If param->length is not given, change it to point to bind_length.
+ This way we can always use *param->length to get the length of data
+ */
+ if (!param->length)
+ param->length= &param->bind_length;
+
+ /* Setup data copy functions for the different supported types */
+ switch (param->buffer_type) {
+ case MYSQL_TYPE_TINY:
+ param->bind_length= 1;
+ param->store_param_func= store_param_tinyint;
+ break;
+ case MYSQL_TYPE_SHORT:
+ param->bind_length= 2;
+ param->store_param_func= store_param_short;
+ break;
+ case MYSQL_TYPE_LONG:
+ param->bind_length= 4;
+ param->store_param_func= store_param_int32;
+ break;
+ case MYSQL_TYPE_LONGLONG:
+ param->bind_length= 8;
+ param->store_param_func= store_param_int64;
+ break;
+ case MYSQL_TYPE_FLOAT:
+ param->bind_length= 4;
+ param->store_param_func= store_param_float;
+ break;
+ case MYSQL_TYPE_DOUBLE:
+ param->bind_length= 4;
+ param->store_param_func= store_param_double;
+ break;
+ case MYSQL_TYPE_TINY_BLOB:
+ case MYSQL_TYPE_MEDIUM_BLOB:
+ case MYSQL_TYPE_LONG_BLOB:
+ case MYSQL_TYPE_VAR_STRING:
+ case MYSQL_TYPE_STRING:
+ param->bind_length= param->buffer_length;
+ param->store_param_func= store_param_str;
+ break;
+ default:
+ sprintf(stmt->last_error, ER(stmt->last_errno= CR_UNSUPPORTED_PARAM_TYPE),
+ param->buffer_type, param->param_number);
+ DBUG_RETURN(1);
}
- /* setup default buffer_length for int and double types */
- param->bind_length = return_result_length(param->buffer_type,
- param->buffer_length);
}
- stmt->types_supplied = 0;
+ /* We have to send/resendtype information to MySQL */
+ stmt->types_supplied= 0;
DBUG_RETURN(0);
}
+
/********************************************************************
Long data implementation
*********************************************************************/
/*
- Store long data buffer type, to distinguish string and binary
+ Send long data in pieces to the server
+
+ SYNOPSIS
+ mysql_send_long_data()
+ stmt Statement handler
+ param_number Parameter number (0 - N-1)
+ data Data to send to server
+ length Length of data to send (may be 0)
+ last_data If != 0 then this is the last data to the
+ server.
+ RETURN VALUES
+ 0 ok
+ 1 error
*/
-static char* my_store_long_type(MYSQL_STMT *stmt, char *packet, uint type)
-{
- *packet++ = (char)stmt->types_supplied;
- if (!stmt->types_supplied)
- {
- int2store(packet, type);
- packet += 2;
- }
- return(packet);
-}
-
-/*
- Long data in pieces, if buffured successfully send '0' as
- status else send '1'
-
- if length == MYSQL_END_OF_DATA, then thats the last data
- piece for the parameter
-*/
-my_bool STDCALL
-mysql_send_long_data(MYSQL_STMT *stmt, uint param_number,
- gptr data, ulong length)
+my_bool STDCALL
+mysql_send_long_data(MYSQL_STMT *stmt, uint param_number,
+ const char *data, ulong length,
+ my_bool last_data)
{
MYSQL_BIND *param;
- MYSQL *mysql;
- char *packet;
- ulong packet_length, long_length;
-
DBUG_ENTER("mysql_send_long_data");
- DBUG_ASSERT( stmt != 0 );
-
+ DBUG_ASSERT(stmt != 0);
DBUG_PRINT("enter",("param no : %d, data : %lx, length : %ld",
- param_number, data, length));
+ param_number, data, length));
- if (!(param = (stmt->params+param_number)))
+ if (param_number >= stmt->param_count)
{
set_stmt_error(stmt, CR_INVALID_PARAMETER_NO);
DBUG_RETURN(1);
}
-
- mysql = stmt->mysql;
- if (length == MYSQL_LONG_DATA_END || param->long_ended)
- {
- if (!stmt->long_alloced)
- {
- stmt->long_length = MAX_LONG_DATA_LENGTH;
- my_free(stmt->long_data, MY_ALLOW_ZERO_PTR);
-
- if (!(stmt->long_data = (char*) my_malloc(stmt->long_length,MYF(0))))
- {
- set_stmt_error(stmt, CR_MEMORY_ERROR);
- DBUG_RETURN(1);
- }
- stmt->long_alloced = 1;
- }
- packet = stmt->long_data;
- packet = my_store_param_length(packet, param_number);/* number */
- packet = my_store_long_type(stmt, packet, param->buffer_type);/* type */
- packet_length = (ulong) ((char *)packet - (char *)(stmt->long_data));
- *packet = (char )MYSQL_LONG_DATA_END; /* data end indicator */
- packet_length++;
-
- if (simple_command(mysql,COM_LONG_DATA,stmt->long_data,packet_length,0))
- goto err;
-
- stmt->types_supplied = 1;
- param->long_ended = 1;
- DBUG_RETURN(0);
- }
- if (!stmt->long_alloced || stmt->long_length < length+7)
+ param= stmt->params+param_number;
+ if (length)
{
- stmt->long_length = ( MAX_LONG_DATA_LENGTH > (length + 7)) ?
- MAX_LONG_DATA_LENGTH : length + 7;
+ MYSQL *mysql= stmt->mysql;
+ char *packet, extra_data[MYSQL_LONG_DATA_HEADER];
+
+ packet= extra_data;
+ int4store(packet, stmt->stmt_id); packet+=4;
+ int2store(packet, param_number); packet+=2;
+ int2store(packet, param->buffer_type); packet+=2;
- my_free(stmt->long_data, MY_ALLOW_ZERO_PTR);
- if (!(stmt->long_data = (char*) my_malloc(stmt->long_length ,MYF(0))))
+ /*
+ Note that we don't get any ok packet from the server in this case
+ This is intentional to save bandwidth.
+ */
+ if (advanced_command(mysql, COM_LONG_DATA, extra_data,
+ MYSQL_LONG_DATA_HEADER, data, length, 1))
{
- set_stmt_error(stmt, CR_MEMORY_ERROR);
+ set_stmt_errmsg(stmt,(char *) mysql->net.last_error,
+ mysql->net.last_errno);
DBUG_RETURN(1);
}
- stmt->long_alloced = 1;
- }
- packet = stmt->long_data;
- long_length = stmt->long_length;
- packet = my_store_param_length(packet, param_number);/* number */
- packet = my_store_long_type(stmt, packet, param->buffer_type);/* type */
- {
- char *to = my_store_param_length(packet, length); /* data length */
- memcpy(to, data, length); /* data */
- packet_length = (ulong)((char *)(to + length) - (char *)(stmt->long_data));
}
- /*
- Send the data to server directly for buffering ..
-
- TO_BE_DELETED : cross check this with Monty, becuase over the phone
- Monty said not to have check for max_packet_length for long data to
- have a local storage, instead send it to server directlty, but in
- one of his e-mail says to store upto max_packet_size locally..
- */
- if (simple_command(mysql, COM_LONG_DATA, stmt->long_data, packet_length, 0))
- goto err;
-
- stmt->types_supplied = 1;
+ param->long_ended= last_data;
DBUG_RETURN(0);
-
-err:
- set_stmt_errmsg(stmt,(char *)mysql->net.last_error, mysql->net.last_errno);
- DBUG_RETURN(-1);
}
+
/********************************************************************
- Fetch-bind related implementations
+ Fetch-bind related implementations
*********************************************************************/
/*
- Setup the bind buffers for resultset processing
+ Setup the bind buffers for resultset processing
*/
-int STDCALL mysql_bind_result(MYSQL_STMT * stmt, MYSQL_BIND * bind)
+my_bool STDCALL mysql_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind)
{
- MYSQL_BIND *param;
- ulong count,bind_count, *length;
-
+ MYSQL_BIND *param, *end;
+ ulong bind_count;
DBUG_ENTER("mysql_bind_result");
DBUG_ASSERT(stmt != 0);
+#ifdef EXTRA_CHECK_ARGUMENTS
if (!bind)
{
set_stmt_error(stmt, CR_NULL_POINTER);
- DBUG_RETURN(-1);
+ DBUG_RETURN(1);
}
- count = sizeof(*bind) / sizeof(MYSQL_BIND) + 1;
- bind_count = stmt->result ? stmt->result->field_count : count;
+#endif
+ bind_count= stmt->result->field_count;
+ memcpy((char*) stmt->bind, (char*) bind,
+ sizeof(MYSQL_BIND)*bind_count);
- /* bind_count now will have total fields, if no resultset
- exists, then this points to sizeof(bind)
- */
- if (bind_count < count)
+ for (param= stmt->bind, end= param+bind_count; param < end ; param++)
{
- set_stmt_error(stmt, CR_NOT_ALL_BUFFERS_BOUND);
- DBUG_RETURN(-1);
- }
- /* In case previously bound, free it */
- my_free((gptr)stmt->bind, MY_ALLOW_ZERO_PTR);
- if (!(stmt->bind=(MYSQL_BIND *)my_memdup((byte *) bind,
- sizeof(MYSQL_BIND) * bind_count, MYF(MY_WME))))
- {
- set_stmt_error(stmt, CR_MEMORY_ERROR);
- DBUG_RETURN(0);
- }
- /* set the lengths */
- for (param=stmt->bind,count=0; count<bind_count; count++,param++)
- {
- if((length=bind->length))
- *length = return_result_length(bind->buffer_type, bind->buffer_length);
+ /* TODO: Set up convert functions like in mysql_bind_param */
}
DBUG_RETURN(0);
}
+
/*
- Copy a row of data to bound buffers, used in myql_fetch
+ Fetch row data to bind buffers
*/
-static int
-my_fetch_record(MYSQL_BIND *bind, MYSQL_FIELD *field,
- char *value)
+static my_bool
+my_fetch_row(MYSQL_STMT *stmt, MYSQL_RES *result, const byte *row)
{
- gptr buff = bind->buffer;
- ulong buff_length = bind->buffer_length;
- long *length = bind->length , tmp_length;
- enum enum_field_types buff_type = bind->buffer_type;
-
- DBUG_ENTER("my_fetch_record");
-
- if (!value)
- {
- buff = NullS;
- DBUG_RETURN(0);
- }
- if (!length)
- length= &tmp_length;
-
- /* Copy the data which is in string format to application buffers
- based on its type .. no cross conversion needed as everything
- is in string buffers in result->row.
+ MYSQL_BIND *bind, *end;
+ uchar *null_ptr= (uchar*) row, bit;
- When the server supports the sending of data in its own format,
- then this needs to be cleaned to have all cross combinations
- */
- switch (buff_type)
+ result->row_count++;
+ row+= (result->field_count+7)/8;
+ /* Copy complete row to application buffers */
+ bit=1;
+ for (bind= stmt->bind, end= (MYSQL_BIND *) bind + result->field_count;
+ bind < end;
+ bind++)
{
- case MYSQL_TYPE_TINY:
- if (unsigned_field(field))
- *((uchar *) buff) = ((uchar) (uint) atoi(value));
+ if (*null_ptr & bit)
+ bind->is_null= 1;
else
- *((char *) buff) = ((char)atoi(value));
- break;
-
- case MYSQL_TYPE_SHORT:
- if (unsigned_field(field))
- *((ushort *) buff) = (ushort) (uint) atol(value);
- else
- *((short *) buff) = (short)atoi(value);
- break;
-
- case MYSQL_TYPE_LONG:
- if (unsigned_field(field))
{
- char *end_ptr;
- *((ulong *) buff) = strtoul(value, &end_ptr, 10);
+ bind->is_null= 0;
+ row= (byte*) (*bind->fetch_result)(bind, (char*) row);
}
- else
+ if (! (bit<<=1) & 255)
{
- uint actual_length = strlen(value);
- if (actual_length >= 10 && value[4] == '-' && value[7] == '-' &&
- (!value[10] || value[10] == ' '))
- {
- *((long *) buff) = ((long)atol(value) * 10000L +
- (long)atol(value + 5) * 100L +
- (long)atol(value + 8));
- }
- else
- *((long *) buff) = (long)atol(value);
+ bit=1; /* To next byte */
+ null_ptr++;
}
- break;
-
- case MYSQL_TYPE_LONGLONG:
- if (unsigned_field(field))
- *((ulonglong *) buff) = (ulonglong) strtoull(value, NULL, 10);
- else
- *((longlong *) buff) = (longlong) strtoll(value, NULL, 10);
- break;
-
- case MYSQL_TYPE_FLOAT:
- *((float *) buff) = (float)atof(value);
- break;
-
- case MYSQL_TYPE_DOUBLE:
- *((double *) buff) = (double)atof(value);
- break;
-
- /* TODO : for strings and blobs, Monty comments
-
- For strings: We should also support letting the user specify
- a pointer to a char * which we would update to where the
- date is in the memory. In this case we would only update the
- pointer to where we have the string in memory. This would make
- things twice as fast for us as we would not have to move things
- around and would also require much less memoryfrom the application.
-
- so, just return the address with the length pointer updated ?
-
- confirm with Monty and enble the following lines of code by
- disbling the existing code which follows next to this.
-
- If this is enabled, then there is no need of buffer_length in
- MYSQL_BIND structure, and clean the code related to that
- */
-#if TO_BE_IMPLEMENTED
- case MYSQL_TYPE_BLOB:
- case MYSQL_TYPE_TINY_BLOB:
- case MYSQL_TYPE_MEDIUM_BLOB:
- case MYSQL_TYPE_LONG_BLOB:
- *length = sizeof(value);/* will contain size */
- (char *)bind->buffer = value; /* send the data address to application */
- break;
-
- default:
- *length = strlen(value);/* will contain string length */
- (char *)bind->buffer = value; /* send the data address to application */
- break;
-#endif
- case MYSQL_TYPE_BLOB:
- case MYSQL_TYPE_TINY_BLOB:
- case MYSQL_TYPE_MEDIUM_BLOB:
- case MYSQL_TYPE_LONG_BLOB:
- *length = sizeof(value);
- memcpy((char *)buff, value, buff_length);
- break;
-
- default:
- buff_length--;
- *length = strlen(value);
- strmake((char *)buff, value, buff_length);
}
- DBUG_RETURN(0);
+ return 0;
}
-/*
- Fetch row data to bind buffers
-*/
-static int my_fetch_row(MYSQL_STMT *stmt, MYSQL_RES *result, MYSQL_ROW values)
+static int
+read_binary_data(MYSQL *mysql)
{
- MYSQL_BIND *bind, *end;
- MYSQL_FIELD *field;
- ulong record=0;
-
- result->current_row = values;
- result->row_count++;
-
- /* Copy complete row to application buffers */
- for (bind = stmt->bind, end = (MYSQL_BIND *) bind + result->field_count;
- bind < end;
- bind++, values++)
- {
- field = &result->fields[record++];
-
- if (my_fetch_record(bind, field, *values))
- return -1;
- }
+ ulong pkt_len;
+ if ((pkt_len= net_safe_read(mysql)) == packet_error)
+ return -1;
+ if (mysql->net.read_pos[0])
+ return 1; /* End of data */
return 0;
}
+
/*
- Fetch and return row data to bound buffers, if any
+ Fetch and return row data to bound buffers, if any
*/
-int STDCALL mysql_fetch(MYSQL_STMT * stmt)
+int STDCALL mysql_fetch(MYSQL_STMT *stmt)
{
MYSQL_RES *result;
-
DBUG_ENTER("mysql_fetch");
- DBUG_ASSERT(stmt != 0);
-
- result = stmt->result;
+ result= stmt->result;
if (!result)
DBUG_RETURN(MYSQL_NO_DATA);
if (!result->data)
{
+ MYSQL *mysql= stmt->mysql;
if (!result->eof)
{
- if (!(read_one_row(result->handle, result->field_count,
- result->row, result->lengths)))
- {
- DBUG_RETURN(my_fetch_row(stmt, result, result->row));
- }
- else
+ int res;
+ if (!(res= read_binary_data(result->handle)))
+ DBUG_RETURN((int) my_fetch_row(stmt, result,
+ (byte*) mysql->net.read_pos+1));
+ DBUG_PRINT("info", ("end of data"));
+ result->eof= 1;
+ result->handle->status= MYSQL_STATUS_READY;
+
+ /* Don't clear handle in mysql_free_results */
+ result->handle= 0;
+ if (res < 0) /* Network error */
{
- DBUG_PRINT("info", ("end of data"));
- result->eof = 1;
- result->handle->status = MYSQL_STATUS_READY;
- /* Don't clear handle in mysql_free_results */
- result->handle = 0;
+ set_stmt_errmsg(stmt,(char *)mysql->net.last_error,
+ mysql->net.last_errno);
+ DBUG_RETURN(MYSQL_STATUS_ERROR);
}
}
DBUG_RETURN(MYSQL_NO_DATA); /* no more data */
}
{
+ /*
+ For prepared statements, the row data is a string of binary bytes,
+ not a set of string pointers as for normal statements
+ It's however convenient to use the data pointer also for prepared
+ statements.
+ */
MYSQL_ROW values;
-
if (!result->data_cursor)
{
DBUG_PRINT("info", ("end of data"));
- result->current_row = (MYSQL_ROW) NULL;
+ result->current_row= (MYSQL_ROW) NULL;
DBUG_RETURN(MYSQL_NO_DATA);
}
- values = result->data_cursor->data;
- result->data_cursor = result->data_cursor->next;
+ values= result->data_cursor->data;
+ result->data_cursor= result->data_cursor->next;
- DBUG_RETURN(my_fetch_row(stmt,result,values));
+ DBUG_RETURN((int) my_fetch_row(stmt,result, (byte*) values));
}
DBUG_RETURN(0);
}
@@ -4262,22 +4046,29 @@ int STDCALL mysql_fetch(MYSQL_STMT * stmt)
/********************************************************************
Misc function implementations
*********************************************************************/
+
/*
- Close the statement handle by freeing all resources
+ Close the statement handle by freeing all resources
*/
-int STDCALL mysql_stmt_close(MYSQL_STMT * stmt)
+my_bool STDCALL mysql_stmt_close(MYSQL_STMT *stmt)
{
+ my_bool error=0;
DBUG_ENTER("mysql_stmt_close");
- DBUG_ASSERT(stmt != 0);
- free_root(&stmt->mem_root,MY_ALLOW_ZERO_PTR);
- my_free((gptr) stmt->query, MYF(MY_WME));
+ if (stmt->state)
+ {
+ char buff[4];
+ int4store(buff, stmt->stmt_id);
+ error= simple_command(stmt->mysql, COM_CLOSE_STMT, buff, 4, 0);
+ }
+
+ free_root(&stmt->mem_root, MYF(0));
+ my_free((gptr) stmt->query, MYF(MY_WME | MY_ALLOW_ZERO_PTR));
my_free((gptr) stmt->bind, MY_ALLOW_ZERO_PTR);
- my_free((gptr) stmt->params, MY_ALLOW_ZERO_PTR);
- my_free((gptr) stmt->long_data, MY_ALLOW_ZERO_PTR);
+ my_free((gptr) stmt->params, MY_ALLOW_ZERO_PTR);
my_free((gptr) stmt, MYF(MY_WME));
- DBUG_RETURN(0);
+ DBUG_RETURN(error);
}
/*
@@ -4287,9 +4078,7 @@ int STDCALL mysql_stmt_close(MYSQL_STMT * stmt)
uint STDCALL mysql_stmt_errno(MYSQL_STMT * stmt)
{
DBUG_ENTER("mysql_stmt_errno");
- DBUG_ASSERT(stmt != 0);
-
- DBUG_RETURN(stmt->err_no);
+ DBUG_RETURN(stmt->last_errno);
}
/*
@@ -4299,33 +4088,27 @@ uint STDCALL mysql_stmt_errno(MYSQL_STMT * stmt)
const char *STDCALL mysql_stmt_error(MYSQL_STMT * stmt)
{
DBUG_ENTER("mysql_stmt_error");
- DBUG_ASSERT(stmt != 0);
-
- DBUG_RETURN(stmt->error);
+ DBUG_RETURN(stmt->last_error);
}
/*
Commit the current transaction
*/
-int STDCALL mysql_commit(MYSQL * mysql)
+my_bool STDCALL mysql_commit(MYSQL * mysql)
{
DBUG_ENTER("mysql_commit");
- DBUG_ASSERT(mysql != 0);
-
- DBUG_RETURN(mysql_real_query(mysql, "commit", 6));
+ DBUG_RETURN((my_bool) mysql_real_query(mysql, "commit", 6));
}
/*
- Rollback the current transaction
+ Rollback the current transaction
*/
-int STDCALL mysql_rollback(MYSQL * mysql)
+my_bool STDCALL mysql_rollback(MYSQL * mysql)
{
DBUG_ENTER("mysql_rollback");
- DBUG_ASSERT(mysql != 0);
-
- DBUG_RETURN(mysql_real_query(mysql, "rollback", 8));
+ DBUG_RETURN((my_bool) mysql_real_query(mysql, "rollback", 8));
}
@@ -4333,14 +4116,12 @@ int STDCALL mysql_rollback(MYSQL * mysql)
Set autocommit to either true or false
*/
-int STDCALL mysql_autocommit(MYSQL * mysql, my_bool auto_mode)
+my_bool STDCALL mysql_autocommit(MYSQL * mysql, my_bool auto_mode)
{
DBUG_ENTER("mysql_autocommit");
- DBUG_ASSERT(mysql != 0);
-
DBUG_PRINT("enter", ("mode : %d", auto_mode));
if (auto_mode) /* set to true */
- DBUG_RETURN(mysql_real_query(mysql, "set autocommit=1", 16));
- DBUG_RETURN(mysql_real_query(mysql, "set autocommit=0", 16));
+ DBUG_RETURN((my_bool) mysql_real_query(mysql, "set autocommit=1", 16));
+ DBUG_RETURN((my_bool) mysql_real_query(mysql, "set autocommit=0", 16));
}
diff --git a/libmysql/libmysql.def b/libmysql/libmysql.def
index 46ca5acafcc..f72f045c96c 100644
--- a/libmysql/libmysql.def
+++ b/libmysql/libmysql.def
@@ -104,8 +104,8 @@ EXPORTS
mysql_rpl_probe
mysql_set_master
mysql_add_slave
-
-
+ mysql_warning_count
+ mysql_warnings
diff --git a/libmysql/manager.c b/libmysql/manager.c
index 22b109caea8..6d977e7eef2 100644
--- a/libmysql/manager.c
+++ b/libmysql/manager.c
@@ -138,7 +138,7 @@ MYSQL_MANAGER* STDCALL mysql_manager_connect(MYSQL_MANAGER* con,
}
sock_addr.sin_port = (ushort) htons((ushort) port);
if (my_connect(sock,(struct sockaddr *) &sock_addr, sizeof(sock_addr),
- 0) <0)
+ 0))
{
con->last_errno=errno;
sprintf(con->last_error ,"Could not connect to %-.64s", host);
diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc
index f5934fc93fa..a3e5bfb4fff 100644
--- a/libmysqld/lib_sql.cc
+++ b/libmysqld/lib_sql.cc
@@ -154,14 +154,12 @@ check_connections1(THD *thd)
end+=SCRAMBLE_LENGTH +1;
int2store(end,client_flags);
end[2]=MY_CHARSET_CURRENT;
-
-#define MIN_HANDSHAKE_SIZE 6
-
int2store(end+3,thd->server_status);
bzero(end+5,13);
end+=18;
- if (net_write_command(net,protocol_version, buff,
- (uint) (end-buff)))
+ if (net_write_command(net,protocol_version,
+ NullS, 0,
+ buff, (uint) (end-buff)))
{
inc_host_errors(&thd->remote.sin_addr);
return(ER_HANDSHAKE_ERROR);
@@ -169,6 +167,8 @@ check_connections1(THD *thd)
return 0;
}
+#define MIN_HANDSHAKE_SIZE 6
+
static int
check_connections2(THD * thd)
{
@@ -214,13 +214,12 @@ check_connections2(THD * thd)
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;
USER_RESOURCES ur;
thd->db=0;
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,
@@ -236,7 +235,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));
@@ -254,7 +253,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);
}
}
@@ -269,7 +268,7 @@ static bool check_user(THD *thd,enum_server_command command, const char *user,
if (db && db[0])
return test(mysql_change_db(thd,db));
else
- send_ok(net); // Ready to handle questions
+ send_ok(thd); // Ready to handle questions
return 0; // ok
}
@@ -370,7 +369,6 @@ int STDCALL mysql_server_init(int argc, char **argv, char **groups)
(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);
@@ -388,6 +386,7 @@ int STDCALL mysql_server_init(int argc, char **argv, char **groups)
(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);
@@ -499,7 +498,7 @@ int STDCALL mysql_server_init(int argc, char **argv, char **groups)
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");
diff --git a/libmysqld/libmysqld.c b/libmysqld/libmysqld.c
index 3fba238a8bf..453376092d7 100644
--- a/libmysqld/libmysqld.c
+++ b/libmysqld/libmysqld.c
@@ -212,12 +212,12 @@ static void free_rows(MYSQL_DATA *cur)
}
-int
+my_bool
simple_command(MYSQL *mysql,enum enum_server_command command, const char *arg,
ulong length, my_bool skipp_check)
{
NET *net= &mysql->net;
- int result= -1;
+ my_bool result= 1;
/* Check that we are calling the client functions in right order */
if (mysql->status != MYSQL_STATUS_READY)
@@ -239,7 +239,7 @@ simple_command(MYSQL *mysql,enum enum_server_command command, const char *arg,
result = lib_dispatch_command(command, net, arg,length);
if (!skipp_check)
result= ((mysql->packet_length=net_safe_read(mysql)) == packet_error ?
- -1 : 0);
+ 1 : 0);
end:
return result;
}
@@ -1124,7 +1124,7 @@ mysql_send_query(MYSQL* mysql, const char* query, ulong length)
}
-int STDCALL
+my_bool STDCALL
mysql_read_query_result(MYSQL *mysql)
{
uchar *pos;
@@ -1134,7 +1134,7 @@ mysql_read_query_result(MYSQL *mysql)
DBUG_ENTER("mysql_read_query_result");
if ((length=net_safe_read(mysql)) == packet_error)
- DBUG_RETURN(-1);
+ DBUG_RETURN(1);
free_old_query(mysql); /* Free old result */
get_info:
pos=(uchar*) mysql->net.read_pos;
@@ -1154,7 +1154,7 @@ get_info:
{
int error=send_file_to_server(mysql,(char*) pos);
if ((length=net_safe_read(mysql)) == packet_error || error)
- DBUG_RETURN(-1);
+ DBUG_RETURN(1);
goto get_info; /* Get info packet */
}
if (!(mysql->server_status & SERVER_STATUS_AUTOCOMMIT))
@@ -1162,19 +1162,19 @@ get_info:
mysql->extra_info= net_field_length_ll(&pos); /* Maybe number of rec */
if (!(fields=read_rows(mysql,(MYSQL_FIELD*) 0,5)))
- DBUG_RETURN(-1);
+ DBUG_RETURN(1);
if (!(mysql->fields=unpack_fields(fields,&mysql->field_alloc,
(uint) field_count,0,
(my_bool) test(mysql->server_capabilities &
CLIENT_LONG_FLAG))))
- DBUG_RETURN(-1);
+ DBUG_RETURN(1);
mysql->status=MYSQL_STATUS_GET_RESULT;
mysql->field_count=field_count;
DBUG_RETURN(0);
}
/****************************************************************************
-* A modified version of connect(). connect2() allows you to specify
+* A modified version of connect(). my_connect() allows you to specify
* a timeout value, in seconds, that we should wait until we
* derermine we can't connect to a particular host. If timeout is 0,
* my_connect() will behave exactly like connect().
@@ -1182,11 +1182,11 @@ get_info:
* Base version coded by Steve Bernacki, Jr. <steve@navinet.net>
*****************************************************************************/
-int my_connect(my_socket s, const struct sockaddr *name, uint namelen,
- uint timeout)
+my_bool my_connect(my_socket s, const struct sockaddr *name, uint namelen,
+ uint timeout)
{
#if defined(__WIN__) || defined(OS2)
- return connect(s, (struct sockaddr*) name, namelen);
+ return connect(s, (struct sockaddr*) name, namelen) != 0;
#else
int flags, res, s_err;
SOCKOPT_OPTLEN_TYPE s_err_size = sizeof(uint);
@@ -1199,7 +1199,7 @@ int my_connect(my_socket s, const struct sockaddr *name, uint namelen,
*/
if (timeout == 0)
- return connect(s, (struct sockaddr*) name, namelen);
+ return connect(s, (struct sockaddr*) name, namelen) != 0;
flags = fcntl(s, F_GETFL, 0); /* Set socket to not block */
#ifdef O_NONBLOCK
@@ -1212,7 +1212,7 @@ int my_connect(my_socket s, const struct sockaddr *name, uint namelen,
if ((res != 0) && (s_err != EINPROGRESS))
{
errno = s_err; /* Restore it */
- return(-1);
+ return(1);
}
if (res == 0) /* Connected quickly! */
return(0);
@@ -1252,7 +1252,7 @@ int my_connect(my_socket s, const struct sockaddr *name, uint namelen,
now_time=time(NULL);
timeout-= (uint) (now_time - start_time);
if (errno != EINTR || (int) timeout <= 0)
- return -1;
+ return 1;
}
/* select() returned something more interesting than zero, let's
@@ -1262,12 +1262,12 @@ int my_connect(my_socket s, const struct sockaddr *name, uint namelen,
s_err=0;
if (getsockopt(s, SOL_SOCKET, SO_ERROR, (char*) &s_err, &s_err_size) != 0)
- return(-1);
+ return(1);
if (s_err)
{ /* getsockopt could succeed */
errno = s_err;
- return(-1); /* but return an error... */
+ return(1); /* but return an error... */
}
return(0); /* It's all good! */
#endif
diff --git a/myisam/ft_boolean_search.c b/myisam/ft_boolean_search.c
index 1a70113f0ad..9a2a29f9a08 100644
--- a/myisam/ft_boolean_search.c
+++ b/myisam/ft_boolean_search.c
@@ -241,8 +241,8 @@ static void _ftb_init_index_search(FT_INFO *ftb)
{
if (!is_tree_inited(& ftb->no_dupes))
{
- init_tree(& ftb->no_dupes,0,0,sizeof(my_off_t),
- _ftb_no_dupes_cmp,0,0,0);
+ init_tree(&ftb->no_dupes,0,0,sizeof(my_off_t),
+ _ftb_no_dupes_cmp, 0, NULL, NULL);
}
}
}
diff --git a/myisam/ft_stopwords.c b/myisam/ft_stopwords.c
index 170442c71de..5415a08e5e3 100644
--- a/myisam/ft_stopwords.c
+++ b/myisam/ft_stopwords.c
@@ -41,8 +41,8 @@ int ft_init_stopwords(const char **sws)
if(!stopwords3)
{
if(!(stopwords3=(TREE *)my_malloc(sizeof(TREE),MYF(0)))) return -1;
- init_tree(stopwords3,0,0,sizeof(FT_STOPWORD),(qsort_cmp2)&FT_STOPWORD_cmp,0,
- NULL, NULL);
+ init_tree(stopwords3,0,0,sizeof(FT_STOPWORD),(qsort_cmp2)&FT_STOPWORD_cmp,
+ 0, NULL, NULL);
}
if(!sws) return 0;
diff --git a/myisam/mi_check.c b/myisam/mi_check.c
index 49f6f31f96e..10d7052fb0f 100644
--- a/myisam/mi_check.c
+++ b/myisam/mi_check.c
@@ -1771,7 +1771,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
File new_file;
MI_SORT_PARAM sort_param;
MYISAM_SHARE *share=info->s;
- MI_KEYSEG *keyseg;
+ HA_KEYSEG *keyseg;
ulong *rec_per_key_part;
char llbuff[22];
SORT_INFO sort_info;
@@ -2136,7 +2136,7 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info,
MI_SORT_PARAM *sort_param=0;
MYISAM_SHARE *share=info->s;
ulong *rec_per_key_part;
- MI_KEYSEG *keyseg;
+ HA_KEYSEG *keyseg;
char llbuff[22];
IO_CACHE_SHARE io_share;
SORT_INFO sort_info;
@@ -3080,7 +3080,7 @@ static int sort_key_write(MI_SORT_PARAM *sort_param, const void *a)
{
sort_info->dupp++;
sort_info->info->lastpos=get_record_for_key(sort_info->info,
- sort_parm->keyinfo,
+ sort_param->keyinfo,
(uchar*) a);
mi_check_print_warning(param,
"Duplicate key for record at %10s against record at %10s",
diff --git a/myisam/myisampack.c b/myisam/myisampack.c
index a299e4eb00d..3fbc371be3f 100644
--- a/myisam/myisampack.c
+++ b/myisam/myisampack.c
@@ -665,7 +665,8 @@ static HUFF_COUNTS *init_huff_count(MI_INFO *info,my_off_t records)
(type == FIELD_NORMAL ||
type == FIELD_SKIP_ZERO))
count[i].max_zero_fill= count[i].field_length;
- init_tree(&count[i].int_tree,0,0,-1,(qsort_cmp2) compare_tree,0,NULL,NULL);
+ init_tree(&count[i].int_tree,0,0,-1,(qsort_cmp2) compare_tree,0, NULL,
+ NULL);
if (records && type != FIELD_BLOB && type != FIELD_VARCHAR)
count[i].tree_pos=count[i].tree_buff =
my_malloc(count[i].field_length > 1 ? tree_buff_length : 2,
diff --git a/myisam/rt_key.c b/myisam/rt_key.c
index c08e918c6db..a48aec53c97 100644
--- a/myisam/rt_key.c
+++ b/myisam/rt_key.c
@@ -1,5 +1,4 @@
-/* Copyright (C) 2000 MySQL AB & Ramil Kalimullin & MySQL Finland AB
- & TCX DataKonsult AB
+/* Copyright (C) 2000 MySQL AB & Ramil Kalimullin
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
@@ -22,14 +21,16 @@
#include "rt_mbr.h"
/*
-Add key to the page
-Result values:
--1 - error
- 0 - not split
- 1 - split
+ Add key to the page
+
+ RESULT VALUES
+ -1 Error
+ 0 Not split
+ 1 Split
*/
+
int rtree_add_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key,
- uint key_length, uchar *page_buf, my_off_t *new_page)
+ uint key_length, uchar *page_buf, my_off_t *new_page)
{
uint page_size = mi_getint(page_buf);
uint nod_flag = mi_test_if_nod(page_buf);
@@ -53,47 +54,39 @@ int rtree_add_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key,
mi_putint(page_buf, page_size, nod_flag);
return 0;
}
- else
- {
- if (rtree_split_page(info, keyinfo, page_buf, key, key_length, new_page))
- return -1;
- else
- return 1;
- }
+
+ return (rtree_split_page(info, keyinfo, page_buf, key, key_length,
+ new_page) ? -1 : 0);
}
/*
-Delete key from the page
+ Delete key from the page
*/
int rtree_delete_key(MI_INFO *info, uchar *page_buf, uchar *key,
- uint key_length, uint nod_flag)
+ uint key_length, uint nod_flag)
{
uint16 page_size = mi_getint(page_buf);
uchar *key_start;
+ key_start= key - nod_flag;
if (nod_flag)
- {
- key_start = key - nod_flag;
- }
- else
- {
- key_start = key;
key_length += info->s->base.rec_reflength;
- }
- memmove(key_start, key + key_length, page_size - key_length -
- (key - page_buf));
- page_size -= key_length + nod_flag;
- mi_putint(page_buf, page_size, nod_flag);
+ memmove(key_start, key + key_length, page_size - key_length -
+ (key - page_buf));
+ page_size-= key_length + nod_flag;
+ mi_putint(page_buf, page_size, nod_flag);
return 0;
}
+
/*
-Calculate and store key MBR
+ Calculate and store key MBR
*/
+
int rtree_set_key_mbr(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key,
- uint key_length, my_off_t child_page)
+ uint key_length, my_off_t child_page)
{
uchar *k;
uchar *last;
@@ -114,21 +107,25 @@ err1:
return -1;
}
+
/*
-Choose non-leaf better key for insertion
+ Choose non-leaf better key for insertion
*/
+
uchar *rtree_choose_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key,
- uint key_length, uchar *page_buf, uint nod_flag)
+ uint key_length, uchar *page_buf, uint nod_flag)
{
double increase;
double best_incr = DBL_MAX;
double area;
double best_area;
uchar *best_key;
-
uchar *k = rt_PAGE_FIRST_KEY(page_buf, nod_flag);
uchar *last = rt_PAGE_END(page_buf);
+ LINT_INIT(best_area);
+ LINT_INIT(best_key);
+
for (; k < last; k = rt_PAGE_NEXT_KEY(k, key_length, nod_flag))
{
if ((increase = rtree_area_increase(keyinfo->seg, key, k, key_length,
diff --git a/myisam/rt_test.c b/myisam/rt_test.c
index 4cc60d63031..5cf4262e804 100644
--- a/myisam/rt_test.c
+++ b/myisam/rt_test.c
@@ -32,7 +32,7 @@ static void print_record(char * record,my_off_t offs,const char * tail);
static int run_test(const char *filename);
-int main(int argc,char *argv[])
+int main(int argc __attribute__((unused)),char *argv[])
{
MY_INIT(argv[0]);
exit(run_test("rt_test"));
@@ -63,7 +63,6 @@ int run_test(const char *filename)
int row_count=0;
char record[MAX_REC_LENGTH];
char read_record[MAX_REC_LENGTH];
- int upd=10;
ha_rows hrows;
@@ -343,7 +342,10 @@ static int read_with_pos (MI_INFO * file,int silent)
}
-static void bprint_record(char * record, my_off_t offs,const char * tail)
+#ifdef NOT_USED
+static void bprint_record(char * record,
+ my_off_t offs __attribute__((unused)),
+ const char * tail)
{
int i;
char * pos;
@@ -356,8 +358,12 @@ static void bprint_record(char * record, my_off_t offs,const char * tail)
}
printf("%s",tail);
}
+#endif
-static void print_record(char * record, my_off_t offs,const char * tail)
+
+static void print_record(char * record,
+ my_off_t offs __attribute__((unused)),
+ const char * tail)
{
int i;
char * pos;
diff --git a/myisam/sp_key.c b/myisam/sp_key.c
index 2ab11f993c3..82c2b1f8510 100644
--- a/myisam/sp_key.c
+++ b/myisam/sp_key.c
@@ -1,5 +1,4 @@
-/* Copyright (C) 2000 MySQL AB & Ramil Kalimullin & MySQL Finland AB
- & TCX DataKonsult AB
+/* Copyright (C) 2000 MySQL AB & Ramil Kalimullin
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
@@ -30,8 +29,9 @@ static int sp_get_geometry_mbr(uchar *(*wkb), uchar *end, uint n_dims,
double *mbr, int top);
static int sp_mbr_from_wkb(uchar (*wkb), uint size, uint n_dims, double *mbr);
+
uint sp_make_key(register MI_INFO *info, uint keynr, uchar *key,
- const byte *record, my_off_t filepos)
+ const byte *record, my_off_t filepos)
{
HA_KEYSEG *keyseg;
MI_KEYDEF *keyinfo = &info->s->keyinfo[keynr];
@@ -91,10 +91,12 @@ static int sp_mbr_from_wkb(uchar *wkb, uint size, uint n_dims, double *mbr)
}
/*
-Add one point stored in wkb to mbr
+ Add one point stored in wkb to mbr
*/
+
static int sp_add_point_to_mbr(uchar *(*wkb), uchar *end, uint n_dims,
- uchar byte_order, double *mbr)
+ uchar byte_order __attribute__((unused)),
+ double *mbr)
{
double ord;
double *mbr_end = mbr + n_dims * 2;
@@ -115,12 +117,14 @@ static int sp_add_point_to_mbr(uchar *(*wkb), uchar *end, uint n_dims,
return 0;
}
+
static int sp_get_point_mbr(uchar *(*wkb), uchar *end, uint n_dims,
uchar byte_order, double *mbr)
{
return sp_add_point_to_mbr(wkb, end, n_dims, byte_order, mbr);
}
+
static int sp_get_linestring_mbr(uchar *(*wkb), uchar *end, uint n_dims,
uchar byte_order, double *mbr)
{
@@ -137,6 +141,7 @@ static int sp_get_linestring_mbr(uchar *(*wkb), uchar *end, uint n_dims,
return 0;
}
+
static int sp_get_polygon_mbr(uchar *(*wkb), uchar *end, uint n_dims,
uchar byte_order, double *mbr)
{
diff --git a/myisam/sp_test.c b/myisam/sp_test.c
index 9d32b3e623d..b8b5880cf67 100644
--- a/myisam/sp_test.c
+++ b/myisam/sp_test.c
@@ -41,7 +41,7 @@ static void rtree_PrintWKB(uchar *wkb, uint n_dims);
static char blob_key[MAX_REC_LENGTH];
-int main(int argc,char *argv[])
+int main(int argc __attribute__((unused)),char *argv[])
{
MY_INIT(argv[0]);
exit(run_test("sp_test"));
@@ -320,7 +320,10 @@ static int read_with_pos (MI_INFO * file,int silent)
}
-static void bprint_record(char * record, my_off_t offs,const char * tail)
+#ifdef NOT_USED
+static void bprint_record(char * record,
+ my_off_t offs __attribute__((unused)),
+ const char * tail)
{
int i;
char * pos;
@@ -333,6 +336,8 @@ static void bprint_record(char * record, my_off_t offs,const char * tail)
}
printf("%s",tail);
}
+#endif
+
static void print_record(char * record, my_off_t offs,const char * tail)
{
@@ -356,6 +361,7 @@ static void print_record(char * record, my_off_t offs,const char * tail)
+#ifndef NOT_USED
static void create_point(char *record,uint rownr)
{
uint tmp;
@@ -380,6 +386,7 @@ static void create_point(char *record,uint rownr)
ptr=blob_key;
memcpy_fixed(pos,&ptr,sizeof(char*));
}
+#endif
static void create_linestring(char *record,uint rownr)
diff --git a/mysql-test/README b/mysql-test/README
index c5dc3e219de..7c6efe7940e 100644
--- a/mysql-test/README
+++ b/mysql-test/README
@@ -1,6 +1,10 @@
This directory contains a test suite for mysql daemon. To run
the currently existing test cases, simply execute ./mysql-test-run in
this directory. It will fire up the newly built mysqld and test it.
+
+If you want to run the test with a running MySQL server use the --external
+option to mysql-test-run.
+
Note that you do not have to have to do make install, and you could
actually have a co-existing MySQL installation - the tests will not
conflict with it.
@@ -13,8 +17,7 @@ http://www.mysql.com/doc/M/y/MySQL_test_suite.html
You can create your own test cases. To create a test case:
- cd t
- vi test_case_name.test
+ xeamacs t/test_case_name.test
in the file, put a set of SQL commands that will create some tables,
load test data, run some queries to manipulate it.
diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh
index a26b597f8db..57b6ef056f2 100644
--- a/mysql-test/mysql-test-run.sh
+++ b/mysql-test/mysql-test-run.sh
@@ -171,7 +171,7 @@ USER_TEST=
EXTRA_MASTER_OPT=""
EXTRA_MYSQL_TEST_OPT=""
-USE_RUNNING_SERVER=1
+USE_RUNNING_SERVER=""
DO_GCOV=""
DO_GDB=""
MANUAL_GDB=""
@@ -199,6 +199,7 @@ while test $# -gt 0; do
--slave-binary=*)
SLAVE_MYSQLD=`$ECHO "$1" | $SED -e "s;--slave-binary=;;"` ;;
--local) USE_RUNNING_SERVER="" ;;
+ --extern) USE_RUNNING_SERVER="1" ;;
--tmpdir=*) MYSQL_TMP_DIR=`$ECHO "$1" | $SED -e "s;--tmpdir=;;"` ;;
--local-master)
MASTER_MYPORT=3306;
diff --git a/mysql-test/r/rollback.result b/mysql-test/r/rollback.result
index a5eb6f8729f..d87aa68dce4 100644
--- a/mysql-test/r/rollback.result
+++ b/mysql-test/r/rollback.result
@@ -4,9 +4,26 @@ begin work;
insert into t1 values (4);
insert into t1 values (5);
rollback;
-Warning: Some non-transactional changed tables couldn't be rolled back
+Warnings:
+Warning 1196 Some non-transactional changed tables couldn't be rolled back
+select @@warning_count;
+@@warning_count
+1
+select @@error_count;
+@@error_count
+0
+show warnings;
+Level Code Message
+Warning 1196 Some non-transactional changed tables couldn't be rolled back
+show errors;
+Level Code Message
select * from t1;
n
4
5
+select @@warning_count;
+@@warning_count
+0
+show warnings;
+Level Code Message
drop table t1;
diff --git a/mysql-test/r/rpl_log.result b/mysql-test/r/rpl_log.result
index 8948460e1bd..b5719c920e6 100644
--- a/mysql-test/r/rpl_log.result
+++ b/mysql-test/r/rpl_log.result
@@ -18,24 +18,24 @@ drop table t1;
show binlog events;
Log_name Pos Event_type Server_id Orig_log_pos Info
master-bin.001 4 Start 1 4 Server ver: VERSION, Binlog ver: 3
-master-bin.001 79 Query 1 79 use test; create table t1(n int not null auto_increment primary key)
+master-bin.001 79 Query 1 79 use `test`; create table t1(n int not null auto_increment primary key)
master-bin.001 172 Intvar 1 172 INSERT_ID=1
-master-bin.001 200 Query 1 200 use test; insert into t1 values (NULL)
-master-bin.001 263 Query 1 263 use test; drop table t1
-master-bin.001 311 Query 1 311 use test; create table t1 (word char(20) not null)
+master-bin.001 200 Query 1 200 use `test`; insert into t1 values (NULL)
+master-bin.001 263 Query 1 263 use `test`; drop table t1
+master-bin.001 311 Query 1 311 use `test`; create table t1 (word char(20) not null)
master-bin.001 386 Create_file 1 386 db=test;table=t1;file_id=1;block_len=81
master-bin.001 556 Exec_load 1 556 ;file_id=1
-master-bin.001 579 Query 1 579 use test; drop table t1
+master-bin.001 579 Query 1 579 use `test`; drop table t1
show binlog events from 79 limit 1;
Log_name Pos Event_type Server_id Orig_log_pos Info
-master-bin.001 79 Query 1 79 use test; create table t1(n int not null auto_increment primary key)
+master-bin.001 79 Query 1 79 use `test`; create table t1(n int not null auto_increment primary key)
show binlog events from 79 limit 2;
Log_name Pos Event_type Server_id Orig_log_pos Info
-master-bin.001 79 Query 1 79 use test; create table t1(n int not null auto_increment primary key)
+master-bin.001 79 Query 1 79 use `test`; create table t1(n int not null auto_increment primary key)
master-bin.001 172 Intvar 1 172 INSERT_ID=1
show binlog events from 79 limit 2,1;
Log_name Pos Event_type Server_id Orig_log_pos Info
-master-bin.001 200 Query 1 200 use test; insert into t1 values (NULL)
+master-bin.001 200 Query 1 200 use `test`; insert into t1 values (NULL)
flush logs;
create table t1 (n int);
insert into t1 values (1);
@@ -43,21 +43,21 @@ drop table t1;
show binlog events;
Log_name Pos Event_type Server_id Orig_log_pos Info
master-bin.001 4 Start 1 4 Server ver: VERSION, Binlog ver: 3
-master-bin.001 79 Query 1 79 use test; create table t1(n int not null auto_increment primary key)
+master-bin.001 79 Query 1 79 use `test`; create table t1(n int not null auto_increment primary key)
master-bin.001 172 Intvar 1 172 INSERT_ID=1
-master-bin.001 200 Query 1 200 use test; insert into t1 values (NULL)
-master-bin.001 263 Query 1 263 use test; drop table t1
-master-bin.001 311 Query 1 311 use test; create table t1 (word char(20) not null)
+master-bin.001 200 Query 1 200 use `test`; insert into t1 values (NULL)
+master-bin.001 263 Query 1 263 use `test`; drop table t1
+master-bin.001 311 Query 1 311 use `test`; create table t1 (word char(20) not null)
master-bin.001 386 Create_file 1 386 db=test;table=t1;file_id=1;block_len=81
master-bin.001 556 Exec_load 1 556 ;file_id=1
-master-bin.001 579 Query 1 579 use test; drop table t1
+master-bin.001 579 Query 1 579 use `test`; drop table t1
master-bin.001 627 Rotate 1 627 master-bin.002;pos=4
master-bin.001 668 Stop 1 668
show binlog events in 'master-bin.002';
Log_name Pos Event_type Server_id Orig_log_pos Info
-master-bin.002 4 Query 1 4 use test; create table t1 (n int)
-master-bin.002 62 Query 1 62 use test; insert into t1 values (1)
-master-bin.002 122 Query 1 122 use test; drop table t1
+master-bin.002 4 Query 1 4 use `test`; create table t1 (n int)
+master-bin.002 62 Query 1 62 use `test`; insert into t1 values (1)
+master-bin.002 122 Query 1 122 use `test`; drop table t1
show master logs;
Log_name
master-bin.001
@@ -71,9 +71,9 @@ show binlog events in 'slave-bin.001' from 4;
show binlog events in 'slave-bin.002' from 4;
Log_name Pos Event_type Server_id Orig_log_pos Info
slave-bin.002 4 Slave 2 627 host=127.0.0.1,port=MASTER_PORT,log=master-bin.002,pos=4
-slave-bin.002 57 Query 1 4 use test; create table t1 (n int)
-slave-bin.002 115 Query 1 62 use test; insert into t1 values (1)
-slave-bin.002 175 Query 1 122 use test; drop table t1
+slave-bin.002 57 Query 1 4 use `test`; create table t1 (n int)
+slave-bin.002 115 Query 1 62 use `test`; insert into t1 values (1)
+slave-bin.002 175 Query 1 122 use `test`; drop table t1
show slave status;
Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space
127.0.0.1 root MASTER_PORT 1 master-bin.002 170 slave-relay-bin.002 916 master-bin.002 Yes Yes 0 0 170 920
diff --git a/mysql-test/t/README b/mysql-test/t/README
deleted file mode 100644
index e69de29bb2d..00000000000
--- a/mysql-test/t/README
+++ /dev/null
diff --git a/mysql-test/t/rollback.test b/mysql-test/t/rollback.test
index 6ea2cca887f..bd37e69ae23 100644
--- a/mysql-test/t/rollback.test
+++ b/mysql-test/t/rollback.test
@@ -8,7 +8,12 @@ create table t1 (n int not null primary key) type=myisam;
begin work;
insert into t1 values (4);
insert into t1 values (5);
-# Should give an error
-!$1196 rollback;
+rollback;
+select @@warning_count;
+select @@error_count;
+show warnings;
+show errors;
select * from t1;
+select @@warning_count;
+show warnings;
drop table t1;
diff --git a/mysql-test/t/rpl_log_pos.test b/mysql-test/t/rpl_log_pos.test
index f585fa233c5..b96d32c7fca 100644
--- a/mysql-test/t/rpl_log_pos.test
+++ b/mysql-test/t/rpl_log_pos.test
@@ -23,6 +23,7 @@ change master to master_log_pos=173;
--replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT
slave start;
sleep 2;
+--replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT
show slave status;
connection master;
show master status;
diff --git a/mysys/hash.c b/mysys/hash.c
index 7fb634a05b9..43e6981f79d 100644
--- a/mysys/hash.c
+++ b/mysys/hash.c
@@ -35,11 +35,12 @@ static uint calc_hashnr(CHARSET_INFO *cs,const byte *key,uint length);
static uint calc_hashnr_caseup(CHARSET_INFO *cs, const byte *key,uint length);
static int hashcmp(HASH *hash,HASH_LINK *pos,const byte *key,uint length);
+
my_bool
_hash_init(HASH *hash,CHARSET_INFO *charset,
- uint size,uint key_offset,uint key_length,
- hash_get_key get_key,
- void (*free_element)(void*),uint flags CALLER_INFO_PROTO)
+ uint size,uint key_offset,uint key_length,
+ hash_get_key get_key,
+ void (*free_element)(void*),uint flags CALLER_INFO_PROTO)
{
DBUG_ENTER("hash_init");
DBUG_PRINT("enter",("hash: %lx size: %d",hash,size));
diff --git a/mysys/my_error.c b/mysys/my_error.c
index eaa126a31c1..cd41589f366 100644
--- a/mysys/my_error.c
+++ b/mysys/my_error.c
@@ -120,7 +120,7 @@ int my_error(int nr,myf MyFlags, ...)
... variable list
*/
-int my_printf_error (uint error, const char *format, myf MyFlags, ...)
+int my_printf_error(uint error, const char *format, myf MyFlags, ...)
{
va_list args;
char ebuff[ERRMSGSIZE+20];
diff --git a/mysys/tree.c b/mysys/tree.c
index 489262fcdc7..f72a4961312 100644
--- a/mysys/tree.c
+++ b/mysys/tree.c
@@ -17,26 +17,33 @@
/*
Code for handling red-black (balanced) binary trees.
key in tree is allocated accrding to following:
- 1) If free_element function is given to init_tree or size < 0 then tree
- will not allocate keys and only a pointer to each key is saved in tree.
- key_sizes must be 0 to init and search.
+
+ 1) If size < 0 then tree will not allocate keys and only a pointer to
+ each key is saved in tree.
+ compare and search functions uses and returns key-pointer
+
+ 2) If size == 0 then there are two options:
+ - key_size != 0 to tree_insert: The key will be stored in the tree.
+ - key_size == 0 to tree_insert: A pointer to the key is stored.
compare and search functions uses and returns key-pointer.
- 2) if key_size is given to init_tree then each node will continue the
+
+ 3) if key_size is given to init_tree then each node will continue the
key and calls to insert_key may increase length of key.
if key_size > sizeof(pointer) and key_size is a multiple of 8 (double
allign) then key will be put on a 8 alligned adress. Else
the key will be on adress (element+1). This is transparent for user
compare and search functions uses a pointer to given key-argument.
- 3) If init_tree - keysize is 0 then key_size must be given to tree_insert
- and tree_insert will alloc space for key.
- compare and search functions uses a pointer to given key-argument.
+
+ - If you use a free function for tree-elements and you are freeing
+ the element itself, you should use key_size = 0 to init_tree and
+ tree_search
The actual key in TREE_ELEMENT is saved as a pointer or after the
TREE_ELEMENT struct.
If one uses only pointers in tree one can use tree_set_pointer() to
change address of data.
- Copyright Monty Program KB.
- By monty.
+
+ Implemented by monty.
*/
#include "mysys_priv.h"
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 */
diff --git a/strings/ctype-simple.c b/strings/ctype-simple.c
index 19989afea60..f6c92edf1b8 100644
--- a/strings/ctype-simple.c
+++ b/strings/ctype-simple.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 MySQL AB
+/* Copyright (C) 2002 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -23,22 +23,24 @@ int my_strnxfrm_simple(CHARSET_INFO * cs,
char *dest, uint len,
const char *src, uint srclen)
{
+ uchar *map= cs->sort_order;
DBUG_ASSERT(len >= srclen);
for ( ; len > 0 ; len-- )
- *dest++= (char) cs->sort_order[(uchar) *src++];
+ *dest++= (char) map[(uchar) *src++];
return srclen;
}
-int my_strnncoll_simple(CHARSET_INFO * cs,const char *s, uint slen,
- const char *t, uint tlen)
+int my_strnncoll_simple(CHARSET_INFO * cs, const char *s, uint slen,
+ const char *t, uint tlen)
{
int len = ( slen > tlen ) ? tlen : slen;
+ uchar *map= cs->sort_order;
while (len--)
{
- if (cs->sort_order[(uchar) *s++] != cs->sort_order[(uchar) *t++])
- return ((int) cs->sort_order[(uchar) s[-1]] -
- (int) cs->sort_order[(uchar) t[-1]]);
+ if (map[(uchar) *s++] != map[(uchar) *t++])
+ return ((int) map[(uchar) s[-1]] -
+ (int) map[(uchar) t[-1]]);
}
return (int) (slen-tlen);
}
diff --git a/tests/client_test.c b/tests/client_test.c
index f988b7dec9a..a00c475129d 100644
--- a/tests/client_test.c
+++ b/tests/client_test.c
@@ -268,7 +268,7 @@ void my_print_result_metadata(MYSQL_RES *result)
for(i=0; i< field_count; i++)
{
field = mysql_fetch_field(result);
- fprintf(stdout, " %-*s |",field->max_length, field->name);
+ fprintf(stdout, " %-*s |",(int) field->max_length, field->name);
}
fputc('\n', stdout);
my_print_dashes(result);
@@ -296,11 +296,11 @@ int my_process_result_set(MYSQL *mysql, MYSQL_RES *result)
{
field = mysql_fetch_field(result);
if(row[i] == NULL)
- fprintf(stdout, " %-*s |", field->max_length, "NULL");
+ fprintf(stdout, " %-*s |", (int) field->max_length, "NULL");
else if (IS_NUM(field->type))
- fprintf(stdout, " %*s |", field->max_length, row[i]);
+ fprintf(stdout, " %*s |", (int) field->max_length, row[i]);
else
- fprintf(stdout, " %-*s |", field->max_length, row[i]);
+ fprintf(stdout, " %-*s |", (int) field->max_length, row[i]);
}
fputc('\t',stdout);
fputc('\n',stdout);
@@ -548,13 +548,15 @@ void test_tran_innodb(MYSQL *mysql)
mysql_autocommit(mysql,true);
}
+
/********************************************************
-* to test simple prepares of all DML statements *
+ To test simple prepares of all DML statements
*********************************************************/
+
void test_prepare_simple(MYSQL *mysql)
{
MYSQL_STMT *stmt;
- int rc,param_count,length;
+ int rc,param_count;
const char *query;
myheader("test_prepare_simple");
@@ -570,8 +572,7 @@ void test_prepare_simple(MYSQL *mysql)
/* alter table */
query = "ALTER TABLE test_prepare_simple ADD new char(20)";
- length = strlen(query);
- stmt = mysql_prepare(mysql, query);
+ stmt = mysql_prepare(mysql, query, strlen(query));
myxquery(mysql,stmt);
param_count = mysql_param_count(stmt);
@@ -581,8 +582,7 @@ void test_prepare_simple(MYSQL *mysql)
/* insert */
query = "INSERT INTO test_prepare_simple VALUES(?,?)";
- length = strlen(query);
- stmt = mysql_prepare(mysql, query);
+ stmt = mysql_prepare(mysql, query, strlen(query));
myxquery(mysql,stmt);
param_count = mysql_param_count(stmt);
@@ -592,8 +592,7 @@ void test_prepare_simple(MYSQL *mysql)
/* update */
query = "UPDATE test_prepare_simple SET id=? WHERE id=? AND name= ?";
- length = strlen(query);
- stmt = mysql_prepare(mysql, query);
+ stmt = mysql_prepare(mysql, query, strlen(query));
myxquery(mysql,stmt);
param_count = mysql_param_count(stmt);
@@ -603,8 +602,7 @@ void test_prepare_simple(MYSQL *mysql)
/* delete */
query = "DELETE FROM test_prepare_simple WHERE id=10";
- length = strlen(query);
- stmt = mysql_prepare(mysql, query);
+ stmt = mysql_prepare(mysql, query, strlen(query));
myxquery(mysql,stmt);
param_count = mysql_param_count(stmt);
@@ -617,8 +615,7 @@ void test_prepare_simple(MYSQL *mysql)
/* delete */
query = "DELETE FROM test_prepare_simple WHERE id=?";
- length = strlen(query);
- stmt = mysql_prepare(mysql, query);
+ stmt = mysql_prepare(mysql, query, strlen(query));
myxquery(mysql,stmt);
param_count = mysql_param_count(stmt);
@@ -631,8 +628,7 @@ void test_prepare_simple(MYSQL *mysql)
/* select */
query = "SELECT * FROM test_prepare_simple WHERE id=? AND name= ?";
- length = strlen(query);
- stmt = mysql_prepare(mysql, query);
+ stmt = mysql_prepare(mysql, query, strlen(query));
myxquery(mysql,stmt);
param_count = mysql_param_count(stmt);
@@ -653,7 +649,7 @@ void test_prepare_simple(MYSQL *mysql)
void test_prepare_field_result(MYSQL *mysql)
{
MYSQL_STMT *stmt;
- int rc,param_count,length;
+ int rc,param_count;
const char *query;
myheader("test_prepare_field_result");
@@ -670,8 +666,7 @@ void test_prepare_field_result(MYSQL *mysql)
/* insert */
query = "SELECT id,name FROM test_prepare_field_result WHERE id=?";
- length = strlen(query);
- stmt = mysql_prepare(mysql, query);
+ stmt = mysql_prepare(mysql, query, strlen(query));
myxquery(mysql,stmt);
param_count = mysql_param_count(stmt);
@@ -691,7 +686,7 @@ void test_prepare_field_result(MYSQL *mysql)
void test_prepare_syntax(MYSQL *mysql)
{
MYSQL_STMT *stmt;
- int rc,length;
+ int rc;
const char *query;
myheader("test_prepare_syntax");
@@ -706,13 +701,11 @@ void test_prepare_syntax(MYSQL *mysql)
myquery(mysql,rc);
query = "INSERT INTO test_prepare_syntax VALUES(?";
- length = strlen(query);
- stmt = mysql_prepare(mysql, query);
+ stmt = mysql_prepare(mysql, query, strlen(query));
myxquery_r(mysql,stmt);
query = "SELECT id,name FROM test_prepare_syntax WHERE id=? AND WHERE";
- length = strlen(query);
- stmt = mysql_prepare(mysql, query);
+ stmt = mysql_prepare(mysql, query, strlen(query));
myxquery_r(mysql,stmt);
/* now fetch the results ..*/
@@ -759,7 +752,7 @@ void test_prepare(MYSQL *mysql)
/* insert by prepare */
strcpy(query,"INSERT INTO my_prepare VALUES(?,?,?,?,?,?,?)");
- stmt = mysql_prepare(mysql, query);
+ stmt = mysql_prepare(mysql, query, strlen(query));
myxquery(mysql,stmt);
param_count = mysql_param_count(stmt);
@@ -861,7 +854,7 @@ void test_double_compare(MYSQL *mysql)
myquery(mysql,rc);
strcpy(query, "UPDATE test_double_compare SET col1=100 WHERE col1 = ? AND col2 = ? AND COL3 = ?");
- stmt = mysql_prepare(mysql,query);
+ stmt = mysql_prepare(mysql,query, strlen(query));
myxquery(mysql,stmt);
param_count = mysql_param_count(stmt);
@@ -937,13 +930,11 @@ void test_null(MYSQL *mysql)
/* insert by prepare, wrong column name */
query = "INSERT INTO test_null(col3,col2) VALUES(?,?)";
- nData = strlen(query);
- stmt = mysql_prepare(mysql, query);
+ stmt = mysql_prepare(mysql, query, strlen(query));
myxquery_r(mysql,stmt);
query = "INSERT INTO test_null(col1,col2) VALUES(?,?)";
- nData = strlen(query);
- stmt = mysql_prepare(mysql, query);
+ stmt = mysql_prepare(mysql, query, strlen(query));
myxquery(mysql,stmt);
param_count = mysql_param_count(stmt);
@@ -998,8 +989,7 @@ void test_select_simple(MYSQL *mysql)
/* insert by prepare */
strcpy((char *)query, "SHOW TABLES FROM mysql");
- length = strlen(query);
- stmt = mysql_prepare(mysql, query);
+ stmt = mysql_prepare(mysql, query, strlen(query));
myxquery(mysql,stmt);
length = mysql_param_count(stmt);
@@ -1079,8 +1069,7 @@ void test_select(MYSQL *mysql)
myquery(mysql,rc);
query = "SELECT * FROM test_select WHERE id=? AND name=?";
- nData = strlen(query);
- stmt = mysql_prepare(mysql, query);
+ stmt = mysql_prepare(mysql, query, strlen(query));
myxquery(mysql,stmt);
param_count = mysql_param_count(stmt);
@@ -1159,8 +1148,7 @@ void test_simple_update(MYSQL *mysql)
/* insert by prepare */
query = "UPDATE test_update SET col2=? WHERE col1=?";
- nData = strlen(query);
- stmt = mysql_prepare(mysql, query);
+ stmt = mysql_prepare(mysql, query, strlen(query));
myxquery(mysql,stmt);
param_count = mysql_param_count(stmt);
@@ -1208,7 +1196,6 @@ void test_long_data(MYSQL *mysql)
int rc,param_count;
const char *query;
char *data=NullS;
- int length;
MYSQL_RES *result;
MYSQL_BIND bind[2];
@@ -1233,8 +1220,7 @@ void test_long_data(MYSQL *mysql)
myquery(mysql,rc);
query = "INSERT INTO test_long_data(col2) VALUES(?)";
- length=strlen(query);
- stmt = mysql_prepare(mysql, query);
+ stmt = mysql_prepare(mysql, query, strlen(query));
myxquery(mysql,stmt);
param_count = mysql_param_count(stmt);
@@ -1261,7 +1247,7 @@ void test_long_data(MYSQL *mysql)
data = (char *)"Micheal";
/* supply data in pieces */
- rc = mysql_send_long_data(stmt,0,data,7);
+ rc = mysql_send_long_data(stmt,0,data,7,1);
mystmt(stmt, rc);
/* try to execute mysql_execute() now, it should return
@@ -1275,11 +1261,11 @@ void test_long_data(MYSQL *mysql)
/* supply data in pieces */
data = (char *)" 'monty' widenius";
- rc = mysql_send_long_data(stmt,0,data,17);
+ rc = mysql_send_long_data(stmt,0,data,17,0);
mystmt(stmt, rc);
/* Indiate end of data supply */
- rc = mysql_send_long_data(stmt,0,0,MYSQL_LONG_DATA_END);
+ rc = mysql_send_long_data(stmt,0,0,0,1);
mystmt(stmt, rc);
/* execute */
@@ -1311,7 +1297,7 @@ void test_long_data_str(MYSQL *mysql)
int rc,param_count;
const char *query;
char data[255];
- int length;
+ long length;
MYSQL_RES *result;
MYSQL_BIND bind[2];
@@ -1335,8 +1321,7 @@ void test_long_data_str(MYSQL *mysql)
myquery(mysql,rc);
query = "INSERT INTO test_long_data_str VALUES(?,?)";
- length=strlen(query);
- stmt = mysql_prepare(mysql, query);
+ stmt = mysql_prepare(mysql, query, strlen(query));
myxquery(mysql,stmt);
param_count = mysql_param_count(stmt);
@@ -1365,7 +1350,7 @@ void test_long_data_str(MYSQL *mysql)
int i;
for(i=0; i < 4; i++)
{
- rc = mysql_send_long_data(stmt,1,(char *)data,5);
+ rc = mysql_send_long_data(stmt,1,(char *)data,5,0);
mystmt(stmt, rc);
}
@@ -1378,7 +1363,7 @@ void test_long_data_str(MYSQL *mysql)
}
/* Indiate end of data supply */
- rc = mysql_send_long_data(stmt,1,0,MYSQL_LONG_DATA_END);
+ rc = mysql_send_long_data(stmt,1,0,0,1);
mystmt(stmt, rc);
/* execute */
@@ -1437,8 +1422,7 @@ void test_long_data_str1(MYSQL *mysql)
myquery(mysql,rc);
query = "INSERT INTO test_long_data_str VALUES(?,?)";
- length=strlen(query);
- stmt = mysql_prepare(mysql, query);
+ stmt = mysql_prepare(mysql, query, strlen(query));
myxquery(mysql,stmt);
param_count = mysql_param_count(stmt);
@@ -1467,10 +1451,10 @@ void test_long_data_str1(MYSQL *mysql)
int i;
for(i=0; i < 2; i++)
{
- rc = mysql_send_long_data(stmt,0,data,length);
+ rc = mysql_send_long_data(stmt,0,data,length,0);
mystmt(stmt, rc);
- rc = mysql_send_long_data(stmt,1,data,2);
+ rc = mysql_send_long_data(stmt,1,data,2,0);
mystmt(stmt, rc);
}
/* try to execute mysql_execute() now, it should return
@@ -1482,14 +1466,14 @@ void test_long_data_str1(MYSQL *mysql)
}
/* Indiate end of data supply */
- rc = mysql_send_long_data(stmt,1,0,MYSQL_LONG_DATA_END);
+ rc = mysql_send_long_data(stmt,1,0,0,1);
mystmt(stmt, rc);
rc = mysql_execute(stmt);
fprintf(stdout,"mysql_execute() returned %d\n",rc);
assert(rc == MYSQL_NEED_DATA);
- rc = mysql_send_long_data(stmt,0,0,MYSQL_LONG_DATA_END);
+ rc = mysql_send_long_data(stmt,0,0,0,1);
mystmt(stmt, rc);
/* execute */
@@ -1548,8 +1532,7 @@ void test_long_data_bin(MYSQL *mysql)
myquery(mysql,rc);
query = "INSERT INTO test_long_data_bin VALUES(?,?)";
- length=strlen(query);
- stmt = mysql_prepare(mysql, query);
+ stmt = mysql_prepare(mysql, query, strlen(query));
myxquery(mysql,stmt);
param_count = mysql_param_count(stmt);
@@ -1577,7 +1560,7 @@ void test_long_data_bin(MYSQL *mysql)
int i;
for(i=0; i < 100; i++)
{
- rc = mysql_send_long_data(stmt,1,(char *)data,4);
+ rc = mysql_send_long_data(stmt,1,(char *)data,4,0);
mystmt(stmt, rc);
}
@@ -1590,7 +1573,7 @@ void test_long_data_bin(MYSQL *mysql)
}
/* Indiate end of data supply */
- rc = mysql_send_long_data(stmt,1,0,MYSQL_LONG_DATA_END);
+ rc = mysql_send_long_data(stmt,1,0,0,1);
mystmt(stmt, rc);
/* execute */
@@ -1659,8 +1642,7 @@ void test_simple_delete(MYSQL *mysql)
/* insert by prepare */
query = "DELETE FROM test_simple_delete WHERE col1=? AND col2=? AND col3=100";
- nData = strlen(query);
- stmt = mysql_prepare(mysql, query);
+ stmt = mysql_prepare(mysql, query, strlen(query));
myxquery(mysql,stmt);
param_count = mysql_param_count(stmt);
@@ -1737,8 +1719,7 @@ void test_update(MYSQL *mysql)
myquery(mysql,rc);
query = "INSERT INTO test_update(col2,col3) VALUES(?,?)";
- nData = strlen(query);
- stmt = mysql_prepare(mysql, query);
+ stmt = mysql_prepare(mysql, query, strlen(query));
myxquery(mysql,stmt);
param_count = mysql_param_count(stmt);
@@ -1764,8 +1745,7 @@ void test_update(MYSQL *mysql)
/* insert by prepare */
query = "UPDATE test_update SET col2=? WHERE col3=?";
- nData = strlen(query);
- stmt = mysql_prepare(mysql, query);
+ stmt = mysql_prepare(mysql, query, strlen(query));
myxquery(mysql,stmt);
param_count = mysql_param_count(stmt);
@@ -1812,7 +1792,7 @@ void test_update(MYSQL *mysql)
void test_init_prepare(MYSQL *mysql)
{
MYSQL_STMT *stmt;
- int length, param_count, rc;
+ int param_count, rc;
const char *query;
MYSQL_RES *result;
@@ -1830,8 +1810,7 @@ void test_init_prepare(MYSQL *mysql)
/* insert by prepare */
query = "INSERT INTO my_prepare VALUES(10,'venu')";
- length = strlen(query);
- stmt = mysql_prepare(mysql, query);
+ stmt = mysql_prepare(mysql, query, strlen(query));
myxquery(mysql,stmt);
param_count = mysql_param_count(stmt);
@@ -1904,8 +1883,7 @@ void test_bind_result(MYSQL *mysql)
bind[1].buffer=szData; /* string data */
strcpy((char *)query , "SELECT * FROM test_bind_result");
- nData = strlen(query);
- stmt = mysql_prepare(mysql, query);
+ stmt = mysql_prepare(mysql, query, strlen(query));
myxquery(mysql,stmt);
rc = mysql_bind_result(stmt,bind);
@@ -2000,7 +1978,7 @@ void test_prepare_ext(MYSQL *mysql)
/* insert by prepare - all integers */
query = (char *)"INSERT INTO test_prepare_ext(c1,c2,c3,c4,c5,c6) VALUES(?,?,?,?,?,?)";
- stmt = mysql_prepare(mysql,query);
+ stmt = mysql_prepare(mysql,query, strlen(query));
myquery(mysql,rc);
param_count = mysql_param_count(stmt);
@@ -2189,7 +2167,7 @@ void test_insert(MYSQL *mysql)
/* insert by prepare */
bzero(bind, sizeof(bind));
strcpy(query,"INSERT INTO test_prep_insert VALUES(?,?)");
- stmt = mysql_prepare(mysql, query);
+ stmt = mysql_prepare(mysql, query, strlen(query));
myxquery(mysql,stmt);
param_count = mysql_param_count(stmt);
@@ -2260,7 +2238,7 @@ void test_prepare_resultset(MYSQL *mysql)
/* insert by prepare */
strcpy(query,"INSERT INTO test_prepare_resultset(id,name) VALUES(?,?)");
- stmt = mysql_prepare(mysql, query);
+ stmt = mysql_prepare(mysql, query, strlen(query));
myxquery(mysql,stmt);
param_count = mysql_param_count(stmt);