summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/mysql.h9
-rw-r--r--libmysql/libmysql.c12
-rw-r--r--libmysqld/emb_qcache.cc129
-rw-r--r--libmysqld/embedded_priv.h21
-rw-r--r--libmysqld/lib_sql.cc513
-rw-r--r--libmysqld/libmysqld.c14
-rw-r--r--mysql-test/t/backup.test3
-rw-r--r--mysql-test/t/binlog_stm_binlog.test1
-rw-r--r--mysql-test/t/binlog_stm_blackhole.test1
-rw-r--r--mysql-test/t/binlog_stm_ctype_cp932.test1
-rw-r--r--mysql-test/t/compress.test3
-rw-r--r--mysql-test/t/ctype_cp932_notembedded.test32
-rw-r--r--mysql-test/t/delayed.test3
-rw-r--r--mysql-test/t/federated.test2
-rw-r--r--mysql-test/t/federated_archive.test2
-rw-r--r--mysql-test/t/federated_bug_13118.test2
-rw-r--r--mysql-test/t/federated_transactions.test2
-rw-r--r--mysql-test/t/flush_table.test2
-rw-r--r--mysql-test/t/handler.test3
-rw-r--r--mysql-test/t/init_connect.test2
-rw-r--r--mysql-test/t/innodb.test26
-rw-r--r--mysql-test/t/innodb_notembedded.test36
-rw-r--r--mysql-test/t/mysql.test2
-rw-r--r--mysql-test/t/mysql_client_test.test3
-rw-r--r--mysql-test/t/mysqltest.test2
-rw-r--r--mysql-test/t/query_cache.test15
-rw-r--r--mysql-test/t/query_cache_notembedded.test84
-rw-r--r--mysql-test/t/read_only.test3
-rw-r--r--mysql-test/t/skip_grants.test3
-rw-r--r--mysql-test/t/sp-destruct.test3
-rw-r--r--mysql-test/t/sp-error.test22
-rw-r--r--mysql-test/t/sp-threads.test2
-rw-r--r--mysql-test/t/sp.test101
-rw-r--r--mysql-test/t/sp_notembedded.test261
-rw-r--r--mysql-test/t/subselect_notembedded.test8
-rw-r--r--mysql-test/t/view.test2
-rw-r--r--mysql-test/t/wait_timeout.test3
-rw-r--r--sql-common/client.c9
-rw-r--r--sql/mysqld.cc2
-rw-r--r--sql/protocol.cc82
-rw-r--r--sql/protocol.h9
-rw-r--r--sql/sql_class.cc6
-rw-r--r--sql/sql_class.h12
-rw-r--r--sql/sql_cursor.cc1
-rw-r--r--sql/sql_parse.cc31
-rw-r--r--sql/sql_prepare.cc11
46 files changed, 1031 insertions, 465 deletions
diff --git a/include/mysql.h b/include/mysql.h
index f3244d4ba36..303cb2af4f5 100644
--- a/include/mysql.h
+++ b/include/mysql.h
@@ -130,14 +130,14 @@ typedef MYSQL_ROWS *MYSQL_ROW_OFFSET; /* offset to current row */
#include "my_alloc.h"
+typedef struct embedded_query_result EMBEDDED_QUERY_RESULT;
typedef struct st_mysql_data {
my_ulonglong rows;
unsigned int fields;
MYSQL_ROWS *data;
MEM_ROOT alloc;
-#if !defined(CHECK_EMBEDDED_DIFFERENCES) || defined(EMBEDDED_LIBRARY)
- MYSQL_ROWS **prev_ptr;
-#endif
+ /* extra info for embedded library */
+ struct embedded_query_result *embedded_info;
} MYSQL_DATA;
enum mysql_option
@@ -287,6 +287,8 @@ typedef struct st_mysql
from mysql_stmt_close if close had to cancel result set of this object.
*/
my_bool *unbuffered_fetch_owner;
+ /* needed for embedded server - no net buffer to store the 'info' */
+ char *info_buffer;
} MYSQL;
typedef struct st_mysql_res {
@@ -755,6 +757,7 @@ typedef struct st_mysql_methods
const char *(*read_statistics)(MYSQL *mysql);
my_bool (*next_result)(MYSQL *mysql);
int (*read_change_user_result)(MYSQL *mysql, char *buff, const char *passwd);
+ int (*read_rows_from_cursor)(MYSQL_STMT *stmt);
#endif
} MYSQL_METHODS;
diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c
index 11ee7284cbf..e2ee44efffb 100644
--- a/libmysql/libmysql.c
+++ b/libmysql/libmysql.c
@@ -2722,13 +2722,13 @@ stmt_read_row_from_cursor(MYSQL_STMT *stmt, unsigned char **row)
/* Send row request to the server */
int4store(buff, stmt->stmt_id);
int4store(buff + 4, stmt->prefetch_rows); /* number of rows to fetch */
- if (cli_advanced_command(mysql, COM_STMT_FETCH, buff, sizeof(buff),
- NullS, 0, 1))
+ if ((*mysql->methods->advanced_command)(mysql, COM_STMT_FETCH,
+ buff, sizeof(buff), NullS, 0, 1))
{
set_stmt_errmsg(stmt, net->last_error, net->last_errno, net->sqlstate);
return 1;
}
- if (cli_read_binary_rows(stmt))
+ if ((*mysql->methods->read_rows_from_cursor)(stmt))
return 1;
stmt->server_status= mysql->server_status;
@@ -5101,9 +5101,9 @@ my_bool STDCALL mysql_autocommit(MYSQL * mysql, my_bool auto_mode)
DBUG_ENTER("mysql_autocommit");
DBUG_PRINT("enter", ("mode : %d", auto_mode));
- if (auto_mode) /* set to true */
- DBUG_RETURN((my_bool) mysql_real_query(mysql, "set autocommit=1", 16));
- DBUG_RETURN((my_bool) mysql_real_query(mysql, "set autocommit=0", 16));
+ DBUG_RETURN((my_bool) mysql_real_query(mysql, auto_mode ?
+ "set autocommit=1":"set autocommit=0",
+ 16));
}
diff --git a/libmysqld/emb_qcache.cc b/libmysqld/emb_qcache.cc
index ecc45096165..078243a6d5e 100644
--- a/libmysqld/emb_qcache.cc
+++ b/libmysqld/emb_qcache.cc
@@ -18,6 +18,7 @@
#ifdef HAVE_QUERY_CACHE
#include <mysql.h>
#include "emb_qcache.h"
+#include "embedded_priv.h"
void Querycache_stream::store_char(char c)
{
@@ -284,22 +285,25 @@ int Querycache_stream::load_column(MEM_ROOT *alloc, char** column)
uint emb_count_querycache_size(THD *thd)
{
- uint result;
- MYSQL *mysql= thd->mysql;
- MYSQL_FIELD *field= mysql->fields;
- MYSQL_FIELD *field_end= field + mysql->field_count;
- MYSQL_ROWS *cur_row=NULL;
- my_ulonglong n_rows=0;
+ uint result= 0;
+ MYSQL_FIELD *field;
+ MYSQL_FIELD *field_end;
+ MYSQL_ROWS *cur_row;
+ my_ulonglong n_rows;
+ MYSQL_DATA *data= thd->first_data;
+
+ while (data->embedded_info->next)
+ data= data->embedded_info->next;
+ field= data->embedded_info->fields_list;
+ field_end= field + data->fields;
if (!field)
- return 0;
- if (thd->data)
- {
- *thd->data->prev_ptr= NULL; // this marks the last record
- cur_row= thd->data->data;
- n_rows= thd->data->rows;
- }
- result= (uint) (4+8 + (42 + 4*n_rows)*mysql->field_count);
+ return result;
+ *data->embedded_info->prev_ptr= NULL; // this marks the last record
+ cur_row= data->data;
+ n_rows= data->rows;
+ /* n_fields + n_rows + (field_info + strlen * n_rows) * n_fields */
+ result+= (uint) (4+8 + (42 + 4*n_rows)*data->fields);
for(; field < field_end; field++)
{
@@ -313,34 +317,38 @@ uint emb_count_querycache_size(THD *thd)
for (; cur_row; cur_row=cur_row->next)
{
MYSQL_ROW col= cur_row->data;
- MYSQL_ROW col_end= col + mysql->field_count;
+ MYSQL_ROW col_end= col + data->fields;
for (; col < col_end; col++)
if (*col)
- result+= *(uint *)((*col) - sizeof(uint));
+ result+= *(uint *)((*col) - sizeof(uint));
}
return result;
}
void emb_store_querycache_result(Querycache_stream *dst, THD *thd)
{
- MYSQL *mysql= thd->mysql;
- MYSQL_FIELD *field= mysql->fields;
- MYSQL_FIELD *field_end= field + mysql->field_count;
- MYSQL_ROWS *cur_row= NULL;
- my_ulonglong n_rows= 0;
+ MYSQL_FIELD *field;
+ MYSQL_FIELD *field_end;
+ MYSQL_ROWS *cur_row;
+ my_ulonglong n_rows;
+ MYSQL_DATA *data= thd->first_data;
+
+ DBUG_ENTER("emb_store_querycache_result");
+
+ while (data->embedded_info->next)
+ data= data->embedded_info->next;
+ field= data->embedded_info->fields_list;
+ field_end= field + data->fields;
if (!field)
- return;
+ DBUG_VOID_RETURN;
- if (thd->data)
- {
- *thd->data->prev_ptr= NULL; // this marks the last record
- cur_row= thd->data->data;
- n_rows= thd->data->rows;
- }
+ *data->embedded_info->prev_ptr= NULL; // this marks the last record
+ cur_row= data->data;
+ n_rows= data->rows;
- dst->store_int((uint)mysql->field_count);
- dst->store_ll((uint)n_rows);
+ dst->store_int((uint)data->fields);
+ dst->store_ll((ulonglong)n_rows);
for(; field < field_end; field++)
{
@@ -356,14 +364,13 @@ void emb_store_querycache_result(Querycache_stream *dst, THD *thd)
dst->store_str(field->org_table, field->org_table_length);
dst->store_str(field->db, field->db_length);
dst->store_str(field->catalog, field->catalog_length);
-
dst->store_safe_str(field->def, field->def_length);
}
for (; cur_row; cur_row=cur_row->next)
{
MYSQL_ROW col= cur_row->data;
- MYSQL_ROW col_end= col + mysql->field_count;
+ MYSQL_ROW col_end= col + data->fields;
for (; col < col_end; col++)
{
uint len= *col ? *(uint *)((*col) - sizeof(uint)) : 0;
@@ -371,28 +378,34 @@ void emb_store_querycache_result(Querycache_stream *dst, THD *thd)
}
}
DBUG_ASSERT(emb_count_querycache_size(thd) == dst->stored_size);
+ DBUG_VOID_RETURN;
}
int emb_load_querycache_result(THD *thd, Querycache_stream *src)
{
- MYSQL *mysql= thd->mysql;
- MYSQL_DATA *data;
+ MYSQL_DATA *data= thd->alloc_new_dataset();
MYSQL_FIELD *field;
MYSQL_FIELD *field_end;
- MEM_ROOT *f_alloc= &mysql->field_alloc;
+ MEM_ROOT *f_alloc;
MYSQL_ROWS *row, *end_row;
MYSQL_ROWS **prev_row;
ulonglong rows;
MYSQL_ROW columns;
+ DBUG_ENTER("emb_load_querycache_result");
+
+ if (!data)
+ goto err;
+ init_alloc_root(&data->alloc, 8192,0);
+ f_alloc= &data->alloc;
- mysql->field_count= src->load_int();
+ data->fields= src->load_int();
rows= src->load_ll();
if (!(field= (MYSQL_FIELD *)
- alloc_root(&mysql->field_alloc,mysql->field_count*sizeof(MYSQL_FIELD))))
+ alloc_root(f_alloc,data->fields*sizeof(MYSQL_FIELD))))
goto err;
- mysql->fields= field;
- for(field_end= field+mysql->field_count; field < field_end; field++)
+ data->embedded_info->fields_list= field;
+ for(field_end= field+data->fields; field < field_end; field++)
{
field->length= src->load_int();
field->max_length= (unsigned int)src->load_int();
@@ -402,47 +415,43 @@ int emb_load_querycache_result(THD *thd, Querycache_stream *src)
field->decimals= (unsigned int)src->load_char();
if (!(field->name= src->load_str(f_alloc, &field->name_length)) ||
- !(field->table= src->load_str(f_alloc,&field->table_length)) ||
- !(field->org_name= src->load_str(f_alloc, &field->org_name_length)) ||
- !(field->org_table= src->load_str(f_alloc, &field->org_table_length))||
- !(field->db= src->load_str(f_alloc, &field->db_length)) ||
- !(field->catalog= src->load_str(f_alloc, &field->catalog_length)) ||
- src->load_safe_str(f_alloc, &field->def, &field->def_length))
+ !(field->table= src->load_str(f_alloc,&field->table_length)) ||
+ !(field->org_name= src->load_str(f_alloc, &field->org_name_length)) ||
+ !(field->org_table= src->load_str(f_alloc, &field->org_table_length))||
+ !(field->db= src->load_str(f_alloc, &field->db_length)) ||
+ !(field->catalog= src->load_str(f_alloc, &field->catalog_length)) ||
+ src->load_safe_str(f_alloc, &field->def, &field->def_length))
goto err;
}
- if (!rows)
- return 0;
- if (!(data= (MYSQL_DATA*)my_malloc(sizeof(MYSQL_DATA),
- MYF(MY_WME | MY_ZEROFILL))))
- goto err;
- thd->data= data;
- init_alloc_root(&data->alloc, 8192,0);
- row= (MYSQL_ROWS *)alloc_root(&data->alloc, (uint) (rows * sizeof(MYSQL_ROWS) +
- rows * (mysql->field_count+1)*sizeof(char*)));
+ row= (MYSQL_ROWS *)alloc_root(&data->alloc,
+ (uint) (rows * sizeof(MYSQL_ROWS) +
+ rows*(data->fields+1)*sizeof(char*)));
end_row= row + rows;
columns= (MYSQL_ROW)end_row;
data->rows= rows;
- data->fields= mysql->field_count;
data->data= row;
+ if (!rows)
+ goto return_ok;
for (prev_row= &row->next; row < end_row; prev_row= &row->next, row++)
{
*prev_row= row;
row->data= columns;
- MYSQL_ROW col_end= columns + mysql->field_count;
+ MYSQL_ROW col_end= columns + data->fields;
for (; columns < col_end; columns++)
src->load_column(&data->alloc, columns);
*(columns++)= NULL;
}
*prev_row= NULL;
- data->prev_ptr= prev_row;
-
- return 0;
+ data->embedded_info->prev_ptr= prev_row;
+return_ok:
+ send_eof(thd);
+ DBUG_RETURN(0);
err:
- return 1;
+ DBUG_RETURN(1);
}
#endif /*HAVE_QUERY_CACHE*/
diff --git a/libmysqld/embedded_priv.h b/libmysqld/embedded_priv.h
index d4316dff63f..88015340e8c 100644
--- a/libmysqld/embedded_priv.h
+++ b/libmysqld/embedded_priv.h
@@ -16,18 +16,25 @@
/* Prototypes for the embedded version of MySQL */
-#include <my_global.h>
-#include <mysql.h>
-#include <mysql_embed.h>
-#include <mysqld_error.h>
-#include <my_pthread.h>
-
C_MODE_START
void lib_connection_phase(NET *net, int phase);
void init_embedded_mysql(MYSQL *mysql, int client_flag, char *db);
void *create_embedded_thd(int client_flag, char *db);
int check_embedded_connection(MYSQL *mysql);
void free_old_query(MYSQL *mysql);
-void embedded_get_error(MYSQL *mysql);
extern MYSQL_METHODS embedded_methods;
+
+/* This one is used by embedded library to gather returning data */
+typedef struct embedded_query_result
+{
+ MYSQL_ROWS **prev_ptr;
+ unsigned int warning_count, server_status;
+ struct st_mysql_data *next;
+ my_ulonglong affected_rows, insert_id;
+ char info[MYSQL_ERRMSG_SIZE];
+ MYSQL_FIELD *fields_list;
+ unsigned int last_errno;
+ char sqlstate[SQLSTATE_LENGTH+1];
+} EQR;
+
C_MODE_END
diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc
index 8552b1c2b8a..fe60b4fd19c 100644
--- a/libmysqld/lib_sql.cc
+++ b/libmysqld/lib_sql.cc
@@ -42,21 +42,48 @@ C_MODE_START
#undef ER
#include "errmsg.h"
#include <sql_common.h>
+#include "embedded_priv.h"
-void embedded_get_error(MYSQL *mysql)
+static my_bool emb_read_query_result(MYSQL *mysql);
+
+void THD::clear_data_list()
{
- THD *thd=(THD *) mysql->thd;
- NET *net= &mysql->net;
- if ((net->last_errno= thd->net.last_errno))
- {
- memcpy(net->last_error, thd->net.last_error, sizeof(net->last_error));
- memcpy(net->sqlstate, thd->net.sqlstate, sizeof(net->sqlstate));
- }
- else
+ while (first_data)
{
- net->last_error[0]= 0;
- strmov(net->sqlstate, not_error_sqlstate);
+ MYSQL_DATA *data= first_data;
+ first_data= data->embedded_info->next;
+ free_rows(data);
}
+ data_tail= &first_data;
+ free_rows(cur_data);
+ cur_data= 0;
+}
+
+
+/*
+ Reads error information from the MYSQL_DATA and puts
+ it into proper MYSQL members
+
+ SYNOPSIS
+ embedded_get_error()
+ mysql connection handler
+ data query result
+
+ NOTES
+ after that function error information will be accessible
+ with usual functions like mysql_error()
+ data is my_free-d in this function
+ most of the data is stored in data->embedded_info structure
+*/
+
+void embedded_get_error(MYSQL *mysql, MYSQL_DATA *data)
+{
+ NET *net= &mysql->net;
+ struct embedded_query_result *ei= data->embedded_info;
+ net->last_errno= ei->last_errno;
+ strmake(net->last_error, ei->info, sizeof(net->last_error));
+ memcpy(net->sqlstate, ei->sqlstate, sizeof(net->sqlstate));
+ my_free((gptr) data, MYF(0));
}
static my_bool
@@ -68,11 +95,7 @@ emb_advanced_command(MYSQL *mysql, enum enum_server_command command,
THD *thd=(THD *) mysql->thd;
NET *net= &mysql->net;
- if (thd->data)
- {
- free_rows(thd->data);
- thd->data= 0;
- }
+ thd->clear_data_list();
/* Check that we are calling the client functions in right order */
if (mysql->status != MYSQL_STATUS_READY)
{
@@ -104,83 +127,101 @@ emb_advanced_command(MYSQL *mysql, enum enum_server_command command,
arg_length= header_length;
}
+ thd->net.no_send_error= 0;
result= dispatch_command(command, thd, (char *) arg, arg_length + 1);
+ thd->cur_data= 0;
if (!skip_check)
result= thd->net.last_errno ? -1 : 0;
- /*
- If mysql->field_count is set it means the parsing of the query was OK
- and metadata was returned (see Protocol::send_fields).
- In this case we postpone the error to be returned in mysql_stmt_store_result
- (see emb_read_rows) to behave just as standalone server.
- */
- if (!mysql->field_count)
- embedded_get_error(mysql);
- mysql->server_status= thd->server_status;
- mysql->warning_count= ((THD*)mysql->thd)->total_warn_count;
return result;
}
static void emb_flush_use_result(MYSQL *mysql)
{
- MYSQL_DATA *data= ((THD*)(mysql->thd))->data;
-
- if (data)
+ THD *thd= (THD*) mysql->thd;
+ if (thd->cur_data)
{
+ free_rows(thd->cur_data);
+ thd->cur_data= 0;
+ }
+ else if (thd->first_data)
+ {
+ MYSQL_DATA *data= thd->first_data;
+ thd->first_data= data->embedded_info->next;
free_rows(data);
- ((THD*)(mysql->thd))->data= NULL;
}
}
+
+/*
+ reads dataset from the next query result
+
+ SYNOPSIS
+ emb_read_rows()
+ mysql connection handle
+ other parameters are not used
+
+ NOTES
+ It just gets next MYSQL_DATA from the result's queue
+
+ RETURN
+ pointer to MYSQL_DATA with the coming recordset
+*/
+
static MYSQL_DATA *
emb_read_rows(MYSQL *mysql, MYSQL_FIELD *mysql_fields __attribute__((unused)),
unsigned int fields __attribute__((unused)))
{
- MYSQL_DATA *result= ((THD*)mysql->thd)->data;
- embedded_get_error(mysql);
- if (mysql->net.last_errno)
- return NULL;
- if (!result)
+ MYSQL_DATA *result= ((THD*)mysql->thd)->cur_data;
+ ((THD*)mysql->thd)->cur_data= 0;
+ if (result->embedded_info->last_errno)
{
- if (!(result=(MYSQL_DATA*) my_malloc(sizeof(MYSQL_DATA),
- MYF(MY_WME | MY_ZEROFILL))))
- {
- NET *net = &mysql->net;
- net->last_errno=CR_OUT_OF_MEMORY;
- strmov(net->sqlstate, unknown_sqlstate);
- strmov(net->last_error,ER(net->last_errno));
- return NULL;
- }
- return result;
- }
- *result->prev_ptr= NULL;
- ((THD*)mysql->thd)->data= NULL;
+ embedded_get_error(mysql, result);
+ return NULL;
+ }
+ *result->embedded_info->prev_ptr= NULL;
return result;
}
+
static MYSQL_FIELD *emb_list_fields(MYSQL *mysql)
{
+ MYSQL_DATA *res;
+ if (emb_read_query_result(mysql))
+ return 0;
+ res= ((THD*) mysql->thd)->cur_data;
+ ((THD*) mysql->thd)->cur_data= 0;
+ mysql->field_alloc= res->alloc;
+ my_free((gptr) res,MYF(0));
+ mysql->status= MYSQL_STATUS_READY;
return mysql->fields;
}
static my_bool emb_read_prepare_result(MYSQL *mysql, MYSQL_STMT *stmt)
{
- THD *thd= (THD*)mysql->thd;
- if (mysql->net.last_errno)
- return 1;
+ THD *thd= (THD*) mysql->thd;
+ MYSQL_DATA *res;
+
stmt->stmt_id= thd->client_stmt_id;
stmt->param_count= thd->client_param_count;
- stmt->field_count= mysql->field_count;
+ stmt->field_count= 0;
- if (stmt->field_count != 0)
+ if (thd->first_data)
{
+ if (emb_read_query_result(mysql))
+ return 1;
+ stmt->field_count= mysql->field_count;
+ mysql->status= MYSQL_STATUS_READY;
+ res= thd->cur_data;
+ thd->cur_data= NULL;
if (!(mysql->server_status & SERVER_STATUS_AUTOCOMMIT))
mysql->server_status|= SERVER_STATUS_IN_TRANS;
stmt->fields= mysql->fields;
- stmt->mem_root= mysql->field_alloc;
+ stmt->mem_root= res->alloc;
mysql->fields= NULL;
+ my_free((gptr) res,MYF(0));
}
return 0;
@@ -201,13 +242,42 @@ static void emb_fetch_lengths(ulong *to, MYSQL_ROW column,
*to= *column ? *(uint *)((*column) - sizeof(uint)) : 0;
}
-static my_bool emb_mysql_read_query_result(MYSQL *mysql)
+static my_bool emb_read_query_result(MYSQL *mysql)
{
- if (mysql->net.last_errno)
- return -1;
+ THD *thd= (THD*) mysql->thd;
+ MYSQL_DATA *res= thd->first_data;
+ DBUG_ASSERT(!thd->cur_data);
+ thd->first_data= res->embedded_info->next;
+ if (res->embedded_info->last_errno &&
+ !res->embedded_info->fields_list)
+ {
+ embedded_get_error(mysql, res);
+ return 1;
+ }
+
+ mysql->warning_count= res->embedded_info->warning_count;
+ mysql->server_status= res->embedded_info->server_status;
+ mysql->field_count= res->fields;
+ mysql->fields= res->embedded_info->fields_list;
+ mysql->affected_rows= res->embedded_info->affected_rows;
+ mysql->insert_id= res->embedded_info->insert_id;
+ mysql->net.last_errno= 0;
+ mysql->net.last_error[0]= 0;
+ mysql->info= 0;
+
+ if (res->embedded_info->info[0])
+ {
+ strmake(mysql->info_buffer, res->embedded_info->info, MYSQL_ERRMSG_SIZE-1);
+ mysql->info= mysql->info_buffer;
+ }
- if (mysql->field_count)
+ if (res->embedded_info->fields_list)
+ {
mysql->status=MYSQL_STATUS_GET_RESULT;
+ thd->cur_data= res;
+ }
+ else
+ my_free((gptr) res, MYF(0));
return 0;
}
@@ -215,14 +285,18 @@ static my_bool emb_mysql_read_query_result(MYSQL *mysql)
static int emb_stmt_execute(MYSQL_STMT *stmt)
{
DBUG_ENTER("emb_stmt_execute");
- char header[4];
+ char header[5];
+ MYSQL_DATA *res;
+ THD *thd;
+
int4store(header, stmt->stmt_id);
- THD *thd= (THD*)stmt->mysql->thd;
+ header[4]= stmt->flags;
+ thd= (THD*)stmt->mysql->thd;
thd->client_param_count= stmt->param_count;
thd->client_params= stmt->params;
if (emb_advanced_command(stmt->mysql, COM_STMT_EXECUTE,0,0,
header, sizeof(header), 1) ||
- emb_mysql_read_query_result(stmt->mysql))
+ emb_read_query_result(stmt->mysql))
{
NET *net= &stmt->mysql->net;
set_stmt_errmsg(stmt, net->last_error, net->last_errno, net->sqlstate);
@@ -230,6 +304,8 @@ static int emb_stmt_execute(MYSQL_STMT *stmt)
}
stmt->affected_rows= stmt->mysql->affected_rows;
stmt->insert_id= stmt->mysql->insert_id;
+ stmt->server_status= stmt->mysql->server_status;
+
DBUG_RETURN(0);
}
@@ -240,22 +316,53 @@ int emb_read_binary_rows(MYSQL_STMT *stmt)
return 1;
stmt->result= *data;
my_free((char *) data, MYF(0));
+ set_stmt_errmsg(stmt, stmt->mysql->net.last_error,
+ stmt->mysql->net.last_errno, stmt->mysql->net.sqlstate);
return 0;
}
+int emb_read_rows_from_cursor(MYSQL_STMT *stmt)
+{
+ MYSQL *mysql= stmt->mysql;
+ THD *thd= (THD*) mysql->thd;
+ MYSQL_DATA *res= thd->first_data;
+ DBUG_ASSERT(!thd->first_data->embedded_info->next);
+ thd->first_data= 0;
+ if (res->embedded_info->last_errno)
+ {
+ embedded_get_error(mysql, res);
+ set_stmt_errmsg(stmt, mysql->net.last_error,
+ mysql->net.last_errno, mysql->net.sqlstate);
+ return 1;
+ }
+
+ thd->cur_data= res;
+ mysql->warning_count= res->embedded_info->warning_count;
+ mysql->server_status= res->embedded_info->server_status;
+ mysql->net.last_errno= 0;
+ mysql->net.last_error[0]= 0;
+
+ return emb_read_binary_rows(stmt);
+}
+
int emb_unbuffered_fetch(MYSQL *mysql, char **row)
{
- MYSQL_DATA *data= ((THD*)mysql->thd)->data;
- embedded_get_error(mysql);
- if (mysql->net.last_errno)
- return mysql->net.last_errno;
+ THD *thd= (THD*) mysql->thd;
+ MYSQL_DATA *data= thd->cur_data;
+ if (data && data->embedded_info->last_errno)
+ {
+ embedded_get_error(mysql, data);
+ thd->cur_data= 0;
+ return 1;
+ }
if (!data || !data->data)
{
*row= NULL;
if (data)
{
+ thd->cur_data= thd->first_data;
+ thd->first_data= data->embedded_info->next;
free_rows(data);
- ((THD*)mysql->thd)->data= NULL;
}
}
else
@@ -269,9 +376,9 @@ int emb_unbuffered_fetch(MYSQL *mysql, char **row)
static void emb_free_embedded_thd(MYSQL *mysql)
{
THD *thd= (THD*)mysql->thd;
- if (thd->data)
- free_rows(thd->data);
+ thd->clear_data_list();
thread_count--;
+ thd->store_globals();
delete thd;
mysql->thd=0;
}
@@ -283,23 +390,11 @@ static const char * emb_read_statistics(MYSQL *mysql)
}
-static MYSQL_RES * emb_mysql_store_result(MYSQL *mysql)
+static MYSQL_RES * emb_store_result(MYSQL *mysql)
{
return mysql_store_result(mysql);
}
-my_bool emb_next_result(MYSQL *mysql)
-{
- THD *thd= (THD*)mysql->thd;
- DBUG_ENTER("emb_next_result");
-
- if (emb_advanced_command(mysql, COM_QUERY,0,0,
- thd->query_rest.ptr(),thd->query_rest.length(),1) ||
- emb_mysql_read_query_result(mysql))
- DBUG_RETURN(1);
-
- DBUG_RETURN(0); /* No more results */
-}
int emb_read_change_user_result(MYSQL *mysql,
char *buff __attribute__((unused)),
@@ -310,10 +405,10 @@ int emb_read_change_user_result(MYSQL *mysql,
MYSQL_METHODS embedded_methods=
{
- emb_mysql_read_query_result,
+ emb_read_query_result,
emb_advanced_command,
emb_read_rows,
- emb_mysql_store_result,
+ emb_store_result,
emb_fetch_lengths,
emb_flush_use_result,
emb_list_fields,
@@ -323,8 +418,9 @@ MYSQL_METHODS embedded_methods=
emb_unbuffered_fetch,
emb_free_embedded_thd,
emb_read_statistics,
- emb_next_result,
- emb_read_change_user_result
+ emb_read_query_result,
+ emb_read_change_user_result,
+ emb_read_rows_from_cursor
};
C_MODE_END
@@ -483,6 +579,7 @@ void init_embedded_mysql(MYSQL *mysql, int client_flag, char *db)
THD *thd = (THD *)mysql->thd;
thd->mysql= mysql;
mysql->server_version= server_version;
+ init_alloc_root(&mysql->field_alloc, 8192, 0);
}
void *create_embedded_thd(int client_flag, char *db)
@@ -490,6 +587,7 @@ void *create_embedded_thd(int client_flag, char *db)
THD * thd= new THD;
thd->thread_id= thread_id++;
+ thd->thread_stack= (char*) &thd;
if (thd->store_globals())
{
fprintf(stderr,"store_globals failed.\n");
@@ -498,7 +596,6 @@ void *create_embedded_thd(int client_flag, char *db)
thd->mysys_var= my_thread_var;
thd->dbug_thread_id= my_thread_id();
- thd->thread_stack= (char*) &thd;
/* TODO - add init_connect command execution */
@@ -517,9 +614,10 @@ void *create_embedded_thd(int client_flag, char *db)
thd->security_ctx->db_access= DB_ACLS;
thd->security_ctx->master_access= ~NO_ACCESS;
#endif
- thd->net.query_cache_query= 0;
-
- thd->data= 0;
+ thd->cur_data= 0;
+ thd->first_data= 0;
+ thd->data_tail= &thd->first_data;
+ bzero((char*) &thd->net, sizeof(thd->net));
thread_count++;
return thd;
@@ -531,11 +629,15 @@ err:
#ifdef NO_EMBEDDED_ACCESS_CHECKS
int check_embedded_connection(MYSQL *mysql)
{
+ int result;
THD *thd= (THD*)mysql->thd;
Security_context *sctx= thd->security_ctx;
- sctx->host_or_ip= sctx->host= (char*)my_localhost;
+ sctx->host_or_ip= sctx->host= (char*) my_localhost;
+ strmake(sctx->priv_host, (char*) my_localhost, MAX_HOSTNAME-1);
sctx->priv_user= sctx->user= my_strdup(mysql->user, MYF(0));
- return check_user(thd, COM_CONNECT, NULL, 0, thd->db, true);
+ result= check_user(thd, COM_CONNECT, NULL, 0, thd->db, true);
+ emb_read_query_result(mysql);
+ return result;
}
#else
@@ -616,26 +718,147 @@ static char *dup_str_aux(MEM_ROOT *root, const char *from, uint length,
}
+/*
+ creates new result and hooks it to the list
+
+ SYNOPSIS
+ alloc_new_dataset()
+
+ NOTES
+ allocs the MYSQL_DATA + embedded_query_result couple
+ to store the next query result,
+ links these two and attach it to the THD::data_tail
+
+ RETURN
+ pointer to the newly created query result
+*/
+
+MYSQL_DATA *THD::alloc_new_dataset()
+{
+ MYSQL_DATA *data;
+ struct embedded_query_result *emb_data;
+ if (!my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),
+ &data, sizeof(*data),
+ &emb_data, sizeof(*emb_data),
+ NULL))
+ return NULL;
+
+ emb_data->prev_ptr= &data->data;
+ cur_data= data;
+ *data_tail= data;
+ data_tail= &emb_data->next;
+ data->embedded_info= emb_data;
+ return data;
+}
+
+
+/*
+ stores server_status and warning_count in the current
+ query result structures
+
+ SYNOPSIS
+ write_eof_packet()
+ thd current thread
+
+ NOTES
+ should be called to after we get the recordset-result
+
+*/
+
+static void write_eof_packet(THD *thd)
+{
+ /*
+ The following test should never be true, but it's better to do it
+ because if 'is_fatal_error' is set the server is not going to execute
+ other queries (see the if test in dispatch_command / COM_QUERY)
+ */
+ if (thd->is_fatal_error)
+ thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
+ thd->cur_data->embedded_info->server_status= thd->server_status;
+ /*
+ Don't send warn count during SP execution, as the warn_list
+ is cleared between substatements, and mysqltest gets confused
+ */
+ thd->cur_data->embedded_info->warning_count=
+ (thd->spcont ? 0 : min(thd->total_warn_count, 65535));
+}
+
+
+/*
+ allocs new query result and initialises Protocol::alloc
+
+ SYNOPSIS
+ Protocol::begin_dataset()
+
+ RETURN
+ 0 if success
+ 1 if memory allocation failed
+*/
+
+int Protocol::begin_dataset()
+{
+ MYSQL_DATA *data= thd->alloc_new_dataset();
+ if (!data)
+ return 1;
+ alloc= &data->alloc;
+ init_alloc_root(alloc,8192,0); /* Assume rowlength < 8192 */
+ alloc->min_malloc=sizeof(MYSQL_ROWS);
+ return 0;
+}
+
+
+/*
+ remove last row of current recordset
+
+ SYNOPSIS
+ Protocol_simple::remove_last_row()
+
+ NOTES
+ does the loop from the beginning of the current recordset to
+ the last record and cuts it off.
+ Not supposed to be frequently called.
+*/
+
+void Protocol_simple::remove_last_row()
+{
+ MYSQL_DATA *data= thd->cur_data;
+ MYSQL_ROWS **last_row_hook= &data->data;
+ uint count= data->rows;
+ DBUG_ENTER("Protocol_simple::remove_last_row");
+ while (--count)
+ last_row_hook= &(*last_row_hook)->next;
+
+ *last_row_hook= 0;
+ data->embedded_info->prev_ptr= last_row_hook;
+ data->rows--;
+
+ DBUG_VOID_RETURN;
+}
+
+
bool Protocol::send_fields(List<Item> *list, uint flags)
{
List_iterator_fast<Item> it(*list);
Item *item;
MYSQL_FIELD *client_field;
- MYSQL *mysql= thd->mysql;
MEM_ROOT *field_alloc;
CHARSET_INFO *thd_cs= thd->variables.character_set_results;
CHARSET_INFO *cs= system_charset_info;
-
+ MYSQL_DATA *data;
DBUG_ENTER("send_fields");
- if (!mysql) // bootstrap file handling
+ if (!thd->mysql) // bootstrap file handling
DBUG_RETURN(0);
- field_count= list->elements;
- field_alloc= &mysql->field_alloc;
- if (!(client_field= thd->mysql->fields=
- (MYSQL_FIELD *)alloc_root(field_alloc,
- sizeof(MYSQL_FIELD) * field_count)))
+ if (begin_dataset())
+ goto err;
+
+ data= thd->cur_data;
+ data->fields= field_count= list->elements;
+ field_alloc= &data->alloc;
+
+ if (!(client_field= data->embedded_info->fields_list=
+ (MYSQL_FIELD*)alloc_root(field_alloc, sizeof(MYSQL_FIELD)*field_count)))
goto err;
while ((item= it++))
@@ -643,6 +866,10 @@ bool Protocol::send_fields(List<Item> *list, uint flags)
Send_field server_field;
item->make_field(&server_field);
+ /* Keep things compatible for old clients */
+ if (server_field.type == MYSQL_TYPE_VARCHAR)
+ server_field.type= MYSQL_TYPE_VAR_STRING;
+
client_field->db= dup_str_aux(field_alloc, server_field.db_name,
strlen(server_field.db_name), cs, thd_cs);
client_field->table= dup_str_aux(field_alloc, server_field.table_name,
@@ -703,7 +930,9 @@ bool Protocol::send_fields(List<Item> *list, uint flags)
client_field->max_length= 0;
++client_field;
}
- thd->mysql->field_count= field_count;
+
+ if (flags & SEND_EOF)
+ write_eof_packet(thd);
DBUG_RETURN(prepare_for_send(list));
err:
@@ -723,25 +952,11 @@ bool Protocol::write()
bool Protocol_prep::write()
{
MYSQL_ROWS *cur;
- MYSQL_DATA *data= thd->data;
-
- if (!data)
- {
- if (!(data= (MYSQL_DATA*) my_malloc(sizeof(MYSQL_DATA),
- MYF(MY_WME | MY_ZEROFILL))))
- return true;
-
- alloc= &data->alloc;
- init_alloc_root(alloc,8192,0); /* Assume rowlength < 8192 */
- alloc->min_malloc=sizeof(MYSQL_ROWS);
- data->rows=0;
- data->fields=field_count;
- data->prev_ptr= &data->data;
- thd->data= data;
- }
+ MYSQL_DATA *data= thd->cur_data;
data->rows++;
- if (!(cur= (MYSQL_ROWS *)alloc_root(alloc, sizeof(MYSQL_ROWS)+packet->length())))
+ if (!(cur= (MYSQL_ROWS *)alloc_root(alloc,
+ sizeof(MYSQL_ROWS)+packet->length())))
{
my_error(ER_OUT_OF_RESOURCES,MYF(0));
return true;
@@ -750,8 +965,8 @@ bool Protocol_prep::write()
memcpy(cur->data, packet->ptr()+1, packet->length()-1);
cur->length= packet->length(); /* To allow us to do sanity checks */
- *data->prev_ptr= cur;
- data->prev_ptr= &cur->next;
+ *data->embedded_info->prev_ptr= cur;
+ data->embedded_info->prev_ptr= &cur->next;
cur->next= 0;
return false;
@@ -761,46 +976,52 @@ void
send_ok(THD *thd,ha_rows affected_rows,ulonglong id,const char *message)
{
DBUG_ENTER("send_ok");
- MYSQL *mysql= current_thd->mysql;
+ MYSQL_DATA *data;
+ MYSQL *mysql= thd->mysql;
+
if (!mysql) // bootstrap file handling
DBUG_VOID_RETURN;
- mysql->affected_rows= affected_rows;
- mysql->insert_id= id;
+ if (thd->net.no_send_ok) // hack for re-parsing queries
+ DBUG_VOID_RETURN;
+ if (!(data= thd->alloc_new_dataset()))
+ return;
+ data->embedded_info->affected_rows= affected_rows;
+ data->embedded_info->insert_id= id;
if (message)
- {
- strmake(thd->net.last_error, message, sizeof(thd->net.last_error)-1);
- mysql->info= thd->net.last_error;
- }
+ strmake(data->embedded_info->info, message,
+ sizeof(data->embedded_info->info)-1);
+
+ write_eof_packet(thd);
+ thd->cur_data= 0;
DBUG_VOID_RETURN;
}
void
send_eof(THD *thd)
{
+ write_eof_packet(thd);
+ thd->cur_data= 0;
}
+
+void net_send_error_packet(THD *thd, uint sql_errno, const char *err)
+{
+ MYSQL_DATA *data= thd->cur_data ? thd->cur_data : thd->alloc_new_dataset();
+ struct embedded_query_result *ei= data->embedded_info;
+
+ ei->last_errno= sql_errno;
+ strmake(ei->info, err, sizeof(ei->info)-1);
+ strmov(ei->sqlstate, mysql_errno_to_sqlstate(sql_errno));
+ thd->cur_data= 0;
+}
+
+
void Protocol_simple::prepare_for_resend()
{
MYSQL_ROWS *cur;
- MYSQL_DATA *data= thd->data;
-
+ MYSQL_DATA *data= thd->cur_data;
DBUG_ENTER("send_data");
- if (!data)
- {
- if (!(data= (MYSQL_DATA*) my_malloc(sizeof(MYSQL_DATA),
- MYF(MY_WME | MY_ZEROFILL))))
- goto err;
-
- alloc= &data->alloc;
- init_alloc_root(alloc,8192,0); /* Assume rowlength < 8192 */
- alloc->min_malloc=sizeof(MYSQL_ROWS);
- data->rows=0;
- data->fields=field_count;
- data->prev_ptr= &data->data;
- thd->data= data;
- }
-
data->rows++;
if (!(cur= (MYSQL_ROWS *)alloc_root(alloc, sizeof(MYSQL_ROWS)+(field_count + 1) * sizeof(char *))))
{
@@ -809,10 +1030,10 @@ void Protocol_simple::prepare_for_resend()
}
cur->data= (MYSQL_ROW)(((char *)cur) + sizeof(MYSQL_ROWS));
- *data->prev_ptr= cur;
- data->prev_ptr= &cur->next;
+ *data->embedded_info->prev_ptr= cur;
+ data->embedded_info->prev_ptr= &cur->next;
next_field=cur->data;
- next_mysql_field= thd->mysql->fields;
+ next_mysql_field= data->embedded_info->fields_list;
err:
DBUG_VOID_RETURN;
}
diff --git a/libmysqld/libmysqld.c b/libmysqld/libmysqld.c
index 70074e44c6f..cad1bd4c47b 100644
--- a/libmysqld/libmysqld.c
+++ b/libmysqld/libmysqld.c
@@ -14,6 +14,11 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+#include <my_global.h>
+#include <mysql.h>
+#include <mysql_embed.h>
+#include <mysqld_error.h>
+#include <my_pthread.h>
#include "embedded_priv.h"
#include <my_sys.h>
#include <mysys_err.h>
@@ -193,7 +198,12 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
if (!user)
user= "";
- mysql->user=my_strdup(user,MYF(0));
+ /*
+ We need to alloc some space for mysql->info but don't want to
+ put extra 'my_free's in mysql_close.
+ So we alloc it with the 'user' string to be freed at once
+ */
+ mysql->user= my_strdup(user, MYF(0));
port=0;
unix_socket=0;
@@ -207,6 +217,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
if (db)
client_flag|=CLIENT_CONNECT_WITH_DB;
+ mysql->info_buffer= my_malloc(MYSQL_ERRMSG_SIZE, MYF(0));
mysql->thd= create_embedded_thd(client_flag, db_name);
init_embedded_mysql(mysql, client_flag, db_name);
@@ -243,7 +254,6 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
DBUG_RETURN(mysql);
error:
- embedded_get_error(mysql);
DBUG_PRINT("error",("message: %u (%s)", mysql->net.last_errno,
mysql->net.last_error));
{
diff --git a/mysql-test/t/backup.test b/mysql-test/t/backup.test
index 40a9fa73b60..a75837c1d2d 100644
--- a/mysql-test/t/backup.test
+++ b/mysql-test/t/backup.test
@@ -1,3 +1,6 @@
+# This test should work in embedded server after we fix mysqltest
+-- source include/not_embedded.inc
+
#
# This test is a bit tricky as we can't use backup table to overwrite an old
# table
diff --git a/mysql-test/t/binlog_stm_binlog.test b/mysql-test/t/binlog_stm_binlog.test
index da93d86c7ce..6d3dce9a323 100644
--- a/mysql-test/t/binlog_stm_binlog.test
+++ b/mysql-test/t/binlog_stm_binlog.test
@@ -1,5 +1,6 @@
# This is a wrapper for binlog.test so that the same test case can be used
# For both statement and row based bin logs 9/19/2005 [jbm]
+-- source include/not_embedded.inc
-- source include/have_binlog_format_statement.inc
-- source extra/binlog_tests/binlog.test
diff --git a/mysql-test/t/binlog_stm_blackhole.test b/mysql-test/t/binlog_stm_blackhole.test
index 3c0096fa3f6..6047d8ca2fc 100644
--- a/mysql-test/t/binlog_stm_blackhole.test
+++ b/mysql-test/t/binlog_stm_blackhole.test
@@ -1,5 +1,6 @@
# This is a wrapper for binlog.test so that the same test case can be used
# For both statement and row based bin logs 9/19/2005 [jbm]
+-- source include/not_embedded.inc
-- source include/have_binlog_format_statement.inc
-- source extra/binlog_tests/blackhole.test
diff --git a/mysql-test/t/binlog_stm_ctype_cp932.test b/mysql-test/t/binlog_stm_ctype_cp932.test
index cef179e0028..436f95a2453 100644
--- a/mysql-test/t/binlog_stm_ctype_cp932.test
+++ b/mysql-test/t/binlog_stm_ctype_cp932.test
@@ -1,5 +1,6 @@
# This is a wrapper for binlog.test so that the same test case can be used
# For both statement and row based bin logs 9/19/2005 [jbm]
+-- source include/not_embedded.inc
-- source include/have_binlog_format_statement.inc
-- source extra/binlog_tests/ctype_cp932.test
diff --git a/mysql-test/t/compress.test b/mysql-test/t/compress.test
index 46244edd2a8..3f1892b5dec 100644
--- a/mysql-test/t/compress.test
+++ b/mysql-test/t/compress.test
@@ -1,6 +1,9 @@
# Turn on compression between the client and server
# and run a number of tests
+# Can't test with embedded server
+-- source include/not_embedded.inc
+
-- source include/have_compress.inc
connect (comp_con,localhost,root,,,,,COMPRESS);
diff --git a/mysql-test/t/ctype_cp932_notembedded.test b/mysql-test/t/ctype_cp932_notembedded.test
new file mode 100644
index 00000000000..52e7acc3f01
--- /dev/null
+++ b/mysql-test/t/ctype_cp932_notembedded.test
@@ -0,0 +1,32 @@
+-- source include/not_embedded.inc
+-- source include/have_cp932.inc
+
+--character_set cp932
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+set names cp932;
+set character_set_database = cp932;
+
+# Test prepared statement with 0x8300 sequence in parameter while
+# running with cp932 client character set.
+RESET MASTER;
+CREATE TABLE t1(f1 blob);
+PREPARE stmt1 FROM 'INSERT INTO t1 VALUES(?)';
+SET @var1= x'8300';
+# TODO: Note that this doesn't actually test the code which was added for
+# bug#11338 because this syntax for prepared statements causes the PS to
+# be replicated differently than if we executed the PS from C or Java.
+# Using this syntax, variable names are inserted into the binlog instead
+# of values. The real goal of this test is to check the code that was
+# added to Item_param::query_val_str() in order to do hex encoding of
+# PS parameters when the client character set is cp932;
+# Bug#11338 has an example java program which can be used to verify this
+# code (and I have used it to test the fix) until there is some way to
+# exercise this code from mysql-test-run.
+EXECUTE stmt1 USING @var1;
+SHOW BINLOG EVENTS FROM 98;
+SELECT HEX(f1) FROM t1;
+DROP table t1;
+# end test for bug#11338
diff --git a/mysql-test/t/delayed.test b/mysql-test/t/delayed.test
index ca34cc020f3..5ae757b1fde 100644
--- a/mysql-test/t/delayed.test
+++ b/mysql-test/t/delayed.test
@@ -3,6 +3,9 @@
# (Can't be tested with purify :( )
#
+# This tests not performed with embedded server
+-- source include/not_embedded.inc
+
--disable_warnings
drop table if exists t1;
--enable_warnings
diff --git a/mysql-test/t/federated.test b/mysql-test/t/federated.test
index b6b3b90c083..a31fcf59074 100644
--- a/mysql-test/t/federated.test
+++ b/mysql-test/t/federated.test
@@ -1,3 +1,5 @@
+# should work with embedded server after mysqltest is fixed
+-- source include/not_embedded.inc
source include/federated.inc;
connection slave;
diff --git a/mysql-test/t/federated_archive.test b/mysql-test/t/federated_archive.test
index 6d80664fef7..f8df5f1c51a 100644
--- a/mysql-test/t/federated_archive.test
+++ b/mysql-test/t/federated_archive.test
@@ -1,3 +1,5 @@
+# should work with embedded server after mysqltest is fixed
+-- source include/not_embedded.inc
source include/have_archive.inc;
source include/federated.inc;
diff --git a/mysql-test/t/federated_bug_13118.test b/mysql-test/t/federated_bug_13118.test
index deec79becd2..e429a660489 100644
--- a/mysql-test/t/federated_bug_13118.test
+++ b/mysql-test/t/federated_bug_13118.test
@@ -1,3 +1,5 @@
+# should work with embedded server after mysqltest is fixed
+-- source include/not_embedded.inc
source include/federated.inc;
diff --git a/mysql-test/t/federated_transactions.test b/mysql-test/t/federated_transactions.test
index 1a5b14ca8b4..5095c8ce9c3 100644
--- a/mysql-test/t/federated_transactions.test
+++ b/mysql-test/t/federated_transactions.test
@@ -1,3 +1,5 @@
+# should work with embedded server after mysqltest is fixed
+-- source include/not_embedded.inc
source include/have_bdb.inc;
source include/federated.inc;
diff --git a/mysql-test/t/flush_table.test b/mysql-test/t/flush_table.test
index 0ea0ac0840a..50e7e91419a 100644
--- a/mysql-test/t/flush_table.test
+++ b/mysql-test/t/flush_table.test
@@ -4,6 +4,8 @@
# Test of flush table
#
+# Should work in embedded server after mysqltest is fixed
+-- source include/not_embedded.inc
--disable_warnings
drop table if exists t1,t2;
--enable_warnings
diff --git a/mysql-test/t/handler.test b/mysql-test/t/handler.test
index f3e14c3cd2b..cce1c5de725 100644
--- a/mysql-test/t/handler.test
+++ b/mysql-test/t/handler.test
@@ -2,6 +2,9 @@
# test of HANDLER ...
#
+# should work in embedded server after mysqltest is fixed
+-- source include/not_embedded.inc
+
--disable_warnings
drop table if exists t1;
--enable_warnings
diff --git a/mysql-test/t/init_connect.test b/mysql-test/t/init_connect.test
index 2e3c67a7d38..0ee6387d985 100644
--- a/mysql-test/t/init_connect.test
+++ b/mysql-test/t/init_connect.test
@@ -2,6 +2,8 @@
# Test of init_connect variable
#
+# should work with embedded server after mysqltest is fixed
+-- source include/not_embedded.inc
connect (con0,localhost,root,,);
connection con0;
select hex(@a);
diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test
index 71b92c419ca..10cb1dcf08b 100644
--- a/mysql-test/t/innodb.test
+++ b/mysql-test/t/innodb.test
@@ -1576,33 +1576,7 @@ connection a;
checksum table t1;
drop table t1;
-#
-# BUG#11238 - in prelocking mode SELECT .. FOR UPDATE is changed to
-# non-blocking SELECT
-#
-create table t1 (col1 integer primary key, col2 integer) engine=innodb;
-insert t1 values (1,100);
-delimiter |;
-create function f1 () returns integer begin
-declare var1 int;
-select col2 into var1 from t1 where col1=1 for update;
-return var1;
-end|
-delimiter ;|
-start transaction;
-select f1();
-connection b;
-send update t1 set col2=0 where col1=1;
-connection default;
-select * from t1;
-connection a;
-rollback;
-connection b;
-reap;
-rollback;
connection default;
-drop table t1;
-drop function f1;
disconnect a;
disconnect b;
diff --git a/mysql-test/t/innodb_notembedded.test b/mysql-test/t/innodb_notembedded.test
new file mode 100644
index 00000000000..1d8a590be78
--- /dev/null
+++ b/mysql-test/t/innodb_notembedded.test
@@ -0,0 +1,36 @@
+-- source include/not_embedded.inc
+-- source include/have_innodb.inc
+
+connect (a,localhost,root,,);
+connect (b,localhost,root,,);
+
+
+#
+# BUG#11238 - in prelocking mode SELECT .. FOR UPDATE is changed to
+# non-blocking SELECT
+#
+create table t1 (col1 integer primary key, col2 integer) engine=innodb;
+insert t1 values (1,100);
+delimiter |;
+create function f1 () returns integer begin
+declare var1 int;
+select col2 into var1 from t1 where col1=1 for update;
+return var1;
+end|
+delimiter ;|
+start transaction;
+select f1();
+connection b;
+send update t1 set col2=0 where col1=1;
+connection default;
+select * from t1;
+connection a;
+rollback;
+connection b;
+reap;
+rollback;
+connection default;
+drop table t1;
+drop function f1;
+disconnect a;
+disconnect b;
diff --git a/mysql-test/t/mysql.test b/mysql-test/t/mysql.test
index 0783c043ef6..7871ec3690e 100644
--- a/mysql-test/t/mysql.test
+++ b/mysql-test/t/mysql.test
@@ -1,3 +1,5 @@
+# This test should work in embedded server after we fix mysqltest
+-- source include/not_embedded.inc
#
# Testing the MySQL command line client(mysql)
#
diff --git a/mysql-test/t/mysql_client_test.test b/mysql-test/t/mysql_client_test.test
index 66b57dd5fb7..1225bf73009 100644
--- a/mysql-test/t/mysql_client_test.test
+++ b/mysql-test/t/mysql_client_test.test
@@ -1,3 +1,6 @@
+# This test should work in embedded server after we fix mysqltest
+-- source include/not_embedded.inc
+
# We run with different binaries for normal and --embedded-server
#
# If this test fails with "command "$MYSQL_CLIENT_TEST" failed",
diff --git a/mysql-test/t/mysqltest.test b/mysql-test/t/mysqltest.test
index 440a7787985..1f5c798e6fe 100644
--- a/mysql-test/t/mysqltest.test
+++ b/mysql-test/t/mysqltest.test
@@ -1,3 +1,5 @@
+# This test should work in embedded server after mysqltest is fixed
+-- source include/not_embedded.inc
# ============================================================================
#
diff --git a/mysql-test/t/query_cache.test b/mysql-test/t/query_cache.test
index 9b4a64872d9..a99d802e5a5 100644
--- a/mysql-test/t/query_cache.test
+++ b/mysql-test/t/query_cache.test
@@ -822,29 +822,14 @@ select sql_cache * from t1 where s1=1;
end;//
delimiter ;//
call f1();
-show status like "Qcache_queries_in_cache";
-show status like "Qcache_inserts";
-show status like "Qcache_hits";
call f1();
-show status like "Qcache_queries_in_cache";
-show status like "Qcache_inserts";
-show status like "Qcache_hits";
call f1();
select sql_cache * from t1;
-show status like "Qcache_queries_in_cache";
-show status like "Qcache_inserts";
-show status like "Qcache_hits";
insert into t1 values (1);
select sql_cache * from t1;
-show status like "Qcache_queries_in_cache";
-show status like "Qcache_inserts";
-show status like "Qcache_hits";
call f1();
call f1();
select sql_cache * from t1;
-show status like "Qcache_queries_in_cache";
-show status like "Qcache_inserts";
-show status like "Qcache_hits";
flush query cache;
reset query cache;
flush status;
diff --git a/mysql-test/t/query_cache_notembedded.test b/mysql-test/t/query_cache_notembedded.test
index fd4785ffe95..5e1ab7051e5 100644
--- a/mysql-test/t/query_cache_notembedded.test
+++ b/mysql-test/t/query_cache_notembedded.test
@@ -97,4 +97,88 @@ connection root;
SELECT * FROM t1;
drop table t1;
+#
+# query in QC from normal execution and SP (BUG#6897)
+# improved to also test BUG#3583 and BUG#12990
+#
+flush query cache;
+reset query cache;
+flush status;
+delimiter //;
+create table t1 (s1 int)//
+create procedure f1 () begin
+select sql_cache * from t1;
+select sql_cache * from t1;
+select sql_cache * from t1;
+end;//
+create procedure f2 () begin
+select sql_cache * from t1 where s1=1;
+select sql_cache * from t1;
+end;//
+create procedure f3 () begin
+select sql_cache * from t1;
+select sql_cache * from t1 where s1=1;
+end;//
+create procedure f4 () begin
+select sql_cache * from t1;
+select sql_cache * from t1 where s1=1;
+select sql_cache * from t1;
+select sql_cache * from t1 where s1=1;
+select sql_cache * from t1 where s1=1;
+end;//
+delimiter ;//
+call f1();
+--replace_result 1 3
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+call f1();
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+call f1();
+select sql_cache * from t1;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+insert into t1 values (1);
+select sql_cache * from t1;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+call f1();
+call f1();
+select sql_cache * from t1;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+flush query cache;
+reset query cache;
+flush status;
+select sql_cache * from t1;
+select sql_cache * from t1 where s1=1;
+call f1();
+call f2();
+call f3();
+call f4();
+call f4();
+call f3();
+call f2();
+select sql_cache * from t1 where s1=1;
+insert into t1 values (2);
+call f1();
+select sql_cache * from t1 where s1=1;
+select sql_cache * from t1;
+call f1();
+call f3();
+call f3();
+call f1();
+
+drop procedure f1;
+drop procedure f2;
+drop procedure f3;
+drop procedure f4;
+drop table t1;
+
+
set GLOBAL query_cache_size=0;
diff --git a/mysql-test/t/read_only.test b/mysql-test/t/read_only.test
index 0861951a6a1..1e92e438122 100644
--- a/mysql-test/t/read_only.test
+++ b/mysql-test/t/read_only.test
@@ -1,6 +1,9 @@
# Test of the READ_ONLY global variable:
# check that it blocks updates unless they are only on temporary tables.
+# should work with embedded server after mysqltest is fixed
+-- source include/not_embedded.inc
+
--disable_warnings
DROP TABLE IF EXISTS t1,t2,t3;
--enable_warnings
diff --git a/mysql-test/t/skip_grants.test b/mysql-test/t/skip_grants.test
index 16b0fbc4d25..a0164cb0759 100644
--- a/mysql-test/t/skip_grants.test
+++ b/mysql-test/t/skip_grants.test
@@ -1,3 +1,6 @@
+# This tests not performed with embedded server
+-- source include/not_embedded.inc
+
--disable_warnings
drop table if exists t1,v1;
drop view if exists t1,v1;
diff --git a/mysql-test/t/sp-destruct.test b/mysql-test/t/sp-destruct.test
index a2a66090866..4f812453f45 100644
--- a/mysql-test/t/sp-destruct.test
+++ b/mysql-test/t/sp-destruct.test
@@ -35,10 +35,13 @@ create trigger t1_ai after insert on t1 for each row call bug14233();
# Unsupported tampering with the mysql.proc definition
alter table mysql.proc drop type;
+--replace_result $MYSQL_TEST_DIR .
--error ER_SP_PROC_TABLE_CORRUPT
call bug14233();
+--replace_result $MYSQL_TEST_DIR .
--error ER_SP_PROC_TABLE_CORRUPT
create view v1 as select bug14233_f();
+--replace_result $MYSQL_TEST_DIR .
--error ER_SP_PROC_TABLE_CORRUPT
insert into t1 values (0);
diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test
index cf8f8dfc79c..cabd00fe5f9 100644
--- a/mysql-test/t/sp-error.test
+++ b/mysql-test/t/sp-error.test
@@ -648,28 +648,6 @@ call bug3294()|
drop procedure bug3294|
#
-# BUG#6807: Stored procedure crash if CREATE PROCEDURE ... KILL QUERY
-#
---disable_warnings
-drop procedure if exists bug6807|
---enable_warnings
-create procedure bug6807()
-begin
- declare id int;
-
- set id = connection_id();
- kill query id;
- select 'Not reached';
-end|
-
---error 1317
-call bug6807()|
---error 1317
-call bug6807()|
-
-drop procedure bug6807|
-
-#
# BUG#876: Stored Procedures: Invalid SQLSTATE is allowed in
# a DECLARE ? HANDLER FOR stmt.
#
diff --git a/mysql-test/t/sp-threads.test b/mysql-test/t/sp-threads.test
index 70c1efb1f0b..d8a8ce5dae7 100644
--- a/mysql-test/t/sp-threads.test
+++ b/mysql-test/t/sp-threads.test
@@ -1,3 +1,5 @@
+# This test should work in embedded server after mysqltest is fixed
+-- source include/not_embedded.inc
#
# Testing stored procedures with multiple connections,
# except security/privilege tests, they go to sp-security.test
diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test
index 91973da6c22..54444a91fbb 100644
--- a/mysql-test/t/sp.test
+++ b/mysql-test/t/sp.test
@@ -1368,11 +1368,11 @@ end|
call ifac(20)|
select * from fac|
drop table fac|
---replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
+--replace_column 4 'root@localhost' 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
show function status like '%f%'|
drop procedure ifac|
drop function fac|
---replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
+--replace_column 4 'root@localhost' 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
show function status like '%f%'|
@@ -1455,7 +1455,7 @@ begin
end while;
end|
show create procedure opp|
---replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
+--replace_column 4 'root@localhost' 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
show procedure status like '%p%'|
# This isn't the fastest way in the world to compute prime numbers, so
@@ -1473,7 +1473,7 @@ select * from primes where i=45 or i=100 or i=199|
drop table primes|
drop procedure opp|
drop procedure ip|
---replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
+--replace_column 4 'root@localhost' 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
show procedure status like '%p%'|
@@ -1541,13 +1541,13 @@ drop procedure if exists bar|
create procedure bar(x char(16), y int)
comment "111111111111" sql security invoker
insert into test.t1 values (x, y)|
---replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
+--replace_column 4 'root@localhost' 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
show procedure status like 'bar'|
alter procedure bar comment "2222222222" sql security definer|
alter procedure bar comment "3333333333"|
alter procedure bar|
show create procedure bar|
---replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
+--replace_column 4 'root@localhost' 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
show procedure status like 'bar'|
drop procedure bar|
@@ -2497,7 +2497,6 @@ begin
show databases like 'foo';
show errors;
show columns from t1;
- show grants for 'root'@'localhost';
show keys from t1;
show open tables like 'foo';
show privileges;
@@ -2519,20 +2518,6 @@ call bug4902()|
drop procedure bug4902|
-# We need separate SP for SHOW PROCESSLIST since we want use replace_column
---disable_warnings
-drop procedure if exists bug4902_2|
---enable_warnings
-create procedure bug4902_2()
-begin
- show processlist;
-end|
---replace_column 1 # 6 # 3 localhost
-call bug4902_2()|
---replace_column 1 # 6 # 3 localhost
-call bug4902_2()|
-drop procedure bug4902_2|
-
#
# BUG#4904
#
@@ -2747,44 +2732,6 @@ select @x|
delete from t1|
drop procedure bug4941|
-
-#
-# BUG#3583: query cache doesn't work for stored procedures
-#
---disable_warnings
-drop procedure if exists bug3583|
---enable_warnings
---disable_warnings
-drop procedure if exists bug3583|
---enable_warnings
-create procedure bug3583()
-begin
- declare c int;
-
- select * from t1;
- select count(*) into c from t1;
- select c;
-end|
-
-insert into t1 values ("x", 3), ("y", 5)|
-set @x = @@query_cache_size|
-set global query_cache_size = 10*1024*1024|
-
-flush status|
-flush query cache|
-show status like 'Qcache_hits'|
-call bug3583()|
-show status like 'Qcache_hits'|
-call bug3583()|
-call bug3583()|
-show status like 'Qcache_hits'|
-
-set global query_cache_size = @x|
-flush status|
-flush query cache|
-delete from t1|
-drop procedure bug3583|
-
#
# BUG#4905: Stored procedure doesn't clear for "Rows affected"
#
@@ -3094,24 +3041,6 @@ select id, bug5240() from t1|
drop function bug5240|
#
-# BUG#5278: Stored procedure packets out of order if SET PASSWORD.
-#
---disable_warnings
-drop function if exists bug5278|
---enable_warnings
-create function bug5278 () returns char
-begin
- SET PASSWORD FOR 'bob'@'%.loc.gov' = PASSWORD('newpass');
- return 'okay';
-end|
-
---error 1133
-select bug5278()|
---error 1133
-select bug5278()|
-drop function bug5278|
-
-#
# BUG#7992: rolling back temporary Item tree changes in SP
#
--disable_warnings
@@ -4733,24 +4662,6 @@ select bug10100f(5)|
call bug10100t(5)|
#end of the stack checking
-set @@max_sp_recursion_depth=255|
-set @var=1|
-#disable log because error about stack overrun contains numbers which
-#depend on a system
--- disable_result_log
--- error ER_STACK_OVERRUN_NEED_MORE
-call bug10100p(255, @var)|
--- error ER_STACK_OVERRUN_NEED_MORE
-call bug10100pt(1,255)|
--- error ER_STACK_OVERRUN_NEED_MORE
-call bug10100pv(1,255)|
--- error ER_STACK_OVERRUN_NEED_MORE
-call bug10100pd(1,255)|
--- error ER_STACK_OVERRUN_NEED_MORE
-call bug10100pc(1,255)|
--- enable_result_log
-set @@max_sp_recursion_depth=0|
-
deallocate prepare stmt2|
drop function bug10100f|
diff --git a/mysql-test/t/sp_notembedded.test b/mysql-test/t/sp_notembedded.test
new file mode 100644
index 00000000000..964b5d313c8
--- /dev/null
+++ b/mysql-test/t/sp_notembedded.test
@@ -0,0 +1,261 @@
+# Can't test with embedded server
+-- source include/not_embedded.inc
+
+delimiter |;
+
+#
+# BUG#4902: Stored procedure with SHOW WARNINGS leads to packet error
+#
+# Added tests for show grants command
+--disable_warnings
+drop procedure if exists bug4902|
+--enable_warnings
+create procedure bug4902()
+begin
+ show grants for 'root'@'localhost';
+end|
+--disable_parsing
+show binlog events;
+show storage engines;
+show master status;
+show slave hosts;
+show slave status;
+--enable_parsing
+
+call bug4902()|
+call bug4902()|
+
+drop procedure bug4902|
+
+# We need separate SP for SHOW PROCESSLIST since we want use replace_column
+--disable_warnings
+drop procedure if exists bug4902_2|
+--enable_warnings
+create procedure bug4902_2()
+begin
+ show processlist;
+end|
+--replace_column 1 # 6 # 3 localhost
+call bug4902_2()|
+--replace_column 1 # 6 # 3 localhost
+call bug4902_2()|
+drop procedure bug4902_2|
+
+
+#
+# BUG#5278: Stored procedure packets out of order if SET PASSWORD.
+#
+--disable_warnings
+drop function if exists bug5278|
+--enable_warnings
+create function bug5278 () returns char
+begin
+ SET PASSWORD FOR 'bob'@'%.loc.gov' = PASSWORD('newpass');
+ return 'okay';
+end|
+
+--error 1133
+select bug5278()|
+--error 1133
+select bug5278()|
+drop function bug5278|
+
+
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+create table t1 (
+ id char(16) not null default '',
+ data int not null
+);
+#
+# BUG#3583: query cache doesn't work for stored procedures
+#
+--disable_warnings
+drop procedure if exists bug3583|
+--enable_warnings
+--disable_warnings
+drop procedure if exists bug3583|
+--enable_warnings
+create procedure bug3583()
+begin
+ declare c int;
+
+ select * from t1;
+ select count(*) into c from t1;
+ select c;
+end|
+
+insert into t1 values ("x", 3), ("y", 5)|
+set @x = @@query_cache_size|
+set global query_cache_size = 10*1024*1024|
+
+flush status|
+flush query cache|
+show status like 'Qcache_hits'|
+call bug3583()|
+show status like 'Qcache_hits'|
+call bug3583()|
+call bug3583()|
+show status like 'Qcache_hits'|
+
+set global query_cache_size = @x|
+flush status|
+flush query cache|
+delete from t1|
+drop procedure bug3583|
+drop table t1;
+
+#
+# BUG#6807: Stored procedure crash if CREATE PROCEDURE ... KILL QUERY
+#
+--disable_warnings
+drop procedure if exists bug6807|
+--enable_warnings
+create procedure bug6807()
+begin
+ declare id int;
+
+ set id = connection_id();
+ kill query id;
+ select 'Not reached';
+end|
+
+--error 1317
+call bug6807()|
+--error 1317
+call bug6807()|
+
+drop procedure bug6807|
+
+#
+# BUG#10100: function (and stored procedure?) recursivity problem
+#
+--disable_warnings
+drop function if exists bug10100f|
+drop procedure if exists bug10100p|
+drop procedure if exists bug10100t|
+drop procedure if exists bug10100pt|
+drop procedure if exists bug10100pv|
+drop procedure if exists bug10100pd|
+drop procedure if exists bug10100pc|
+--enable_warnings
+# routines with simple recursion
+create function bug10100f(prm int) returns int
+begin
+ if prm > 1 then
+ return prm * bug10100f(prm - 1);
+ end if;
+ return 1;
+end|
+create procedure bug10100p(prm int, inout res int)
+begin
+ set res = res * prm;
+ if prm > 1 then
+ call bug10100p(prm - 1, res);
+ end if;
+end|
+create procedure bug10100t(prm int)
+begin
+ declare res int;
+ set res = 1;
+ call bug10100p(prm, res);
+ select res;
+end|
+
+# a procedure which use tables and recursion
+create table t3 (a int)|
+insert into t3 values (0)|
+create view v1 as select a from t3;
+create procedure bug10100pt(level int, lim int)
+begin
+ if level < lim then
+ update t3 set a=level;
+ FLUSH TABLES;
+ call bug10100pt(level+1, lim);
+ else
+ select * from t3;
+ end if;
+end|
+# view & recursion
+create procedure bug10100pv(level int, lim int)
+begin
+ if level < lim then
+ update v1 set a=level;
+ FLUSH TABLES;
+ call bug10100pv(level+1, lim);
+ else
+ select * from v1;
+ end if;
+end|
+# dynamic sql & recursion
+prepare stmt2 from "select * from t3;";
+create procedure bug10100pd(level int, lim int)
+begin
+ if level < lim then
+ select level;
+ prepare stmt1 from "update t3 set a=a+2";
+ execute stmt1;
+ FLUSH TABLES;
+ execute stmt1;
+ FLUSH TABLES;
+ execute stmt1;
+ FLUSH TABLES;
+ deallocate prepare stmt1;
+ execute stmt2;
+ select * from t3;
+ call bug10100pd(level+1, lim);
+ else
+ execute stmt2;
+ end if;
+end|
+# cursor & recursion
+create procedure bug10100pc(level int, lim int)
+begin
+ declare lv int;
+ declare c cursor for select a from t3;
+ open c;
+ if level < lim then
+ select level;
+ fetch c into lv;
+ select lv;
+ update t3 set a=level+lv;
+ FLUSH TABLES;
+ call bug10100pc(level+1, lim);
+ else
+ select * from t3;
+ end if;
+ close c;
+end|
+
+#end of the stack checking
+set @@max_sp_recursion_depth=255|
+set @var=1|
+#disable log because error about stack overrun contains numbers which
+#depend on a system
+-- disable_result_log
+-- error ER_STACK_OVERRUN_NEED_MORE
+call bug10100p(255, @var)|
+-- error ER_STACK_OVERRUN_NEED_MORE
+call bug10100pt(1,255)|
+-- error ER_STACK_OVERRUN_NEED_MORE
+call bug10100pv(1,255)|
+-- error ER_STACK_OVERRUN_NEED_MORE
+call bug10100pd(1,255)|
+-- error ER_STACK_OVERRUN_NEED_MORE
+call bug10100pc(1,255)|
+-- enable_result_log
+set @@max_sp_recursion_depth=0|
+
+deallocate prepare stmt2|
+
+drop function bug10100f|
+drop procedure bug10100p|
+drop procedure bug10100t|
+drop procedure bug10100pt|
+drop procedure bug10100pv|
+drop procedure bug10100pd|
+drop procedure bug10100pc|
+drop view v1|
+
+delimiter ;|
diff --git a/mysql-test/t/subselect_notembedded.test b/mysql-test/t/subselect_notembedded.test
new file mode 100644
index 00000000000..c5b23f6dac8
--- /dev/null
+++ b/mysql-test/t/subselect_notembedded.test
@@ -0,0 +1,8 @@
+-- source include/not_embedded.inc
+
+#
+# BUG #10308: purge log with subselect
+#
+
+purge master logs before (select adddate(current_timestamp(), interval -4 day));
+
diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test
index 3a0e33f6aae..957b74b9c8c 100644
--- a/mysql-test/t/view.test
+++ b/mysql-test/t/view.test
@@ -2084,7 +2084,9 @@ drop table t1, t2;
#
-- error ER_MALFORMED_DEFINER
create definer=some_user@`` sql security invoker view v1 as select 1;
+--disable_warnings
create definer=some_user@localhost sql security invoker view v1 as select 1;
+--enable_warnings
show create view v1;
drop view v1;
diff --git a/mysql-test/t/wait_timeout.test b/mysql-test/t/wait_timeout.test
index 26f91569868..4c1aeee5c04 100644
--- a/mysql-test/t/wait_timeout.test
+++ b/mysql-test/t/wait_timeout.test
@@ -1,3 +1,6 @@
+# This tests not performed with embedded server
+-- source include/not_embedded.inc
+
#
# Bug #8731: wait_timeout does not work on Mac OS X
#
diff --git a/sql-common/client.c b/sql-common/client.c
index 4c2debd41ff..8e55cf7c2b7 100644
--- a/sql-common/client.c
+++ b/sql-common/client.c
@@ -1545,7 +1545,8 @@ static MYSQL_METHODS client_methods=
NULL,
cli_read_statistics,
cli_read_query_result,
- cli_read_change_user_result
+ cli_read_change_user_result,
+ cli_read_binary_rows
#endif
};
@@ -2339,8 +2340,9 @@ static void mysql_close_free(MYSQL *mysql)
my_free(mysql->user,MYF(MY_ALLOW_ZERO_PTR));
my_free(mysql->passwd,MYF(MY_ALLOW_ZERO_PTR));
my_free(mysql->db,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(mysql->info_buffer,MYF(MY_ALLOW_ZERO_PTR));
/* Clear pointers for better safety */
- mysql->host_info=mysql->user=mysql->passwd=mysql->db=0;
+ mysql->info_buffer=mysql->host_info=mysql->user=mysql->passwd=mysql->db=0;
}
@@ -2476,8 +2478,7 @@ get_info:
if (!(mysql->server_status & SERVER_STATUS_AUTOCOMMIT))
mysql->server_status|= SERVER_STATUS_IN_TRANS;
- if (!(fields=(*mysql->methods->read_rows)(mysql,(MYSQL_FIELD*)0,
- protocol_41(mysql) ? 7 : 5)))
+ if (!(fields=cli_read_rows(mysql,(MYSQL_FIELD*)0, protocol_41(mysql) ? 7:5)))
DBUG_RETURN(1);
if (!(mysql->fields=unpack_fields(fields,&mysql->field_alloc,
(uint) field_count,0,
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 2a51afbee8d..3682f16613f 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -2449,9 +2449,7 @@ static int my_message_sql(uint error, const char *str, myf MyFlags)
{
NET *net= &thd->net;
net->report_error= 1;
-#ifndef EMBEDDED_LIBRARY /* TODO query cache in embedded library*/
query_cache_abort(net);
-#endif
if (!net->last_error[0]) // Return only first message
{
strmake(net->last_error, str, sizeof(net->last_error)-1);
diff --git a/sql/protocol.cc b/sql/protocol.cc
index 0a1b42f5236..98cded56871 100644
--- a/sql/protocol.cc
+++ b/sql/protocol.cc
@@ -29,6 +29,7 @@
static const unsigned int PACKET_BUFFER_EXTRA_ALLOC= 1024;
static void write_eof_packet(THD *thd, NET *net);
+void net_send_error_packet(THD *thd, uint sql_errno, const char *err);
#ifndef EMBEDDED_LIBRARY
bool Protocol::net_store_data(const char *from, uint length)
@@ -56,10 +57,6 @@ bool Protocol_prep::net_store_data(const char *from, uint length)
void net_send_error(THD *thd, uint sql_errno, const char *err)
{
-#ifndef EMBEDDED_LIBRARY
- uint length;
- char buff[MYSQL_ERRMSG_SIZE+2], *pos;
-#endif
NET *net= &thd->net;
bool generate_warning= thd->killed != THD::KILL_CONNECTION;
DBUG_ENTER("net_send_error");
@@ -106,42 +103,8 @@ void net_send_error(THD *thd, uint sql_errno, const char *err)
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, sql_errno, err);
}
-#ifdef EMBEDDED_LIBRARY
- net->last_errno= sql_errno;
- strmake(net->last_error, err, sizeof(net->last_error)-1);
- strmov(net->sqlstate, mysql_errno_to_sqlstate(sql_errno));
-#else
-
- if (net->vio == 0)
- {
- if (thd->bootstrap)
- {
- /* In bootstrap it's ok to print on stderr */
- fprintf(stderr,"ERROR: %d %s\n",sql_errno,err);
- }
- DBUG_VOID_RETURN;
- }
+ net_send_error_packet(thd, sql_errno, err);
- if (net->return_errno)
- { // new client code; Add errno before message
- int2store(buff,sql_errno);
- pos= buff+2;
- if (thd->client_capabilities & CLIENT_PROTOCOL_41)
- {
- /* The first # is to make the protocol backward compatible */
- buff[2]= '#';
- pos= strmov(buff+3, mysql_errno_to_sqlstate(sql_errno));
- }
- length= (uint) (strmake(pos, err, MYSQL_ERRMSG_SIZE-1) - buff);
- err=buff;
- }
- else
- {
- length=(uint) strlen(err);
- set_if_smaller(length,MYSQL_ERRMSG_SIZE-1);
- }
- VOID(net_write_command(net,(uchar) 255, "", 0, (char*) err,length));
-#endif /* EMBEDDED_LIBRARY*/
thd->is_fatal_error=0; // Error message is given
thd->net.report_error= 0;
@@ -430,6 +393,47 @@ bool send_old_password_request(THD *thd)
return my_net_write(net, eof_buff, 1) || net_flush(net);
}
+
+void net_send_error_packet(THD *thd, uint sql_errno, const char *err)
+{
+ NET *net= &thd->net;
+ uint length;
+ char buff[MYSQL_ERRMSG_SIZE+2], *pos;
+
+ DBUG_ENTER("send_error_packet");
+
+ if (net->vio == 0)
+ {
+ if (thd->bootstrap)
+ {
+ /* In bootstrap it's ok to print on stderr */
+ fprintf(stderr,"ERROR: %d %s\n",sql_errno,err);
+ }
+ DBUG_VOID_RETURN;
+ }
+
+ if (net->return_errno)
+ { // new client code; Add errno before message
+ int2store(buff,sql_errno);
+ pos= buff+2;
+ if (thd->client_capabilities & CLIENT_PROTOCOL_41)
+ {
+ /* The first # is to make the protocol backward compatible */
+ buff[2]= '#';
+ pos= strmov(buff+3, mysql_errno_to_sqlstate(sql_errno));
+ }
+ length= (uint) (strmake(pos, err, MYSQL_ERRMSG_SIZE-1) - buff);
+ err=buff;
+ }
+ else
+ {
+ length=(uint) strlen(err);
+ set_if_smaller(length,MYSQL_ERRMSG_SIZE-1);
+ }
+ VOID(net_write_command(net,(uchar) 255, "", 0, (char*) err,length));
+ DBUG_VOID_RETURN;
+}
+
#endif /* EMBEDDED_LIBRARY */
/*
diff --git a/sql/protocol.h b/sql/protocol.h
index 8d9da5774b2..85c22724b74 100644
--- a/sql/protocol.h
+++ b/sql/protocol.h
@@ -91,6 +91,12 @@ public:
virtual bool store_date(TIME *time)=0;
virtual bool store_time(TIME *time)=0;
virtual bool store(Field *field)=0;
+#ifdef EMBEDDED_LIBRARY
+ int begin_dataset();
+ virtual void remove_last_row() {}
+#else
+ void remove_last_row() {}
+#endif
};
@@ -117,6 +123,9 @@ public:
virtual bool store(float nr, uint32 decimals, String *buffer);
virtual bool store(double from, uint32 decimals, String *buffer);
virtual bool store(Field *field);
+#ifdef EMBEDDED_LIBRARY
+ void remove_last_row();
+#endif
};
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 08d89228a72..4644145c856 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -951,7 +951,9 @@ bool select_send::send_data(List<Item> &items)
thd->sent_row_count++;
if (!thd->vio_ok())
DBUG_RETURN(0);
- if (!thd->net.report_error)
+ if (thd->net.report_error)
+ protocol->remove_last_row();
+ else
DBUG_RETURN(protocol->write());
DBUG_RETURN(1);
}
@@ -1983,10 +1985,8 @@ void THD::reset_sub_statement_state(Sub_statement_state *backup,
cuted_fields= 0;
transaction.savepoints= 0;
-#ifndef EMBEDDED_LIBRARY
/* Surpress OK packets in case if we will execute statements */
net.no_send_ok= TRUE;
-#endif
}
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 1ef3322bc8f..fc31742240b 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -801,13 +801,16 @@ public:
#ifdef EMBEDDED_LIBRARY
struct st_mysql *mysql;
- struct st_mysql_data *data;
unsigned long client_stmt_id;
unsigned long client_param_count;
struct st_mysql_bind *client_params;
char *extra_data;
ulong extra_length;
- String query_rest;
+ struct st_mysql_data *cur_data;
+ struct st_mysql_data *first_data;
+ struct st_mysql_data **data_tail;
+ void clear_data_list();
+ struct st_mysql_data *alloc_new_dataset();
#endif
NET net; // client connection descriptor
MEM_ROOT warn_root; // For warnings and errors
@@ -1441,6 +1444,11 @@ public:
*/
virtual void cleanup();
void set_thd(THD *thd_arg) { thd= thd_arg; }
+#ifdef EMBEDDED_LIBRARY
+ virtual void begin_dataset() {}
+#else
+ void begin_dataset() {}
+#endif
};
diff --git a/sql/sql_cursor.cc b/sql/sql_cursor.cc
index 89c160cd70a..33ad27b9d14 100644
--- a/sql/sql_cursor.cc
+++ b/sql/sql_cursor.cc
@@ -603,6 +603,7 @@ void Materialized_cursor::fetch(ulong num_rows)
THD *thd= table->in_use;
int res= 0;
+ result->begin_dataset();
for (fetch_limit+= num_rows; fetch_count < fetch_limit; fetch_count++)
{
if ((res= table->file->rnd_next(table->record[0])))
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 4def568635d..5a3d25f9de7 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -1713,13 +1713,10 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
net->no_send_error= 0;
/*
Multiple queries exits, execute them individually
- in embedded server - just store them to be executed later
*/
-#ifndef EMBEDDED_LIBRARY
if (thd->lock || thd->open_tables || thd->derived_tables ||
thd->prelocked_mode)
close_thread_tables(thd);
-#endif
ulong length= (ulong)(packet_end-packet);
log_slow_statement(thd);
@@ -1737,25 +1734,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
thd->set_time(); /* Reset the query start time. */
/* TODO: set thd->lex->sql_command to SQLCOM_END here */
VOID(pthread_mutex_unlock(&LOCK_thread_count));
-#ifndef EMBEDDED_LIBRARY
mysql_parse(thd, packet, length);
-#else
- /*
- 'packet' can point inside the query_rest's buffer
- so we have to do memmove here
- */
- if (thd->query_rest.length() > length)
- {
- memmove(thd->query_rest.c_ptr(), packet, length);
- thd->query_rest.length(length);
- }
- else
- thd->query_rest.copy(packet, length, thd->query_rest.charset());
-
- thd->server_status&= ~ (SERVER_QUERY_NO_INDEX_USED |
- SERVER_QUERY_NO_GOOD_INDEX_USED);
- break;
-#endif /*EMBEDDED_LIBRARY*/
}
if (!(specialflag & SPECIAL_NO_PRIOR))
@@ -4242,10 +4221,8 @@ end_with_restore_list:
goto error;
}
-#ifndef EMBEDDED_LIBRARY
my_bool nsok= thd->net.no_send_ok;
thd->net.no_send_ok= TRUE;
-#endif
if (sp->m_flags & sp_head::MULTI_RESULTS)
{
if (! (thd->client_capabilities & CLIENT_MULTI_RESULTS))
@@ -4255,9 +4232,7 @@ end_with_restore_list:
back
*/
my_error(ER_SP_BADSELECT, MYF(0), sp->m_qname.str);
-#ifndef EMBEDDED_LIBRARY
thd->net.no_send_ok= nsok;
-#endif
goto error;
}
/*
@@ -4274,18 +4249,14 @@ end_with_restore_list:
sp->m_db.str, sp->m_name.str, TRUE, 0) ||
sp_change_security_context(thd, sp, &save_ctx))
{
-#ifndef EMBEDDED_LIBRARY
thd->net.no_send_ok= nsok;
-#endif
goto error;
}
if (save_ctx &&
check_routine_access(thd, EXECUTE_ACL,
sp->m_db.str, sp->m_name.str, TRUE, 0))
{
-#ifndef EMBEDDED_LIBRARY
thd->net.no_send_ok= nsok;
-#endif
sp_restore_security_context(thd, save_ctx);
goto error;
}
@@ -4317,9 +4288,7 @@ end_with_restore_list:
sp_restore_security_context(thd, save_ctx);
#endif
-#ifndef EMBEDDED_LIBRARY
thd->net.no_send_ok= nsok;
-#endif
thd->server_status&= ~bits_to_be_cleared;
if (!res)
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 7b35f057217..78487dd965d 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -92,6 +92,12 @@ public:
virtual bool send_fields(List<Item> &list, uint flags);
virtual bool send_data(List<Item> &items);
virtual bool send_eof();
+#ifdef EMBEDDED_LIBRARY
+ void begin_dataset()
+ {
+ protocol.begin_dataset();
+ }
+#endif
};
/******************************************************************************
@@ -524,9 +530,10 @@ void set_param_time(Item_param *param, uchar **pos, ulong len)
void set_param_datetime(Item_param *param, uchar **pos, ulong len)
{
- MYSQL_TIME *to= (MYSQL_TIME*)*pos;
+ MYSQL_TIME tm= *((MYSQL_TIME*)*pos);
+ tm.neg= 0;
- param->set_time(to, MYSQL_TIMESTAMP_DATETIME,
+ param->set_time(&tm, MYSQL_TIMESTAMP_DATETIME,
MAX_DATETIME_WIDTH * MY_CHARSET_BIN_MB_MAXLEN);
}