Fixes to embedded server to be able to run tests with it

(Needed for "list of pushes" web page and autopush)


include/mysql.h:
  Fix to embedded server to be able to run tests on it
libmysql/libmysql.c:
  Fix to embedded server to be able to run tests on it
libmysqld/emb_qcache.cc:
  Fix to embedded server to be able to run tests on it
libmysqld/embedded_priv.h:
  Fix to embedded server to be able to run tests on it
libmysqld/lib_sql.cc:
  Fix to embedded server to be able to run tests on it
libmysqld/libmysqld.c:
  Fix to embedded server to be able to run tests on it
mysql-test/mysql-test-run.sh:
  Fix to embedded server to be able to run tests on it
mysql-test/r/binlog.result:
  Updated test for embedded server
mysql-test/r/ctype_cp932.result:
  Updated test for embedded server
mysql-test/r/innodb.result:
  Updated test for embedded server
mysql-test/r/mysqltest.result:
  Updated test for embedded server
mysql-test/r/query_cache.result:
  Updated test for embedded server
mysql-test/r/query_cache_notembedded.result:
  Updated test for embedded server
mysql-test/r/sp-error.result:
  Updated test for embedded server
mysql-test/r/sp.result:
  Updated test for embedded server
mysql-test/r/subselect.result:
  Updated test for embedded server
mysql-test/r/view.result:
  Updated test for embedded server
mysql-test/r/view_grant.result:
  Updated test for embedded server
mysql-test/t/backup.test:
  Updated test for embedded server
mysql-test/t/binlog.test:
  Updated test for embedded server
mysql-test/t/blackhole.test:
  Updated test for embedded server
mysql-test/t/compress.test:
  Updated test for embedded server
mysql-test/t/ctype_cp932.test:
  Updated test for embedded server
mysql-test/t/delayed.test:
  Updated test for embedded server
mysql-test/t/handler.test:
  Updated test for embedded server
mysql-test/t/innodb.test:
  Updated test for embedded server
mysql-test/t/mysql.test:
  Updated test for embedded server
mysql-test/t/mysql_client_test.test:
  Updated test for embedded server
mysql-test/t/mysqltest.test:
  Updated test for embedded server
mysql-test/t/query_cache.test:
  Updated test for embedded server
mysql-test/t/query_cache_notembedded.test:
  Updated test for embedded server
mysql-test/t/read_only.test:
  Updated test for embedded server
mysql-test/t/skip_grants.test:
  Updated test for embedded server
mysql-test/t/sp-destruct.test:
  Updated test for embedded server
mysql-test/t/sp-error.test:
  Updated test for embedded server
mysql-test/t/sp-threads.test:
  Updated test for embedded server
mysql-test/t/sp.test:
  Updated test for embedded server
mysql-test/t/subselect.test:
  Updated test for embedded server
mysql-test/t/temp_table.test:
  Updated test for embedded server
mysql-test/t/view.test:
  Updated test for embedded server
mysql-test/t/view_grant.test:
  Updated test for embedded server
mysql-test/t/wait_timeout.test:
  Updated test for embedded server
mysys/mf_dirname.c:
  Review fix: Don't access data outside of array
mysys/my_bitmap.c:
  Remove compiler warnings
scripts/mysql_fix_privilege_tables.sql:
  Add flush privileges to .sql script so that one doesn't have to reboot mysqld when one runs the mysql_fix_privilege_script
sql-common/client.c:
  Updated test for embedded server
sql/item.cc:
  Remove DBUG_PRINT statement that can cause crashes when running with --debug
sql/mysqld.cc:
  Fix to embedded server to be able to run tests on it
sql/protocol.cc:
  Fix to embedded server to be able to run tests on it
  (Trivial reconstruction of code)
sql/protocol.h:
  Fix to embedded server to be able to run tests on it
sql/sql_base.cc:
  Better comment
sql/sql_class.cc:
  Fix to embedded server to be able to run tests on it
sql/sql_class.h:
  Fix to embedded server to be able to run tests on it
sql/sql_cursor.cc:
  Fix to embedded server to be able to run tests on it
sql/sql_parse.cc:
  Fix to embedded server to be able to run tests on it
  Don't crash for disabled commands when using embedded server
sql/sql_prepare.cc:
  Fix to embedded server to be able to run tests on it
mysql-test/r/ctype_cp932_notembedded.result:
  New BitKeeper file ``mysql-test/r/ctype_cp932_notembedded.result''
mysql-test/r/innodb_notembedded.result:
  New BitKeeper file ``mysql-test/r/innodb_notembedded.result''
mysql-test/r/sp.result.orig:
  New BitKeeper file ``mysql-test/r/sp.result.orig''
mysql-test/r/sp_notembedded.result:
  New BitKeeper file ``mysql-test/r/sp_notembedded.result''
mysql-test/r/subselect_notembedded.result:
  New BitKeeper file ``mysql-test/r/subselect_notembedded.result''
mysql-test/t/ctype_cp932_notembedded.test:
  New BitKeeper file ``mysql-test/t/ctype_cp932_notembedded.test''
mysql-test/t/innodb_notembedded.test:
  New BitKeeper file ``mysql-test/t/innodb_notembedded.test''
mysql-test/t/sp.test.orig:
  New BitKeeper file ``mysql-test/t/sp.test.orig''
mysql-test/t/sp_notembedded.test:
  New BitKeeper file ``mysql-test/t/sp_notembedded.test''
mysql-test/t/subselect_notembedded.test:
  New BitKeeper file ``mysql-test/t/subselect_notembedded.test''
This commit is contained in:
unknown 2006-02-24 18:34:15 +02:00
parent ef1316fadd
commit 0afb6ff660
66 changed files with 12108 additions and 698 deletions

View file

@ -130,14 +130,14 @@ typedef MYSQL_ROWS *MYSQL_ROW_OFFSET; /* offset to current row */
#include "my_alloc.h" #include "my_alloc.h"
typedef struct embedded_query_result EMBEDDED_QUERY_RESULT;
typedef struct st_mysql_data { typedef struct st_mysql_data {
my_ulonglong rows; my_ulonglong rows;
unsigned int fields; unsigned int fields;
MYSQL_ROWS *data; MYSQL_ROWS *data;
MEM_ROOT alloc; MEM_ROOT alloc;
#if !defined(CHECK_EMBEDDED_DIFFERENCES) || defined(EMBEDDED_LIBRARY) /* extra info for embedded library */
MYSQL_ROWS **prev_ptr; struct embedded_query_result *embedded_info;
#endif
} MYSQL_DATA; } MYSQL_DATA;
enum mysql_option 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. from mysql_stmt_close if close had to cancel result set of this object.
*/ */
my_bool *unbuffered_fetch_owner; my_bool *unbuffered_fetch_owner;
/* needed for embedded server - no net buffer to store the 'info' */
char *info_buffer;
} MYSQL; } MYSQL;
typedef struct st_mysql_res { typedef struct st_mysql_res {
@ -755,6 +757,7 @@ typedef struct st_mysql_methods
const char *(*read_statistics)(MYSQL *mysql); const char *(*read_statistics)(MYSQL *mysql);
my_bool (*next_result)(MYSQL *mysql); my_bool (*next_result)(MYSQL *mysql);
int (*read_change_user_result)(MYSQL *mysql, char *buff, const char *passwd); int (*read_change_user_result)(MYSQL *mysql, char *buff, const char *passwd);
int (*read_rows_from_cursor)(MYSQL_STMT *stmt);
#endif #endif
} MYSQL_METHODS; } MYSQL_METHODS;

View file

@ -2727,13 +2727,13 @@ stmt_read_row_from_cursor(MYSQL_STMT *stmt, unsigned char **row)
/* Send row request to the server */ /* Send row request to the server */
int4store(buff, stmt->stmt_id); int4store(buff, stmt->stmt_id);
int4store(buff + 4, stmt->prefetch_rows); /* number of rows to fetch */ int4store(buff + 4, stmt->prefetch_rows); /* number of rows to fetch */
if (cli_advanced_command(mysql, COM_STMT_FETCH, buff, sizeof(buff), if ((*mysql->methods->advanced_command)(mysql, COM_STMT_FETCH,
NullS, 0, 1)) buff, sizeof(buff), NullS, 0, 1))
{ {
set_stmt_errmsg(stmt, net->last_error, net->last_errno, net->sqlstate); set_stmt_errmsg(stmt, net->last_error, net->last_errno, net->sqlstate);
return 1; return 1;
} }
if (cli_read_binary_rows(stmt)) if ((*mysql->methods->read_rows_from_cursor)(stmt))
return 1; return 1;
stmt->server_status= mysql->server_status; stmt->server_status= mysql->server_status;
@ -5143,9 +5143,9 @@ my_bool STDCALL mysql_autocommit(MYSQL * mysql, my_bool auto_mode)
DBUG_ENTER("mysql_autocommit"); DBUG_ENTER("mysql_autocommit");
DBUG_PRINT("enter", ("mode : %d", auto_mode)); DBUG_PRINT("enter", ("mode : %d", auto_mode));
if (auto_mode) /* set to true */ DBUG_RETURN((my_bool) mysql_real_query(mysql, auto_mode ?
DBUG_RETURN((my_bool) mysql_real_query(mysql, "set autocommit=1", 16)); "set autocommit=1":"set autocommit=0",
DBUG_RETURN((my_bool) mysql_real_query(mysql, "set autocommit=0", 16)); 16));
} }

View file

@ -18,6 +18,7 @@
#ifdef HAVE_QUERY_CACHE #ifdef HAVE_QUERY_CACHE
#include <mysql.h> #include <mysql.h>
#include "emb_qcache.h" #include "emb_qcache.h"
#include "embedded_priv.h"
void Querycache_stream::store_char(char c) 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 emb_count_querycache_size(THD *thd)
{ {
uint result; uint result= 0;
MYSQL *mysql= thd->mysql; MYSQL_FIELD *field;
MYSQL_FIELD *field= mysql->fields; MYSQL_FIELD *field_end;
MYSQL_FIELD *field_end= field + mysql->field_count; MYSQL_ROWS *cur_row;
MYSQL_ROWS *cur_row=NULL; my_ulonglong n_rows;
my_ulonglong n_rows=0; 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) if (!field)
return 0; return result;
if (thd->data) *data->embedded_info->prev_ptr= NULL; // this marks the last record
{ cur_row= data->data;
*thd->data->prev_ptr= NULL; // this marks the last record n_rows= data->rows;
cur_row= thd->data->data; /* n_fields + n_rows + (field_info + strlen * n_rows) * n_fields */
n_rows= thd->data->rows; result+= (uint) (4+8 + (42 + 4*n_rows)*data->fields);
}
result= (uint) (4+8 + (42 + 4*n_rows)*mysql->field_count);
for(; field < field_end; field++) for(; field < field_end; field++)
{ {
@ -313,34 +317,38 @@ uint emb_count_querycache_size(THD *thd)
for (; cur_row; cur_row=cur_row->next) for (; cur_row; cur_row=cur_row->next)
{ {
MYSQL_ROW col= cur_row->data; 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++) for (; col < col_end; col++)
if (*col) if (*col)
result+= *(uint *)((*col) - sizeof(uint)); result+= *(uint *)((*col) - sizeof(uint));
} }
return result; return result;
} }
void emb_store_querycache_result(Querycache_stream *dst, THD *thd) void emb_store_querycache_result(Querycache_stream *dst, THD *thd)
{ {
MYSQL *mysql= thd->mysql; MYSQL_FIELD *field;
MYSQL_FIELD *field= mysql->fields; MYSQL_FIELD *field_end;
MYSQL_FIELD *field_end= field + mysql->field_count; MYSQL_ROWS *cur_row;
MYSQL_ROWS *cur_row= NULL; my_ulonglong n_rows;
my_ulonglong n_rows= 0; 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) if (!field)
return; DBUG_VOID_RETURN;
if (thd->data) *data->embedded_info->prev_ptr= NULL; // this marks the last record
{ cur_row= data->data;
*thd->data->prev_ptr= NULL; // this marks the last record n_rows= data->rows;
cur_row= thd->data->data;
n_rows= thd->data->rows;
}
dst->store_int((uint)mysql->field_count); dst->store_int((uint)data->fields);
dst->store_ll((uint)n_rows); dst->store_ll((ulonglong)n_rows);
for(; field < field_end; field++) 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->org_table, field->org_table_length);
dst->store_str(field->db, field->db_length); dst->store_str(field->db, field->db_length);
dst->store_str(field->catalog, field->catalog_length); dst->store_str(field->catalog, field->catalog_length);
dst->store_safe_str(field->def, field->def_length); dst->store_safe_str(field->def, field->def_length);
} }
for (; cur_row; cur_row=cur_row->next) for (; cur_row; cur_row=cur_row->next)
{ {
MYSQL_ROW col= cur_row->data; 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++) for (; col < col_end; col++)
{ {
uint len= *col ? *(uint *)((*col) - sizeof(uint)) : 0; 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_ASSERT(emb_count_querycache_size(thd) == dst->stored_size);
DBUG_VOID_RETURN;
} }
int emb_load_querycache_result(THD *thd, Querycache_stream *src) int emb_load_querycache_result(THD *thd, Querycache_stream *src)
{ {
MYSQL *mysql= thd->mysql; MYSQL_DATA *data= thd->alloc_new_dataset();
MYSQL_DATA *data;
MYSQL_FIELD *field; MYSQL_FIELD *field;
MYSQL_FIELD *field_end; MYSQL_FIELD *field_end;
MEM_ROOT *f_alloc= &mysql->field_alloc; MEM_ROOT *f_alloc;
MYSQL_ROWS *row, *end_row; MYSQL_ROWS *row, *end_row;
MYSQL_ROWS **prev_row; MYSQL_ROWS **prev_row;
ulonglong rows; ulonglong rows;
MYSQL_ROW columns; MYSQL_ROW columns;
DBUG_ENTER("emb_load_querycache_result");
mysql->field_count= src->load_int(); if (!data)
goto err;
init_alloc_root(&data->alloc, 8192,0);
f_alloc= &data->alloc;
data->fields= src->load_int();
rows= src->load_ll(); rows= src->load_ll();
if (!(field= (MYSQL_FIELD *) 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; goto err;
mysql->fields= field; data->embedded_info->fields_list= field;
for(field_end= field+mysql->field_count; field < field_end; field++) for(field_end= field+data->fields; field < field_end; field++)
{ {
field->length= src->load_int(); field->length= src->load_int();
field->max_length= (unsigned int)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(); field->decimals= (unsigned int)src->load_char();
if (!(field->name= src->load_str(f_alloc, &field->name_length)) || if (!(field->name= src->load_str(f_alloc, &field->name_length)) ||
!(field->table= src->load_str(f_alloc,&field->table_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_name= src->load_str(f_alloc, &field->org_name_length)) ||
!(field->org_table= src->load_str(f_alloc, &field->org_table_length))|| !(field->org_table= src->load_str(f_alloc, &field->org_table_length))||
!(field->db= src->load_str(f_alloc, &field->db_length)) || !(field->db= src->load_str(f_alloc, &field->db_length)) ||
!(field->catalog= src->load_str(f_alloc, &field->catalog_length)) || !(field->catalog= src->load_str(f_alloc, &field->catalog_length)) ||
src->load_safe_str(f_alloc, &field->def, &field->def_length)) src->load_safe_str(f_alloc, &field->def, &field->def_length))
goto err; goto err;
} }
if (!rows) row= (MYSQL_ROWS *)alloc_root(&data->alloc,
return 0; (uint) (rows * sizeof(MYSQL_ROWS) +
if (!(data= (MYSQL_DATA*)my_malloc(sizeof(MYSQL_DATA), rows*(data->fields+1)*sizeof(char*)));
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*)));
end_row= row + rows; end_row= row + rows;
columns= (MYSQL_ROW)end_row; columns= (MYSQL_ROW)end_row;
data->rows= rows; data->rows= rows;
data->fields= mysql->field_count;
data->data= row; data->data= row;
if (!rows)
goto return_ok;
for (prev_row= &row->next; row < end_row; prev_row= &row->next, row++) for (prev_row= &row->next; row < end_row; prev_row= &row->next, row++)
{ {
*prev_row= row; *prev_row= row;
row->data= columns; row->data= columns;
MYSQL_ROW col_end= columns + mysql->field_count; MYSQL_ROW col_end= columns + data->fields;
for (; columns < col_end; columns++) for (; columns < col_end; columns++)
src->load_column(&data->alloc, columns); src->load_column(&data->alloc, columns);
*(columns++)= NULL; *(columns++)= NULL;
} }
*prev_row= NULL; *prev_row= NULL;
data->prev_ptr= prev_row; data->embedded_info->prev_ptr= prev_row;
return_ok:
return 0; send_eof(thd);
DBUG_RETURN(0);
err: err:
return 1; DBUG_RETURN(1);
} }
#endif /*HAVE_QUERY_CACHE*/ #endif /*HAVE_QUERY_CACHE*/

View file

@ -16,18 +16,25 @@
/* Prototypes for the embedded version of MySQL */ /* 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 C_MODE_START
void lib_connection_phase(NET *net, int phase); void lib_connection_phase(NET *net, int phase);
void init_embedded_mysql(MYSQL *mysql, int client_flag, char *db); void init_embedded_mysql(MYSQL *mysql, int client_flag, char *db);
void *create_embedded_thd(int client_flag, char *db); void *create_embedded_thd(int client_flag, char *db);
int check_embedded_connection(MYSQL *mysql); int check_embedded_connection(MYSQL *mysql);
void free_old_query(MYSQL *mysql); void free_old_query(MYSQL *mysql);
void embedded_get_error(MYSQL *mysql);
extern MYSQL_METHODS embedded_methods; 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 C_MODE_END

View file

@ -42,21 +42,48 @@ C_MODE_START
#undef ER #undef ER
#include "errmsg.h" #include "errmsg.h"
#include <sql_common.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()
{
while (first_data)
{
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)
{ {
THD *thd=(THD *) mysql->thd;
NET *net= &mysql->net; NET *net= &mysql->net;
if ((net->last_errno= thd->net.last_errno)) struct embedded_query_result *ei= data->embedded_info;
{ net->last_errno= ei->last_errno;
memcpy(net->last_error, thd->net.last_error, sizeof(net->last_error)); strmake(net->last_error, ei->info, sizeof(net->last_error));
memcpy(net->sqlstate, thd->net.sqlstate, sizeof(net->sqlstate)); memcpy(net->sqlstate, ei->sqlstate, sizeof(net->sqlstate));
} my_free((gptr) data, MYF(0));
else
{
net->last_error[0]= 0;
strmov(net->sqlstate, not_error_sqlstate);
}
} }
static my_bool static my_bool
@ -68,11 +95,7 @@ emb_advanced_command(MYSQL *mysql, enum enum_server_command command,
THD *thd=(THD *) mysql->thd; THD *thd=(THD *) mysql->thd;
NET *net= &mysql->net; NET *net= &mysql->net;
if (thd->data) thd->clear_data_list();
{
free_rows(thd->data);
thd->data= 0;
}
/* Check that we are calling the client functions in right order */ /* Check that we are calling the client functions in right order */
if (mysql->status != MYSQL_STATUS_READY) if (mysql->status != MYSQL_STATUS_READY)
{ {
@ -104,83 +127,101 @@ emb_advanced_command(MYSQL *mysql, enum enum_server_command command,
arg_length= header_length; arg_length= header_length;
} }
thd->net.no_send_error= 0;
result= dispatch_command(command, thd, (char *) arg, arg_length + 1); result= dispatch_command(command, thd, (char *) arg, arg_length + 1);
thd->cur_data= 0;
if (!skip_check) if (!skip_check)
result= thd->net.last_errno ? -1 : 0; 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; return result;
} }
static void emb_flush_use_result(MYSQL *mysql) static void emb_flush_use_result(MYSQL *mysql)
{ {
MYSQL_DATA *data= ((THD*)(mysql->thd))->data; THD *thd= (THD*) mysql->thd;
if (thd->cur_data)
if (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); 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 * static MYSQL_DATA *
emb_read_rows(MYSQL *mysql, MYSQL_FIELD *mysql_fields __attribute__((unused)), emb_read_rows(MYSQL *mysql, MYSQL_FIELD *mysql_fields __attribute__((unused)),
unsigned int fields __attribute__((unused))) unsigned int fields __attribute__((unused)))
{ {
MYSQL_DATA *result= ((THD*)mysql->thd)->data; MYSQL_DATA *result= ((THD*)mysql->thd)->cur_data;
embedded_get_error(mysql); ((THD*)mysql->thd)->cur_data= 0;
if (mysql->net.last_errno) if (result->embedded_info->last_errno)
return NULL;
if (!result)
{ {
if (!(result=(MYSQL_DATA*) my_malloc(sizeof(MYSQL_DATA), embedded_get_error(mysql, result);
MYF(MY_WME | MY_ZEROFILL)))) return NULL;
{
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; *result->embedded_info->prev_ptr= NULL;
((THD*)mysql->thd)->data= NULL;
return result; return result;
} }
static MYSQL_FIELD *emb_list_fields(MYSQL *mysql) 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; return mysql->fields;
} }
static my_bool emb_read_prepare_result(MYSQL *mysql, MYSQL_STMT *stmt) static my_bool emb_read_prepare_result(MYSQL *mysql, MYSQL_STMT *stmt)
{ {
THD *thd= (THD*)mysql->thd; THD *thd= (THD*) mysql->thd;
if (mysql->net.last_errno) MYSQL_DATA *res;
return 1;
stmt->stmt_id= thd->client_stmt_id; stmt->stmt_id= thd->client_stmt_id;
stmt->param_count= thd->client_param_count; 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)) if (!(mysql->server_status & SERVER_STATUS_AUTOCOMMIT))
mysql->server_status|= SERVER_STATUS_IN_TRANS; mysql->server_status|= SERVER_STATUS_IN_TRANS;
stmt->fields= mysql->fields; stmt->fields= mysql->fields;
stmt->mem_root= mysql->field_alloc; stmt->mem_root= res->alloc;
mysql->fields= NULL; mysql->fields= NULL;
my_free((gptr) res,MYF(0));
} }
return 0; return 0;
@ -201,13 +242,42 @@ static void emb_fetch_lengths(ulong *to, MYSQL_ROW column,
*to= *column ? *(uint *)((*column) - sizeof(uint)) : 0; *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) THD *thd= (THD*) mysql->thd;
return -1; 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;
}
if (mysql->field_count) 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 (res->embedded_info->fields_list)
{
mysql->status=MYSQL_STATUS_GET_RESULT; mysql->status=MYSQL_STATUS_GET_RESULT;
thd->cur_data= res;
}
else
my_free((gptr) res, MYF(0));
return 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) static int emb_stmt_execute(MYSQL_STMT *stmt)
{ {
DBUG_ENTER("emb_stmt_execute"); DBUG_ENTER("emb_stmt_execute");
char header[4]; char header[5];
MYSQL_DATA *res;
THD *thd;
int4store(header, stmt->stmt_id); 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_param_count= stmt->param_count;
thd->client_params= stmt->params; thd->client_params= stmt->params;
if (emb_advanced_command(stmt->mysql, COM_STMT_EXECUTE,0,0, if (emb_advanced_command(stmt->mysql, COM_STMT_EXECUTE,0,0,
header, sizeof(header), 1) || header, sizeof(header), 1) ||
emb_mysql_read_query_result(stmt->mysql)) emb_read_query_result(stmt->mysql))
{ {
NET *net= &stmt->mysql->net; NET *net= &stmt->mysql->net;
set_stmt_errmsg(stmt, net->last_error, net->last_errno, net->sqlstate); 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->affected_rows= stmt->mysql->affected_rows;
stmt->insert_id= stmt->mysql->insert_id; stmt->insert_id= stmt->mysql->insert_id;
stmt->server_status= stmt->mysql->server_status;
DBUG_RETURN(0); DBUG_RETURN(0);
} }
@ -240,22 +316,53 @@ int emb_read_binary_rows(MYSQL_STMT *stmt)
return 1; return 1;
stmt->result= *data; stmt->result= *data;
my_free((char *) data, MYF(0)); 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; 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) int emb_unbuffered_fetch(MYSQL *mysql, char **row)
{ {
MYSQL_DATA *data= ((THD*)mysql->thd)->data; THD *thd= (THD*) mysql->thd;
embedded_get_error(mysql); MYSQL_DATA *data= thd->cur_data;
if (mysql->net.last_errno) if (data && data->embedded_info->last_errno)
return mysql->net.last_errno; {
embedded_get_error(mysql, data);
thd->cur_data= 0;
return 1;
}
if (!data || !data->data) if (!data || !data->data)
{ {
*row= NULL; *row= NULL;
if (data) if (data)
{ {
thd->cur_data= thd->first_data;
thd->first_data= data->embedded_info->next;
free_rows(data); free_rows(data);
((THD*)mysql->thd)->data= NULL;
} }
} }
else else
@ -269,9 +376,9 @@ int emb_unbuffered_fetch(MYSQL *mysql, char **row)
static void emb_free_embedded_thd(MYSQL *mysql) static void emb_free_embedded_thd(MYSQL *mysql)
{ {
THD *thd= (THD*)mysql->thd; THD *thd= (THD*)mysql->thd;
if (thd->data) thd->clear_data_list();
free_rows(thd->data);
thread_count--; thread_count--;
thd->store_globals();
delete thd; delete thd;
mysql->thd=0; 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); 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, int emb_read_change_user_result(MYSQL *mysql,
char *buff __attribute__((unused)), char *buff __attribute__((unused)),
@ -310,10 +405,10 @@ int emb_read_change_user_result(MYSQL *mysql,
MYSQL_METHODS embedded_methods= MYSQL_METHODS embedded_methods=
{ {
emb_mysql_read_query_result, emb_read_query_result,
emb_advanced_command, emb_advanced_command,
emb_read_rows, emb_read_rows,
emb_mysql_store_result, emb_store_result,
emb_fetch_lengths, emb_fetch_lengths,
emb_flush_use_result, emb_flush_use_result,
emb_list_fields, emb_list_fields,
@ -323,8 +418,9 @@ MYSQL_METHODS embedded_methods=
emb_unbuffered_fetch, emb_unbuffered_fetch,
emb_free_embedded_thd, emb_free_embedded_thd,
emb_read_statistics, emb_read_statistics,
emb_next_result, emb_read_query_result,
emb_read_change_user_result emb_read_change_user_result,
emb_read_rows_from_cursor
}; };
C_MODE_END C_MODE_END
@ -483,6 +579,7 @@ void init_embedded_mysql(MYSQL *mysql, int client_flag, char *db)
THD *thd = (THD *)mysql->thd; THD *thd = (THD *)mysql->thd;
thd->mysql= mysql; thd->mysql= mysql;
mysql->server_version= server_version; mysql->server_version= server_version;
init_alloc_root(&mysql->field_alloc, 8192, 0);
} }
void *create_embedded_thd(int client_flag, char *db) 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 * thd= new THD;
thd->thread_id= thread_id++; thd->thread_id= thread_id++;
thd->thread_stack= (char*) &thd;
if (thd->store_globals()) if (thd->store_globals())
{ {
fprintf(stderr,"store_globals failed.\n"); fprintf(stderr,"store_globals failed.\n");
@ -517,9 +615,10 @@ void *create_embedded_thd(int client_flag, char *db)
thd->security_ctx->db_access= DB_ACLS; thd->security_ctx->db_access= DB_ACLS;
thd->security_ctx->master_access= ~NO_ACCESS; thd->security_ctx->master_access= ~NO_ACCESS;
#endif #endif
thd->net.query_cache_query= 0; thd->cur_data= 0;
thd->first_data= 0;
thd->data= 0; thd->data_tail= &thd->first_data;
bzero((char*) &thd->net, sizeof(thd->net));
thread_count++; thread_count++;
return thd; return thd;
@ -531,11 +630,15 @@ err:
#ifdef NO_EMBEDDED_ACCESS_CHECKS #ifdef NO_EMBEDDED_ACCESS_CHECKS
int check_embedded_connection(MYSQL *mysql) int check_embedded_connection(MYSQL *mysql)
{ {
int result;
THD *thd= (THD*)mysql->thd; THD *thd= (THD*)mysql->thd;
Security_context *sctx= thd->security_ctx; 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)); 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 #else
@ -616,26 +719,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) bool Protocol::send_fields(List<Item> *list, uint flags)
{ {
List_iterator_fast<Item> it(*list); List_iterator_fast<Item> it(*list);
Item *item; Item *item;
MYSQL_FIELD *client_field; MYSQL_FIELD *client_field;
MYSQL *mysql= thd->mysql;
MEM_ROOT *field_alloc; MEM_ROOT *field_alloc;
CHARSET_INFO *thd_cs= thd->variables.character_set_results; CHARSET_INFO *thd_cs= thd->variables.character_set_results;
CHARSET_INFO *cs= system_charset_info; CHARSET_INFO *cs= system_charset_info;
MYSQL_DATA *data;
DBUG_ENTER("send_fields"); DBUG_ENTER("send_fields");
if (!mysql) // bootstrap file handling if (!thd->mysql) // bootstrap file handling
DBUG_RETURN(0); DBUG_RETURN(0);
field_count= list->elements; if (begin_dataset())
field_alloc= &mysql->field_alloc; goto err;
if (!(client_field= thd->mysql->fields=
(MYSQL_FIELD *)alloc_root(field_alloc, data= thd->cur_data;
sizeof(MYSQL_FIELD) * field_count))) 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; goto err;
while ((item= it++)) while ((item= it++))
@ -643,6 +867,10 @@ bool Protocol::send_fields(List<Item> *list, uint flags)
Send_field server_field; Send_field server_field;
item->make_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, client_field->db= dup_str_aux(field_alloc, server_field.db_name,
strlen(server_field.db_name), cs, thd_cs); strlen(server_field.db_name), cs, thd_cs);
client_field->table= dup_str_aux(field_alloc, server_field.table_name, client_field->table= dup_str_aux(field_alloc, server_field.table_name,
@ -703,7 +931,9 @@ bool Protocol::send_fields(List<Item> *list, uint flags)
client_field->max_length= 0; client_field->max_length= 0;
++client_field; ++client_field;
} }
thd->mysql->field_count= field_count;
if (flags & SEND_EOF)
write_eof_packet(thd);
DBUG_RETURN(prepare_for_send(list)); DBUG_RETURN(prepare_for_send(list));
err: err:
@ -723,25 +953,11 @@ bool Protocol::write()
bool Protocol_prep::write() bool Protocol_prep::write()
{ {
MYSQL_ROWS *cur; MYSQL_ROWS *cur;
MYSQL_DATA *data= thd->data; MYSQL_DATA *data= thd->cur_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;
}
data->rows++; 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)); my_error(ER_OUT_OF_RESOURCES,MYF(0));
return true; return true;
@ -750,8 +966,8 @@ bool Protocol_prep::write()
memcpy(cur->data, packet->ptr()+1, packet->length()-1); memcpy(cur->data, packet->ptr()+1, packet->length()-1);
cur->length= packet->length(); /* To allow us to do sanity checks */ cur->length= packet->length(); /* To allow us to do sanity checks */
*data->prev_ptr= cur; *data->embedded_info->prev_ptr= cur;
data->prev_ptr= &cur->next; data->embedded_info->prev_ptr= &cur->next;
cur->next= 0; cur->next= 0;
return false; return false;
@ -761,46 +977,52 @@ void
send_ok(THD *thd,ha_rows affected_rows,ulonglong id,const char *message) send_ok(THD *thd,ha_rows affected_rows,ulonglong id,const char *message)
{ {
DBUG_ENTER("send_ok"); DBUG_ENTER("send_ok");
MYSQL *mysql= current_thd->mysql; MYSQL_DATA *data;
MYSQL *mysql= thd->mysql;
if (!mysql) // bootstrap file handling if (!mysql) // bootstrap file handling
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
mysql->affected_rows= affected_rows; if (thd->net.no_send_ok) // hack for re-parsing queries
mysql->insert_id= id; 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) if (message)
{ strmake(data->embedded_info->info, message,
strmake(thd->net.last_error, message, sizeof(thd->net.last_error)-1); sizeof(data->embedded_info->info)-1);
mysql->info= thd->net.last_error;
} write_eof_packet(thd);
thd->cur_data= 0;
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
void void
send_eof(THD *thd) 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() void Protocol_simple::prepare_for_resend()
{ {
MYSQL_ROWS *cur; MYSQL_ROWS *cur;
MYSQL_DATA *data= thd->data; MYSQL_DATA *data= thd->cur_data;
DBUG_ENTER("send_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++; data->rows++;
if (!(cur= (MYSQL_ROWS *)alloc_root(alloc, sizeof(MYSQL_ROWS)+(field_count + 1) * sizeof(char *)))) if (!(cur= (MYSQL_ROWS *)alloc_root(alloc, sizeof(MYSQL_ROWS)+(field_count + 1) * sizeof(char *))))
{ {
@ -809,10 +1031,10 @@ void Protocol_simple::prepare_for_resend()
} }
cur->data= (MYSQL_ROW)(((char *)cur) + sizeof(MYSQL_ROWS)); cur->data= (MYSQL_ROW)(((char *)cur) + sizeof(MYSQL_ROWS));
*data->prev_ptr= cur; *data->embedded_info->prev_ptr= cur;
data->prev_ptr= &cur->next; data->embedded_info->prev_ptr= &cur->next;
next_field=cur->data; next_field=cur->data;
next_mysql_field= thd->mysql->fields; next_mysql_field= data->embedded_info->fields_list;
err: err:
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }

View file

@ -14,6 +14,11 @@
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ 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 "embedded_priv.h"
#include <my_sys.h> #include <my_sys.h>
#include <mysys_err.h> #include <mysys_err.h>
@ -193,7 +198,12 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
if (!user) if (!user)
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; port=0;
unix_socket=0; unix_socket=0;
@ -207,6 +217,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
if (db) if (db)
client_flag|=CLIENT_CONNECT_WITH_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); mysql->thd= create_embedded_thd(client_flag, db_name);
init_embedded_mysql(mysql, 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); DBUG_RETURN(mysql);
error: error:
embedded_get_error(mysql);
DBUG_PRINT("error",("message: %u (%s)", mysql->net.last_errno, DBUG_PRINT("error",("message: %u (%s)", mysql->net.last_errno,
mysql->net.last_error)); mysql->net.last_error));
{ {

View file

@ -318,6 +318,7 @@ while test $# -gt 0; do
USE_EMBEDDED_SERVER=1 USE_EMBEDDED_SERVER=1
USE_MANAGER=0 NO_SLAVE=1 USE_MANAGER=0 NO_SLAVE=1
USE_RUNNING_SERVER=0 USE_RUNNING_SERVER=0
USE_NDBCLUSTER=""
TEST_MODE="$TEST_MODE embedded" ;; TEST_MODE="$TEST_MODE embedded" ;;
--purify) --purify)
USE_PURIFY=1 USE_PURIFY=1

View file

@ -17,7 +17,7 @@ master-bin.000001 # Query 1 # use `test`; insert t1 values (5)
master-bin.000001 # Query 1 # use `test`; COMMIT master-bin.000001 # Query 1 # use `test`; COMMIT
master-bin.000001 # Query 1 # use `test`; BEGIN master-bin.000001 # Query 1 # use `test`; BEGIN
master-bin.000001 # Query 1 # use `test`; insert t2 values (5) master-bin.000001 # Query 1 # use `test`; insert t2 values (5)
master-bin.000001 # Xid 1 # COMMIT /* xid=11 */ master-bin.000001 # Xid 1 # COMMIT /* xid=12 */
drop table t1,t2; drop table t1,t2;
reset master; reset master;
create table t1 (n int) engine=innodb; create table t1 (n int) engine=innodb;
@ -128,7 +128,7 @@ master-bin.000001 # Query 1 # use `test`; insert into t1 values(4 + 4)
master-bin.000001 # Query 1 # use `test`; insert into t1 values(3 + 4) master-bin.000001 # Query 1 # use `test`; insert into t1 values(3 + 4)
master-bin.000001 # Query 1 # use `test`; insert into t1 values(2 + 4) master-bin.000001 # Query 1 # use `test`; insert into t1 values(2 + 4)
master-bin.000001 # Query 1 # use `test`; insert into t1 values(1 + 4) master-bin.000001 # Query 1 # use `test`; insert into t1 values(1 + 4)
master-bin.000001 # Xid 1 # COMMIT /* xid=18 */ master-bin.000001 # Xid 1 # COMMIT /* xid=19 */
master-bin.000001 # Rotate 1 # master-bin.000002;pos=4 master-bin.000001 # Rotate 1 # master-bin.000002;pos=4
show binlog events in 'master-bin.000002' from 98; show binlog events in 'master-bin.000002' from 98;
Log_name Pos Event_type Server_id End_log_pos Info Log_name Pos Event_type Server_id End_log_pos Info

View file

@ -11315,20 +11315,6 @@ DROP TABLE t1;
DROP TABLE t2; DROP TABLE t2;
DROP TABLE t3; DROP TABLE t3;
DROP TABLE t4; DROP TABLE t4;
RESET MASTER;
CREATE TABLE t1(f1 blob);
PREPARE stmt1 FROM 'INSERT INTO t1 VALUES(?)';
SET @var1= x'8300';
EXECUTE stmt1 USING @var1;
SHOW BINLOG EVENTS FROM 98;
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 98 Query 1 185 use `test`; CREATE TABLE t1(f1 blob)
master-bin.000001 185 User var 1 224 @`var1`=_binary 0x8300 COLLATE binary
master-bin.000001 224 Query 1 317 use `test`; INSERT INTO t1 VALUES(@'var1')
SELECT HEX(f1) FROM t1;
HEX(f1)
8300
DROP table t1;
SET collation_connection='cp932_japanese_ci'; SET collation_connection='cp932_japanese_ci';
create table t1 select repeat('a',4000) a; create table t1 select repeat('a',4000) a;
delete from t1; delete from t1;

View file

@ -0,0 +1,17 @@
drop table if exists t1;
set names cp932;
set character_set_database = cp932;
RESET MASTER;
CREATE TABLE t1(f1 blob);
PREPARE stmt1 FROM 'INSERT INTO t1 VALUES(?)';
SET @var1= x'8300';
EXECUTE stmt1 USING @var1;
SHOW BINLOG EVENTS FROM 98;
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 98 Query 1 185 use `test`; CREATE TABLE t1(f1 blob)
master-bin.000001 185 User var 1 224 @`var1`=_binary 0x8300 COLLATE binary
master-bin.000001 224 Query 1 317 use `test`; INSERT INTO t1 VALUES(@'var1')
SELECT HEX(f1) FROM t1;
HEX(f1)
8300
DROP table t1;

View file

@ -2673,25 +2673,6 @@ checksum table t1;
Table Checksum Table Checksum
test.t1 2050879373 test.t1 2050879373
drop table t1; drop table t1;
create table t1 (col1 integer primary key, col2 integer) engine=innodb;
insert t1 values (1,100);
create function f1 () returns integer begin
declare var1 int;
select col2 into var1 from t1 where col1=1 for update;
return var1;
end|
start transaction;
select f1();
f1()
100
update t1 set col2=0 where col1=1;
select * from t1;
col1 col2
1 100
rollback;
rollback;
drop table t1;
drop function f1;
create table t1 ( create table t1 (
a int, b char(10), c char(10), filler char(10), primary key(a, b(2)), unique key (a, c(2)) a int, b char(10), c char(10), filler char(10), primary key(a, b(2)), unique key (a, c(2))
) character set utf8 engine = innodb; ) character set utf8 engine = innodb;

View file

@ -0,0 +1,20 @@
drop table if exists t1;
create table t1 (col1 integer primary key, col2 integer) engine=innodb;
insert t1 values (1,100);
create function f1 () returns integer begin
declare var1 int;
select col2 into var1 from t1 where col1=1 for update;
return var1;
end|
start transaction;
select f1();
f1()
100
update t1 set col2=0 where col1=1;
select * from t1;
col1 col2
1 100
rollback;
rollback;
drop table t1;
drop function f1;

View file

@ -1,6 +1,6 @@
select -1 as "before_use_test" ; select 0 as "before_use_test" ;
before_use_test before_use_test
-1 0
select otto from (select 1 as otto) as t1; select otto from (select 1 as otto) as t1;
otto otto
1 1

View file

@ -1104,56 +1104,20 @@ call f1();
s1 s1
s1 s1
s1 s1
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 3
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 3
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 0
call f1(); call f1();
s1 s1
s1 s1
s1 s1
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 3
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 3
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 3
call f1(); call f1();
s1 s1
s1 s1
s1 s1
select sql_cache * from t1; select sql_cache * from t1;
s1 s1
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 4
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 4
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 6
insert into t1 values (1); insert into t1 values (1);
select sql_cache * from t1; select sql_cache * from t1;
s1 s1
1 1
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 5
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 6
call f1(); call f1();
s1 s1
1 1
@ -1171,15 +1135,6 @@ s1
select sql_cache * from t1; select sql_cache * from t1;
s1 s1
1 1
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 4
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 8
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 10
flush query cache; flush query cache;
reset query cache; reset query cache;
flush status; flush status;

View file

@ -94,4 +94,224 @@ a
SELECT * FROM t1; SELECT * FROM t1;
a a
drop table t1; drop table t1;
flush query cache;
reset query cache;
flush status;
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;//
call f1();
s1
s1
s1
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 3
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 3
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 0
call f1();
s1
s1
s1
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 3
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 3
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 3
call f1();
s1
s1
s1
select sql_cache * from t1;
s1
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 4
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 4
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 6
insert into t1 values (1);
select sql_cache * from t1;
s1
1
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 5
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 6
call f1();
s1
1
s1
1
s1
1
call f1();
s1
1
s1
1
s1
1
select sql_cache * from t1;
s1
1
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 4
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 8
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 10
flush query cache;
reset query cache;
flush status;
select sql_cache * from t1;
s1
1
select sql_cache * from t1 where s1=1;
s1
1
call f1();
s1
1
s1
1
s1
1
call f2();
s1
1
s1
1
call f3();
s1
1
s1
1
call f4();
s1
1
s1
1
s1
1
s1
1
s1
1
call f4();
s1
1
s1
1
s1
1
s1
1
s1
1
call f3();
s1
1
s1
1
call f2();
s1
1
s1
1
select sql_cache * from t1 where s1=1;
s1
1
insert into t1 values (2);
call f1();
s1
1
2
s1
1
2
s1
1
2
select sql_cache * from t1 where s1=1;
s1
1
select sql_cache * from t1;
s1
1
2
call f1();
s1
1
2
s1
1
2
s1
1
2
call f3();
s1
1
2
s1
1
call f3();
s1
1
2
s1
1
call f1();
s1
1
2
s1
1
2
s1
1
2
drop procedure f1;
drop procedure f2;
drop procedure f3;
drop procedure f4;
drop table t1;
set GLOBAL query_cache_size=0; set GLOBAL query_cache_size=0;

View file

@ -464,19 +464,6 @@ create table t5 (x int)|
call bug3294()| call bug3294()|
ERROR 42S02: Unknown table 't5' ERROR 42S02: Unknown table 't5'
drop procedure bug3294| drop procedure bug3294|
drop procedure if exists bug6807|
create procedure bug6807()
begin
declare id int;
set id = connection_id();
kill query id;
select 'Not reached';
end|
call bug6807()|
ERROR 70100: Query execution was interrupted
call bug6807()|
ERROR 70100: Query execution was interrupted
drop procedure bug6807|
drop procedure if exists bug8776_1| drop procedure if exists bug8776_1|
drop procedure if exists bug8776_2| drop procedure if exists bug8776_2|
drop procedure if exists bug8776_3| drop procedure if exists bug8776_3|

View file

@ -2463,7 +2463,6 @@ show create database test;
show databases like 'foo'; show databases like 'foo';
show errors; show errors;
show columns from t1; show columns from t1;
show grants for 'root'@'localhost';
show keys from t1; show keys from t1;
show open tables like 'foo'; show open tables like 'foo';
show privileges; show privileges;
@ -2490,8 +2489,6 @@ Level Code Message
Field Type Null Key Default Extra Field Type Null Key Default Extra
id char(16) NO id char(16) NO
data int(11) NO data int(11) NO
Grants for root@localhost
GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
Database Table In_use Name_locked Database Table In_use Name_locked
Privilege Context Comment Privilege Context Comment
@ -2544,8 +2541,6 @@ Level Code Message
Field Type Null Key Default Extra Field Type Null Key Default Extra
id char(16) NO id char(16) NO
data int(11) NO data int(11) NO
Grants for root@localhost
GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
Database Table In_use Name_locked Database Table In_use Name_locked
Privilege Context Comment Privilege Context Comment
@ -2581,18 +2576,6 @@ Tables_in_test (foo)
Variable_name Value Variable_name Value
Level Code Message Level Code Message
drop procedure bug4902| drop procedure bug4902|
drop procedure if exists bug4902_2|
create procedure bug4902_2()
begin
show processlist;
end|
call bug4902_2()|
Id User Host db Command Time State Info
# root localhost test Query # NULL show processlist
call bug4902_2()|
Id User Host db Command Time State Info
# root localhost test Query # NULL show processlist
drop procedure bug4902_2|
drop procedure if exists bug4904| drop procedure if exists bug4904|
create procedure bug4904() create procedure bug4904()
begin begin
@ -2735,52 +2718,6 @@ select @x|
NULL NULL
delete from t1| delete from t1|
drop procedure bug4941| drop procedure bug4941|
drop procedure if exists bug3583|
drop procedure if exists bug3583|
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'|
Variable_name Value
Qcache_hits 0
call bug3583()|
id data
x 3
y 5
c
2
show status like 'Qcache_hits'|
Variable_name Value
Qcache_hits 0
call bug3583()|
id data
x 3
y 5
c
2
call bug3583()|
id data
x 3
y 5
c
2
show status like 'Qcache_hits'|
Variable_name Value
Qcache_hits 2
set global query_cache_size = @x|
flush status|
flush query cache|
delete from t1|
drop procedure bug3583|
drop procedure if exists bug4905| drop procedure if exists bug4905|
create table t3 (s1 int,primary key (s1))| create table t3 (s1 int,primary key (s1))|
drop procedure if exists bug4905| drop procedure if exists bug4905|
@ -2996,17 +2933,6 @@ select id, bug5240() from t1|
id bug5240() id bug5240()
answer 42 answer 42
drop function bug5240| drop function bug5240|
drop function if exists bug5278|
create function bug5278 () returns char
begin
SET PASSWORD FOR 'bob'@'%.loc.gov' = PASSWORD('newpass');
return 'okay';
end|
select bug5278()|
ERROR 42000: Can't find any matching row in the user table
select bug5278()|
ERROR 42000: Can't find any matching row in the user table
drop function bug5278|
drop procedure if exists p1| drop procedure if exists p1|
create table t3(id int)| create table t3(id int)|
insert into t3 values(1)| insert into t3 values(1)|
@ -4352,14 +4278,6 @@ select bug10100f(5)|
ERROR HY000: Recursive stored functions and triggers are not allowed. ERROR HY000: Recursive stored functions and triggers are not allowed.
call bug10100t(5)| call bug10100t(5)|
ERROR HY000: Recursive limit 0 (as set by the max_sp_recursion_depth variable) was exceeded for routine bug10100p ERROR HY000: Recursive limit 0 (as set by the max_sp_recursion_depth variable) was exceeded for routine bug10100p
set @@max_sp_recursion_depth=255|
set @var=1|
call bug10100p(255, @var)|
call bug10100pt(1,255)|
call bug10100pv(1,255)|
call bug10100pd(1,255)|
call bug10100pc(1,255)|
set @@max_sp_recursion_depth=0|
deallocate prepare stmt2| deallocate prepare stmt2|
drop function bug10100f| drop function bug10100f|
drop procedure bug10100p| drop procedure bug10100p|

4853
mysql-test/r/sp.result.orig Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,206 @@
drop procedure if exists bug4902|
create procedure bug4902()
begin
show grants for 'root'@'localhost';
end|
call bug4902()|
Grants for root@localhost
GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION
call bug4902()|
Grants for root@localhost
GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION
drop procedure bug4902|
drop procedure if exists bug4902_2|
create procedure bug4902_2()
begin
show processlist;
end|
call bug4902_2()|
Id User Host db Command Time State Info
# root localhost test Query # NULL show processlist
call bug4902_2()|
Id User Host db Command Time State Info
# root localhost test Query # NULL show processlist
drop procedure bug4902_2|
drop function if exists bug5278|
create function bug5278 () returns char
begin
SET PASSWORD FOR 'bob'@'%.loc.gov' = PASSWORD('newpass');
return 'okay';
end|
select bug5278()|
ERROR 42000: Can't find any matching row in the user table
select bug5278()|
ERROR 42000: Can't find any matching row in the user table
drop function bug5278|
drop table if exists t1|
create table t1 (
id char(16) not null default '',
data int not null
)|
drop procedure if exists bug3583|
drop procedure if exists bug3583|
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'|
Variable_name Value
Qcache_hits 0
call bug3583()|
id data
x 3
y 5
c
2
show status like 'Qcache_hits'|
Variable_name Value
Qcache_hits 0
call bug3583()|
id data
x 3
y 5
c
2
call bug3583()|
id data
x 3
y 5
c
2
show status like 'Qcache_hits'|
Variable_name Value
Qcache_hits 2
set global query_cache_size = @x|
flush status|
flush query cache|
delete from t1|
drop procedure bug3583|
drop table t1;
#|
drop procedure if exists bug6807|
create procedure bug6807()
begin
declare id int;
set id = connection_id();
kill query id;
select 'Not reached';
end|
call bug6807()|
ERROR 70100: Query execution was interrupted
call bug6807()|
ERROR 70100: Query execution was interrupted
drop procedure bug6807|
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|
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|
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|
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|
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|
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|
set @@max_sp_recursion_depth=255|
set @var=1|
call bug10100p(255, @var)|
call bug10100pt(1,255)|
call bug10100pv(1,255)|
call bug10100pd(1,255)|
call bug10100pc(1,255)|
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|

View file

@ -2987,7 +2987,6 @@ select * from (select max(fld) from t1) as foo;
max(fld) max(fld)
1 1
drop table t1; drop table t1;
purge master logs before (select adddate(current_timestamp(), interval -4 day));
CREATE TABLE t1 (a int, b int); CREATE TABLE t1 (a int, b int);
CREATE TABLE t2 (c int, d int); CREATE TABLE t2 (c int, d int);
CREATE TABLE t3 (e int); CREATE TABLE t3 (e int);

View file

@ -0,0 +1 @@
purge master logs before (select adddate(current_timestamp(), interval -4 day));

View file

@ -2213,15 +2213,6 @@ r_object_id users_names
120001a080000542 guser02 120001a080000542 guser02
drop view v1, v2; drop view v1, v2;
drop table t1, t2; drop table t1, t2;
create definer=some_user@`` sql security invoker view v1 as select 1;
ERROR HY000: Definer is not fully qualified
create definer=some_user@localhost sql security invoker view v1 as select 1;
Warnings:
Note 1449 There is no 'some_user'@'localhost' registered
show create view v1;
View Create View
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`some_user`@`localhost` SQL SECURITY INVOKER VIEW `v1` AS select 1 AS `1`
drop view v1;
create table t1 (s1 int); create table t1 (s1 int);
create view abc as select * from t1 as abc; create view abc as select * from t1 as abc;
drop table t1; drop table t1;

View file

@ -519,3 +519,12 @@ use test;
use test; use test;
drop user mysqltest_1@localhost; drop user mysqltest_1@localhost;
drop database mysqltest; drop database mysqltest;
create definer=some_user@`` sql security invoker view v1 as select 1;
ERROR HY000: Definer is not fully qualified
create definer=some_user@localhost sql security invoker view v1 as select 1;
Warnings:
Note 1449 There is no 'some_user'@'localhost' registered
show create view v1;
View Create View
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`some_user`@`localhost` SQL SECURITY INVOKER VIEW `v1` AS select 1 AS `1`
drop view v1;

View file

@ -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 # This test is a bit tricky as we can't use backup table to overwrite an old
# table # table

View file

@ -1,6 +1,7 @@
# #
# misc binlogging tests that do not require a slave running # misc binlogging tests that do not require a slave running
# #
-- source include/not_embedded.inc
-- source include/have_bdb.inc -- source include/have_bdb.inc
-- source include/have_innodb.inc -- source include/have_innodb.inc
@ -18,7 +19,7 @@ begin;
insert t2 values (5); insert t2 values (5);
commit; commit;
# first COMMIT must be Query_log_event, second - Xid_log_event # first COMMIT must be Query_log_event, second - Xid_log_event
--replace_result "xid=18" "xid=11" --replace_result "xid=19" "xid=12"
--replace_column 2 # 5 # --replace_column 2 # 5 #
show binlog events from 98; show binlog events from 98;
drop table t1,t2; drop table t1,t2;
@ -40,7 +41,7 @@ while ($1)
--enable_query_log --enable_query_log
commit; commit;
drop table t1; drop table t1;
--replace_result "xid=29" "xid=18" --replace_result "xid=30" "xid=19"
--replace_column 2 # 5 # --replace_column 2 # 5 #
show binlog events in 'master-bin.000001' from 98; show binlog events in 'master-bin.000001' from 98;
--replace_column 2 # 5 # --replace_column 2 # 5 #

View file

@ -2,6 +2,7 @@
# Simple test for blackhole example # Simple test for blackhole example
# Taken from the select test # Taken from the select test
# #
-- source include/not_embedded.inc
-- source include/have_blackhole.inc -- source include/have_blackhole.inc
--disable_warnings --disable_warnings

View file

@ -1,6 +1,9 @@
# Turn on compression between the client and server # Turn on compression between the client and server
# and run a number of tests # and run a number of tests
# Can't test with embedded server
-- source include/not_embedded.inc
-- source include/have_compress.inc -- source include/have_compress.inc
connect (comp_con,localhost,root,,,,,COMPRESS); connect (comp_con,localhost,root,,,,,COMPRESS);

View file

@ -398,28 +398,6 @@ DROP TABLE t2;
DROP TABLE t3; DROP TABLE t3;
DROP TABLE t4; DROP TABLE t4;
# 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
SET collation_connection='cp932_japanese_ci'; SET collation_connection='cp932_japanese_ci';
-- source include/ctype_filesort.inc -- source include/ctype_filesort.inc
SET collation_connection='cp932_bin'; SET collation_connection='cp932_bin';

View file

@ -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

View file

@ -3,6 +3,9 @@
# (Can't be tested with purify :( ) # (Can't be tested with purify :( )
# #
# This tests not performed with embedded server
-- source include/not_embedded.inc
--disable_warnings --disable_warnings
drop table if exists t1; drop table if exists t1;
--enable_warnings --enable_warnings

View file

@ -2,6 +2,9 @@
# test of HANDLER ... # test of HANDLER ...
# #
# should work in embedded server after mysqltest is fixed
-- source include/not_embedded.inc
--disable_warnings --disable_warnings
drop table if exists t1,t3,t4,t5; drop table if exists t1,t3,t4,t5;
--enable_warnings --enable_warnings

View file

@ -1619,33 +1619,7 @@ connection a;
checksum table t1; checksum table t1;
drop 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; connection default;
select * from t1;
connection a;
rollback;
connection b;
reap;
rollback;
connection default;
drop table t1;
drop function f1;
disconnect a; disconnect a;
disconnect b; disconnect b;
@ -1788,6 +1762,7 @@ commit;
set foreign_key_checks=0; set foreign_key_checks=0;
create table t2 (a int primary key, b int, foreign key (b) references t1(a)) engine = innodb; create table t2 (a int primary key, b int, foreign key (b) references t1(a)) engine = innodb;
--replace_result $MYSQLTEST_VARDIR . master-data/ ''
-- error 1005 -- error 1005
create table t1(a char(10) primary key, b varchar(20)) engine = innodb; create table t1(a char(10) primary key, b varchar(20)) engine = innodb;
set foreign_key_checks=1; set foreign_key_checks=1;
@ -1798,6 +1773,7 @@ drop table t2;
set foreign_key_checks=0; set foreign_key_checks=0;
create table t1(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=latin1; create table t1(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=latin1;
--replace_result $MYSQLTEST_VARDIR . master-data/ ''
-- error 1005 -- error 1005
create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb DEFAULT CHARSET=utf8; create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb DEFAULT CHARSET=utf8;
set foreign_key_checks=1; set foreign_key_checks=1;
@ -1827,6 +1803,7 @@ drop table t2,t1;
set foreign_key_checks=0; set foreign_key_checks=0;
create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb DEFAULT CHARSET=latin1; create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb DEFAULT CHARSET=latin1;
create table t3(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=utf8; create table t3(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=utf8;
--replace_result $MYSQLTEST_VARDIR . master-data/ ''
-- error 1025 -- error 1025
rename table t3 to t1; rename table t3 to t1;
set foreign_key_checks=1; set foreign_key_checks=1;

View file

@ -0,0 +1,40 @@
-- source include/not_embedded.inc
-- source include/have_innodb.inc
--disable_warnings
drop table if exists t1;
--enable_warnings
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;

View file

@ -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) # Testing the MySQL command line client(mysql)
# #

View file

@ -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 # We run with different binaries for normal and --embedded-server
# #
# If this test fails with "command "$MYSQL_CLIENT_TEST" failed", # If this test fails with "command "$MYSQL_CLIENT_TEST" failed",

View file

@ -1,3 +1,5 @@
# This test should work in embedded server after mysqltest is fixed
-- source include/not_embedded.inc
# ============================================================================ # ============================================================================
# #

View file

@ -819,29 +819,14 @@ select sql_cache * from t1 where s1=1;
end;// end;//
delimiter ;// delimiter ;//
call f1(); call f1();
show status like "Qcache_queries_in_cache";
show status like "Qcache_inserts";
show status like "Qcache_hits";
call f1(); call f1();
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; 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); insert into t1 values (1);
select sql_cache * from t1; 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();
call f1(); call f1();
select sql_cache * from t1; 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; flush query cache;
reset query cache; reset query cache;
flush status; flush status;

View file

@ -97,4 +97,88 @@ connection root;
SELECT * FROM t1; SELECT * FROM t1;
drop table 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; set GLOBAL query_cache_size=0;

View file

@ -1,6 +1,9 @@
# Test of the READ_ONLY global variable: # Test of the READ_ONLY global variable:
# check that it blocks updates unless they are only on temporary tables. # 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 --disable_warnings
DROP TABLE IF EXISTS t1,t2,t3; DROP TABLE IF EXISTS t1,t2,t3;
--enable_warnings --enable_warnings

View file

@ -1,3 +1,6 @@
# This tests not performed with embedded server
-- source include/not_embedded.inc
--disable_warnings --disable_warnings
drop table if exists t1,v1; drop table if exists t1,v1;
drop view if exists t1,v1; drop view if exists t1,v1;

View file

@ -46,10 +46,13 @@ flush table mysql.proc;
# Thrashing the .frm file # Thrashing the .frm file
--system echo 'saljdlfa' > $MYSQLTEST_VARDIR/master-data/mysql/proc.frm --system echo 'saljdlfa' > $MYSQLTEST_VARDIR/master-data/mysql/proc.frm
--replace_result $MYSQLTEST_VARDIR . master-data// ''
--error ER_NOT_FORM_FILE --error ER_NOT_FORM_FILE
call bug14233(); call bug14233();
--replace_result $MYSQLTEST_VARDIR . master-data// ''
--error ER_NOT_FORM_FILE --error ER_NOT_FORM_FILE
create view v1 as select bug14233_f(); create view v1 as select bug14233_f();
--replace_result $MYSQLTEST_VARDIR . master-data// ''
--error ER_NOT_FORM_FILE --error ER_NOT_FORM_FILE
insert into t1 values (0); insert into t1 values (0);

View file

@ -647,28 +647,6 @@ create table t5 (x int)|
call bug3294()| call bug3294()|
drop procedure 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 # BUG#876: Stored Procedures: Invalid SQLSTATE is allowed in
# a DECLARE ? HANDLER FOR stmt. # a DECLARE ? HANDLER FOR stmt.

View file

@ -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, # Testing stored procedures with multiple connections,
# except security/privilege tests, they go to sp-security.test # except security/privilege tests, they go to sp-security.test

View file

@ -699,10 +699,11 @@ drop procedure into_test4|
--disable_warnings --disable_warnings
drop procedure if exists into_outfile| drop procedure if exists into_outfile|
--enable_warnings --enable_warnings
create procedure into_outfile(x char(16), y int) --replace_result $MYSQLTEST_VARDIR ..
eval create procedure into_outfile(x char(16), y int)
begin begin
insert into test.t1 values (x, y); insert into test.t1 values (x, y);
select * into outfile "../tmp/spout" from test.t1; select * into outfile "$MYSQLTEST_VARDIR/tmp/spout" from test.t1;
insert into test.t1 values (concat(x, "2"), y+2); insert into test.t1 values (concat(x, "2"), y+2);
end| end|
@ -715,10 +716,11 @@ drop procedure into_outfile|
--disable_warnings --disable_warnings
drop procedure if exists into_dumpfile| drop procedure if exists into_dumpfile|
--enable_warnings --enable_warnings
create procedure into_dumpfile(x char(16), y int) --replace_result $MYSQLTEST_VARDIR ..
eval create procedure into_dumpfile(x char(16), y int)
begin begin
insert into test.t1 values (x, y); insert into test.t1 values (x, y);
select * into dumpfile "../tmp/spdump" from test.t1 limit 1; select * into dumpfile "$MYSQLTEST_VARDIR/tmp/spdump" from test.t1 limit 1;
insert into test.t1 values (concat(x, "2"), y+2); insert into test.t1 values (concat(x, "2"), y+2);
end| end|
@ -1531,7 +1533,7 @@ begin
end while; end while;
end| end|
show create procedure opp| 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%'| show procedure status like '%p%'|
# This isn't the fastest way in the world to compute prime numbers, so # This isn't the fastest way in the world to compute prime numbers, so
@ -1549,7 +1551,7 @@ select * from t3 where i=45 or i=100 or i=199|
drop table t3| drop table t3|
drop procedure opp| drop procedure opp|
drop procedure ip| 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%'| show procedure status like '%p%'|
@ -1618,13 +1620,13 @@ drop procedure if exists bar|
create procedure bar(x char(16), y int) create procedure bar(x char(16), y int)
comment "111111111111" sql security invoker comment "111111111111" sql security invoker
insert into test.t1 values (x, y)| 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'| show procedure status like 'bar'|
alter procedure bar comment "2222222222" sql security definer| alter procedure bar comment "2222222222" sql security definer|
alter procedure bar comment "3333333333"| alter procedure bar comment "3333333333"|
alter procedure bar| alter procedure bar|
show create 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'| show procedure status like 'bar'|
drop procedure bar| drop procedure bar|
@ -2965,7 +2967,6 @@ begin
show databases like 'foo'; show databases like 'foo';
show errors; show errors;
show columns from t1; show columns from t1;
show grants for 'root'@'localhost';
show keys from t1; show keys from t1;
show open tables like 'foo'; show open tables like 'foo';
show privileges; show privileges;
@ -2987,20 +2988,6 @@ call bug4902()|
drop procedure 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 # BUG#4904
# #
@ -3215,44 +3202,6 @@ select @x|
delete from t1| delete from t1|
drop procedure bug4941| 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" # BUG#4905: Stored procedure doesn't clear for "Rows affected"
# #
@ -3561,24 +3510,6 @@ insert into t1 values ("answer", 42)|
select id, bug5240() from t1| select id, bug5240() from t1|
drop function bug5240| 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 # BUG#7992: rolling back temporary Item tree changes in SP
# #
@ -5176,24 +5107,6 @@ select bug10100f(5)|
call bug10100t(5)| call bug10100t(5)|
#end of the stack checking #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| deallocate prepare stmt2|
drop function bug10100f| drop function bug10100f|

5716
mysql-test/t/sp.test.orig Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,262 @@
# 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 ;|

View file

@ -1962,12 +1962,6 @@ insert into t1 values ('1');
select * from (select max(fld) from t1) as foo; select * from (select max(fld) from t1) as foo;
drop table t1; drop table t1;
#
# BUG #10308: purge log with subselect
#
purge master logs before (select adddate(current_timestamp(), interval -4 day));
# #
# Test for bug #11762: subquery with an aggregate function in HAVING # Test for bug #11762: subquery with an aggregate function in HAVING
# #

View file

@ -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));

View file

@ -1,3 +1,5 @@
# mysqltest should be fixed
-- source include/not_embedded.inc
# #
# Test of temporary tables # Test of temporary tables
# #

View file

@ -2075,16 +2075,6 @@ order by users_names;
drop view v1, v2; drop view v1, v2;
drop table t1, t2; drop table t1, t2;
#
# DEFINER information check
#
-- error ER_MALFORMED_DEFINER
create definer=some_user@`` sql security invoker view v1 as select 1;
create definer=some_user@localhost sql security invoker view v1 as select 1;
show create view v1;
drop view v1;
#
# Bug #6808 - Views: CREATE VIEW v ... FROM t AS v fails # Bug #6808 - Views: CREATE VIEW v ... FROM t AS v fails
# #

View file

@ -702,3 +702,14 @@ drop database mysqltest;
disconnect user1; disconnect user1;
disconnect root; disconnect root;
connection default; connection default;
#
# DEFINER information check
#
-- error ER_MALFORMED_DEFINER
create definer=some_user@`` sql security invoker view v1 as select 1;
create definer=some_user@localhost sql security invoker view v1 as select 1;
show create view v1;
drop view v1;

View file

@ -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 # Bug #8731: wait_timeout does not work on Mac OS X
# #

View file

@ -108,7 +108,7 @@ char *convert_dirname(char *to, const char *from, const char *from_end)
#if FN_LIBCHAR != '/' || defined(FN_C_BEFORE_DIR_2) #if FN_LIBCHAR != '/' || defined(FN_C_BEFORE_DIR_2)
{ {
for (; *from && from != from_end; from++) for (; from != from_end && *from ; from++)
{ {
if (*from == '/') if (*from == '/')
*to++= FN_LIBCHAR; *to++= FN_LIBCHAR;

View file

@ -40,7 +40,7 @@
#include <my_bitmap.h> #include <my_bitmap.h>
#include <m_string.h> #include <m_string.h>
static inline void bitmap_lock(MY_BITMAP *map) static inline void bitmap_lock(MY_BITMAP *map __attribute__((unused)))
{ {
#ifdef THREAD #ifdef THREAD
if (map->mutex) if (map->mutex)
@ -48,7 +48,7 @@ static inline void bitmap_lock(MY_BITMAP *map)
#endif #endif
} }
static inline void bitmap_unlock(MY_BITMAP *map) static inline void bitmap_unlock(MY_BITMAP *map __attribute__((unused)))
{ {
#ifdef THREAD #ifdef THREAD
if (map->mutex) if (map->mutex)

View file

@ -521,3 +521,9 @@ ALTER TABLE proc MODIFY db
char(77) collate utf8_bin DEFAULT '' NOT NULL, char(77) collate utf8_bin DEFAULT '' NOT NULL,
MODIFY comment MODIFY comment
char(64) collate utf8_bin DEFAULT '' NOT NULL; char(64) collate utf8_bin DEFAULT '' NOT NULL;
# Activate the new, possible modified privilege tables
# This should not be needed, but gives us some extra testing that the above
# changes was correct
flush privileges;

View file

@ -1563,7 +1563,8 @@ static MYSQL_METHODS client_methods=
NULL, NULL,
cli_read_statistics, cli_read_statistics,
cli_read_query_result, cli_read_query_result,
cli_read_change_user_result cli_read_change_user_result,
cli_read_binary_rows
#endif #endif
}; };
@ -2340,8 +2341,9 @@ static void mysql_close_free(MYSQL *mysql)
my_free(mysql->user,MYF(MY_ALLOW_ZERO_PTR)); my_free(mysql->user,MYF(MY_ALLOW_ZERO_PTR));
my_free(mysql->passwd,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->db,MYF(MY_ALLOW_ZERO_PTR));
my_free(mysql->info_buffer,MYF(MY_ALLOW_ZERO_PTR));
/* Clear pointers for better safety */ /* 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;
} }
@ -2477,8 +2479,7 @@ get_info:
if (!(mysql->server_status & SERVER_STATUS_AUTOCOMMIT)) if (!(mysql->server_status & SERVER_STATUS_AUTOCOMMIT))
mysql->server_status|= SERVER_STATUS_IN_TRANS; mysql->server_status|= SERVER_STATUS_IN_TRANS;
if (!(fields=(*mysql->methods->read_rows)(mysql,(MYSQL_FIELD*)0, if (!(fields=cli_read_rows(mysql,(MYSQL_FIELD*)0, protocol_41(mysql) ? 7:5)))
protocol_41(mysql) ? 7 : 5)))
DBUG_RETURN(1); DBUG_RETURN(1);
if (!(mysql->fields=unpack_fields(fields,&mysql->field_alloc, if (!(mysql->fields=unpack_fields(fields,&mysql->field_alloc,
(uint) field_count,0, (uint) field_count,0,

View file

@ -375,9 +375,6 @@ void Item::print_item_w_name(String *str)
void Item::cleanup() void Item::cleanup()
{ {
DBUG_ENTER("Item::cleanup"); DBUG_ENTER("Item::cleanup");
DBUG_PRINT("info", ("Item: 0x%lx, Type: %d, name %s, original name %s",
this, (int)type(), name ? name : "(null)",
orig_name ? orig_name : "null"));
fixed=0; fixed=0;
marker= 0; marker= 0;
if (orig_name) if (orig_name)

View file

@ -2387,9 +2387,7 @@ static int my_message_sql(uint error, const char *str, myf MyFlags)
{ {
NET *net= &thd->net; NET *net= &thd->net;
net->report_error= 1; net->report_error= 1;
#ifndef EMBEDDED_LIBRARY /* TODO query cache in embedded library*/
query_cache_abort(net); query_cache_abort(net);
#endif
if (!net->last_error[0]) // Return only first message if (!net->last_error[0]) // Return only first message
{ {
strmake(net->last_error, str, sizeof(net->last_error)-1); strmake(net->last_error, str, sizeof(net->last_error)-1);

View file

@ -29,6 +29,7 @@
static const unsigned int PACKET_BUFFER_EXTRA_ALLOC= 1024; static const unsigned int PACKET_BUFFER_EXTRA_ALLOC= 1024;
static void write_eof_packet(THD *thd, NET *net); 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 #ifndef EMBEDDED_LIBRARY
bool Protocol::net_store_data(const char *from, uint length) 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) 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; NET *net= &thd->net;
bool generate_warning= thd->killed != THD::KILL_CONNECTION; bool generate_warning= thd->killed != THD::KILL_CONNECTION;
DBUG_ENTER("net_send_error"); 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); push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, sql_errno, err);
} }
#ifdef EMBEDDED_LIBRARY net_send_error_packet(thd, sql_errno, err);
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;
}
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->is_fatal_error=0; // Error message is given
thd->net.report_error= 0; 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); 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 */ #endif /* EMBEDDED_LIBRARY */
/* /*

View file

@ -91,6 +91,12 @@ public:
virtual bool store_date(TIME *time)=0; virtual bool store_date(TIME *time)=0;
virtual bool store_time(TIME *time)=0; virtual bool store_time(TIME *time)=0;
virtual bool store(Field *field)=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(float nr, uint32 decimals, String *buffer);
virtual bool store(double from, uint32 decimals, String *buffer); virtual bool store(double from, uint32 decimals, String *buffer);
virtual bool store(Field *field); virtual bool store(Field *field);
#ifdef EMBEDDED_LIBRARY
void remove_last_row();
#endif
}; };

View file

@ -368,6 +368,15 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh,
DESCRIPTION DESCRIPTION
Marks all tables in the list which were used by current substatement Marks all tables in the list which were used by current substatement
(they are marked by its query_id) as free for reuse. (they are marked by its query_id) as free for reuse.
NOTE
The reason we reset query_id is that it's not enough to just test
if table->query_id != thd->query_id to know if a table is in use.
For example
SELECT f1_that_uses_t1() FROM t1;
In f1_that_uses_t1() we will see one instance of t1 where query_id is
set to query_id of original query.
*/ */
static void mark_used_tables_as_free_for_reuse(THD *thd, TABLE *table) static void mark_used_tables_as_free_for_reuse(THD *thd, TABLE *table)

View file

@ -950,6 +950,7 @@ bool select_send::send_data(List<Item> &items)
DBUG_RETURN(0); DBUG_RETURN(0);
if (!thd->net.report_error) if (!thd->net.report_error)
DBUG_RETURN(protocol->write()); DBUG_RETURN(protocol->write());
protocol->remove_last_row();
DBUG_RETURN(1); DBUG_RETURN(1);
} }
@ -1981,10 +1982,8 @@ void THD::reset_sub_statement_state(Sub_statement_state *backup,
cuted_fields= 0; cuted_fields= 0;
transaction.savepoints= 0; transaction.savepoints= 0;
#ifndef EMBEDDED_LIBRARY
/* Surpress OK packets in case if we will execute statements */ /* Surpress OK packets in case if we will execute statements */
net.no_send_ok= TRUE; net.no_send_ok= TRUE;
#endif
} }

View file

@ -1102,13 +1102,16 @@ public:
#ifdef EMBEDDED_LIBRARY #ifdef EMBEDDED_LIBRARY
struct st_mysql *mysql; struct st_mysql *mysql;
struct st_mysql_data *data;
unsigned long client_stmt_id; unsigned long client_stmt_id;
unsigned long client_param_count; unsigned long client_param_count;
struct st_mysql_bind *client_params; struct st_mysql_bind *client_params;
char *extra_data; char *extra_data;
ulong extra_length; 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 #endif
NET net; // client connection descriptor NET net; // client connection descriptor
MEM_ROOT warn_root; // For warnings and errors MEM_ROOT warn_root; // For warnings and errors
@ -1659,6 +1662,11 @@ public:
*/ */
virtual void cleanup(); virtual void cleanup();
void set_thd(THD *thd_arg) { thd= thd_arg; } void set_thd(THD *thd_arg) { thd= thd_arg; }
#ifdef EMBEDDED_LIBRARY
virtual void begin_dataset() {}
#else
void begin_dataset() {}
#endif
}; };

View file

@ -603,6 +603,7 @@ void Materialized_cursor::fetch(ulong num_rows)
THD *thd= table->in_use; THD *thd= table->in_use;
int res= 0; int res= 0;
result->begin_dataset();
for (fetch_limit+= num_rows; fetch_count < fetch_limit; fetch_count++) for (fetch_limit+= num_rows; fetch_count < fetch_limit; fetch_count++)
{ {
if ((res= table->file->rnd_next(table->record[0]))) if ((res= table->file->rnd_next(table->record[0])))

View file

@ -1724,13 +1724,10 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
net->no_send_error= 0; net->no_send_error= 0;
/* /*
Multiple queries exits, execute them individually 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 || if (thd->lock || thd->open_tables || thd->derived_tables ||
thd->prelocked_mode) thd->prelocked_mode)
close_thread_tables(thd); close_thread_tables(thd);
#endif
ulong length= (ulong)(packet_end-packet); ulong length= (ulong)(packet_end-packet);
log_slow_statement(thd); log_slow_statement(thd);
@ -1748,25 +1745,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
thd->set_time(); /* Reset the query start time. */ thd->set_time(); /* Reset the query start time. */
/* TODO: set thd->lex->sql_command to SQLCOM_END here */ /* TODO: set thd->lex->sql_command to SQLCOM_END here */
VOID(pthread_mutex_unlock(&LOCK_thread_count)); VOID(pthread_mutex_unlock(&LOCK_thread_count));
#ifndef EMBEDDED_LIBRARY
mysql_parse(thd, packet, length); 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)) if (!(specialflag & SPECIAL_NO_PRIOR))
@ -4273,10 +4252,8 @@ end_with_restore_list:
goto error; goto error;
} }
#ifndef EMBEDDED_LIBRARY
my_bool nsok= thd->net.no_send_ok; my_bool nsok= thd->net.no_send_ok;
thd->net.no_send_ok= TRUE; thd->net.no_send_ok= TRUE;
#endif
if (sp->m_flags & sp_head::MULTI_RESULTS) if (sp->m_flags & sp_head::MULTI_RESULTS)
{ {
if (! (thd->client_capabilities & CLIENT_MULTI_RESULTS)) if (! (thd->client_capabilities & CLIENT_MULTI_RESULTS))
@ -4286,9 +4263,7 @@ end_with_restore_list:
back back
*/ */
my_error(ER_SP_BADSELECT, MYF(0), sp->m_qname.str); my_error(ER_SP_BADSELECT, MYF(0), sp->m_qname.str);
#ifndef EMBEDDED_LIBRARY
thd->net.no_send_ok= nsok; thd->net.no_send_ok= nsok;
#endif
goto error; goto error;
} }
/* /*
@ -4305,18 +4280,14 @@ end_with_restore_list:
sp->m_db.str, sp->m_name.str, TRUE, 0) || sp->m_db.str, sp->m_name.str, TRUE, 0) ||
sp_change_security_context(thd, sp, &save_ctx)) sp_change_security_context(thd, sp, &save_ctx))
{ {
#ifndef EMBEDDED_LIBRARY
thd->net.no_send_ok= nsok; thd->net.no_send_ok= nsok;
#endif
goto error; goto error;
} }
if (save_ctx && if (save_ctx &&
check_routine_access(thd, EXECUTE_ACL, check_routine_access(thd, EXECUTE_ACL,
sp->m_db.str, sp->m_name.str, TRUE, 0)) sp->m_db.str, sp->m_name.str, TRUE, 0))
{ {
#ifndef EMBEDDED_LIBRARY
thd->net.no_send_ok= nsok; thd->net.no_send_ok= nsok;
#endif
sp_restore_security_context(thd, save_ctx); sp_restore_security_context(thd, save_ctx);
goto error; goto error;
} }
@ -4348,9 +4319,7 @@ end_with_restore_list:
sp_restore_security_context(thd, save_ctx); sp_restore_security_context(thd, save_ctx);
#endif #endif
#ifndef EMBEDDED_LIBRARY
thd->net.no_send_ok= nsok; thd->net.no_send_ok= nsok;
#endif
thd->server_status&= ~bits_to_be_cleared; thd->server_status&= ~bits_to_be_cleared;
if (!res) if (!res)
@ -4846,7 +4815,9 @@ end_with_restore_list:
res= mysql_xa_recover(thd); res= mysql_xa_recover(thd);
break; break;
default: default:
#ifndef EMBEDDED_LIBRARY
DBUG_ASSERT(0); /* Impossible */ DBUG_ASSERT(0); /* Impossible */
#endif
send_ok(thd); send_ok(thd);
break; break;
} }

View file

@ -92,6 +92,12 @@ public:
virtual bool send_fields(List<Item> &list, uint flags); virtual bool send_fields(List<Item> &list, uint flags);
virtual bool send_data(List<Item> &items); virtual bool send_data(List<Item> &items);
virtual bool send_eof(); 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) 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); MAX_DATETIME_WIDTH * MY_CHARSET_BIN_MB_MAXLEN);
} }