summaryrefslogtreecommitdiff
path: root/libmysqld/lib_sql.cc
diff options
context:
space:
mode:
authorunknown <monty@mysql.com>2006-02-24 18:34:15 +0200
committerunknown <monty@mysql.com>2006-02-24 18:34:15 +0200
commit0afb6ff66082f64c7c0aea62662e4c03e7c987c5 (patch)
tree603ae9081a58d9f7bb204327f65d4a8af4425b28 /libmysqld/lib_sql.cc
parentef1316fadda7b7d8c1b00de6d82576ebc21607cc (diff)
downloadmariadb-git-0afb6ff66082f64c7c0aea62662e4c03e7c987c5.tar.gz
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''
Diffstat (limited to 'libmysqld/lib_sql.cc')
-rw-r--r--libmysqld/lib_sql.cc512
1 files changed, 367 insertions, 145 deletions
diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc
index 8552b1c2b8a..e4c9d8cb4e9 100644
--- a/libmysqld/lib_sql.cc
+++ b/libmysqld/lib_sql.cc
@@ -42,21 +42,48 @@ C_MODE_START
#undef ER
#include "errmsg.h"
#include <sql_common.h>
+#include "embedded_priv.h"
-void embedded_get_error(MYSQL *mysql)
+static my_bool emb_read_query_result(MYSQL *mysql);
+
+void THD::clear_data_list()
{
- THD *thd=(THD *) mysql->thd;
- NET *net= &mysql->net;
- if ((net->last_errno= thd->net.last_errno))
- {
- memcpy(net->last_error, thd->net.last_error, sizeof(net->last_error));
- memcpy(net->sqlstate, thd->net.sqlstate, sizeof(net->sqlstate));
- }
- else
+ while (first_data)
{
- net->last_error[0]= 0;
- strmov(net->sqlstate, not_error_sqlstate);
+ MYSQL_DATA *data= first_data;
+ first_data= data->embedded_info->next;
+ free_rows(data);
}
+ data_tail= &first_data;
+ free_rows(cur_data);
+ cur_data= 0;
+}
+
+
+/*
+ Reads error information from the MYSQL_DATA and puts
+ it into proper MYSQL members
+
+ SYNOPSIS
+ embedded_get_error()
+ mysql connection handler
+ data query result
+
+ NOTES
+ after that function error information will be accessible
+ with usual functions like mysql_error()
+ data is my_free-d in this function
+ most of the data is stored in data->embedded_info structure
+*/
+
+void embedded_get_error(MYSQL *mysql, MYSQL_DATA *data)
+{
+ NET *net= &mysql->net;
+ struct embedded_query_result *ei= data->embedded_info;
+ net->last_errno= ei->last_errno;
+ strmake(net->last_error, ei->info, sizeof(net->last_error));
+ memcpy(net->sqlstate, ei->sqlstate, sizeof(net->sqlstate));
+ my_free((gptr) data, MYF(0));
}
static my_bool
@@ -68,11 +95,7 @@ emb_advanced_command(MYSQL *mysql, enum enum_server_command command,
THD *thd=(THD *) mysql->thd;
NET *net= &mysql->net;
- if (thd->data)
- {
- free_rows(thd->data);
- thd->data= 0;
- }
+ thd->clear_data_list();
/* Check that we are calling the client functions in right order */
if (mysql->status != MYSQL_STATUS_READY)
{
@@ -104,83 +127,101 @@ emb_advanced_command(MYSQL *mysql, enum enum_server_command command,
arg_length= header_length;
}
+ thd->net.no_send_error= 0;
result= dispatch_command(command, thd, (char *) arg, arg_length + 1);
+ thd->cur_data= 0;
if (!skip_check)
result= thd->net.last_errno ? -1 : 0;
- /*
- If mysql->field_count is set it means the parsing of the query was OK
- and metadata was returned (see Protocol::send_fields).
- In this case we postpone the error to be returned in mysql_stmt_store_result
- (see emb_read_rows) to behave just as standalone server.
- */
- if (!mysql->field_count)
- embedded_get_error(mysql);
- mysql->server_status= thd->server_status;
- mysql->warning_count= ((THD*)mysql->thd)->total_warn_count;
return result;
}
static void emb_flush_use_result(MYSQL *mysql)
{
- MYSQL_DATA *data= ((THD*)(mysql->thd))->data;
-
- if (data)
+ THD *thd= (THD*) mysql->thd;
+ if (thd->cur_data)
{
+ free_rows(thd->cur_data);
+ thd->cur_data= 0;
+ }
+ else if (thd->first_data)
+ {
+ MYSQL_DATA *data= thd->first_data;
+ thd->first_data= data->embedded_info->next;
free_rows(data);
- ((THD*)(mysql->thd))->data= NULL;
}
}
+
+/*
+ reads dataset from the next query result
+
+ SYNOPSIS
+ emb_read_rows()
+ mysql connection handle
+ other parameters are not used
+
+ NOTES
+ It just gets next MYSQL_DATA from the result's queue
+
+ RETURN
+ pointer to MYSQL_DATA with the coming recordset
+*/
+
static MYSQL_DATA *
emb_read_rows(MYSQL *mysql, MYSQL_FIELD *mysql_fields __attribute__((unused)),
unsigned int fields __attribute__((unused)))
{
- MYSQL_DATA *result= ((THD*)mysql->thd)->data;
- embedded_get_error(mysql);
- if (mysql->net.last_errno)
- return NULL;
- if (!result)
+ MYSQL_DATA *result= ((THD*)mysql->thd)->cur_data;
+ ((THD*)mysql->thd)->cur_data= 0;
+ if (result->embedded_info->last_errno)
{
- if (!(result=(MYSQL_DATA*) my_malloc(sizeof(MYSQL_DATA),
- MYF(MY_WME | MY_ZEROFILL))))
- {
- NET *net = &mysql->net;
- net->last_errno=CR_OUT_OF_MEMORY;
- strmov(net->sqlstate, unknown_sqlstate);
- strmov(net->last_error,ER(net->last_errno));
- return NULL;
- }
- return result;
- }
- *result->prev_ptr= NULL;
- ((THD*)mysql->thd)->data= NULL;
+ embedded_get_error(mysql, result);
+ return NULL;
+ }
+ *result->embedded_info->prev_ptr= NULL;
return result;
}
+
static MYSQL_FIELD *emb_list_fields(MYSQL *mysql)
{
+ MYSQL_DATA *res;
+ if (emb_read_query_result(mysql))
+ return 0;
+ res= ((THD*) mysql->thd)->cur_data;
+ ((THD*) mysql->thd)->cur_data= 0;
+ mysql->field_alloc= res->alloc;
+ my_free((gptr) res,MYF(0));
+ mysql->status= MYSQL_STATUS_READY;
return mysql->fields;
}
static my_bool emb_read_prepare_result(MYSQL *mysql, MYSQL_STMT *stmt)
{
- THD *thd= (THD*)mysql->thd;
- if (mysql->net.last_errno)
- return 1;
+ THD *thd= (THD*) mysql->thd;
+ MYSQL_DATA *res;
+
stmt->stmt_id= thd->client_stmt_id;
stmt->param_count= thd->client_param_count;
- stmt->field_count= mysql->field_count;
+ stmt->field_count= 0;
- if (stmt->field_count != 0)
+ if (thd->first_data)
{
+ if (emb_read_query_result(mysql))
+ return 1;
+ stmt->field_count= mysql->field_count;
+ mysql->status= MYSQL_STATUS_READY;
+ res= thd->cur_data;
+ thd->cur_data= NULL;
if (!(mysql->server_status & SERVER_STATUS_AUTOCOMMIT))
mysql->server_status|= SERVER_STATUS_IN_TRANS;
stmt->fields= mysql->fields;
- stmt->mem_root= mysql->field_alloc;
+ stmt->mem_root= res->alloc;
mysql->fields= NULL;
+ my_free((gptr) res,MYF(0));
}
return 0;
@@ -201,13 +242,42 @@ static void emb_fetch_lengths(ulong *to, MYSQL_ROW column,
*to= *column ? *(uint *)((*column) - sizeof(uint)) : 0;
}
-static my_bool emb_mysql_read_query_result(MYSQL *mysql)
+static my_bool emb_read_query_result(MYSQL *mysql)
{
- if (mysql->net.last_errno)
- return -1;
+ THD *thd= (THD*) mysql->thd;
+ MYSQL_DATA *res= thd->first_data;
+ DBUG_ASSERT(!thd->cur_data);
+ thd->first_data= res->embedded_info->next;
+ if (res->embedded_info->last_errno &&
+ !res->embedded_info->fields_list)
+ {
+ embedded_get_error(mysql, res);
+ return 1;
+ }
+
+ mysql->warning_count= res->embedded_info->warning_count;
+ mysql->server_status= res->embedded_info->server_status;
+ mysql->field_count= res->fields;
+ mysql->fields= res->embedded_info->fields_list;
+ mysql->affected_rows= res->embedded_info->affected_rows;
+ mysql->insert_id= res->embedded_info->insert_id;
+ mysql->net.last_errno= 0;
+ mysql->net.last_error[0]= 0;
+ mysql->info= 0;
+
+ if (res->embedded_info->info[0])
+ {
+ strmake(mysql->info_buffer, res->embedded_info->info, MYSQL_ERRMSG_SIZE-1);
+ mysql->info= mysql->info_buffer;
+ }
- if (mysql->field_count)
+ if (res->embedded_info->fields_list)
+ {
mysql->status=MYSQL_STATUS_GET_RESULT;
+ thd->cur_data= res;
+ }
+ else
+ my_free((gptr) res, MYF(0));
return 0;
}
@@ -215,14 +285,18 @@ static my_bool emb_mysql_read_query_result(MYSQL *mysql)
static int emb_stmt_execute(MYSQL_STMT *stmt)
{
DBUG_ENTER("emb_stmt_execute");
- char header[4];
+ char header[5];
+ MYSQL_DATA *res;
+ THD *thd;
+
int4store(header, stmt->stmt_id);
- THD *thd= (THD*)stmt->mysql->thd;
+ header[4]= stmt->flags;
+ thd= (THD*)stmt->mysql->thd;
thd->client_param_count= stmt->param_count;
thd->client_params= stmt->params;
if (emb_advanced_command(stmt->mysql, COM_STMT_EXECUTE,0,0,
header, sizeof(header), 1) ||
- emb_mysql_read_query_result(stmt->mysql))
+ emb_read_query_result(stmt->mysql))
{
NET *net= &stmt->mysql->net;
set_stmt_errmsg(stmt, net->last_error, net->last_errno, net->sqlstate);
@@ -230,6 +304,8 @@ static int emb_stmt_execute(MYSQL_STMT *stmt)
}
stmt->affected_rows= stmt->mysql->affected_rows;
stmt->insert_id= stmt->mysql->insert_id;
+ stmt->server_status= stmt->mysql->server_status;
+
DBUG_RETURN(0);
}
@@ -240,22 +316,53 @@ int emb_read_binary_rows(MYSQL_STMT *stmt)
return 1;
stmt->result= *data;
my_free((char *) data, MYF(0));
+ set_stmt_errmsg(stmt, stmt->mysql->net.last_error,
+ stmt->mysql->net.last_errno, stmt->mysql->net.sqlstate);
return 0;
}
+int emb_read_rows_from_cursor(MYSQL_STMT *stmt)
+{
+ MYSQL *mysql= stmt->mysql;
+ THD *thd= (THD*) mysql->thd;
+ MYSQL_DATA *res= thd->first_data;
+ DBUG_ASSERT(!thd->first_data->embedded_info->next);
+ thd->first_data= 0;
+ if (res->embedded_info->last_errno)
+ {
+ embedded_get_error(mysql, res);
+ set_stmt_errmsg(stmt, mysql->net.last_error,
+ mysql->net.last_errno, mysql->net.sqlstate);
+ return 1;
+ }
+
+ thd->cur_data= res;
+ mysql->warning_count= res->embedded_info->warning_count;
+ mysql->server_status= res->embedded_info->server_status;
+ mysql->net.last_errno= 0;
+ mysql->net.last_error[0]= 0;
+
+ return emb_read_binary_rows(stmt);
+}
+
int emb_unbuffered_fetch(MYSQL *mysql, char **row)
{
- MYSQL_DATA *data= ((THD*)mysql->thd)->data;
- embedded_get_error(mysql);
- if (mysql->net.last_errno)
- return mysql->net.last_errno;
+ THD *thd= (THD*) mysql->thd;
+ MYSQL_DATA *data= thd->cur_data;
+ if (data && data->embedded_info->last_errno)
+ {
+ embedded_get_error(mysql, data);
+ thd->cur_data= 0;
+ return 1;
+ }
if (!data || !data->data)
{
*row= NULL;
if (data)
{
+ thd->cur_data= thd->first_data;
+ thd->first_data= data->embedded_info->next;
free_rows(data);
- ((THD*)mysql->thd)->data= NULL;
}
}
else
@@ -269,9 +376,9 @@ int emb_unbuffered_fetch(MYSQL *mysql, char **row)
static void emb_free_embedded_thd(MYSQL *mysql)
{
THD *thd= (THD*)mysql->thd;
- if (thd->data)
- free_rows(thd->data);
+ thd->clear_data_list();
thread_count--;
+ thd->store_globals();
delete thd;
mysql->thd=0;
}
@@ -283,23 +390,11 @@ static const char * emb_read_statistics(MYSQL *mysql)
}
-static MYSQL_RES * emb_mysql_store_result(MYSQL *mysql)
+static MYSQL_RES * emb_store_result(MYSQL *mysql)
{
return mysql_store_result(mysql);
}
-my_bool emb_next_result(MYSQL *mysql)
-{
- THD *thd= (THD*)mysql->thd;
- DBUG_ENTER("emb_next_result");
-
- if (emb_advanced_command(mysql, COM_QUERY,0,0,
- thd->query_rest.ptr(),thd->query_rest.length(),1) ||
- emb_mysql_read_query_result(mysql))
- DBUG_RETURN(1);
-
- DBUG_RETURN(0); /* No more results */
-}
int emb_read_change_user_result(MYSQL *mysql,
char *buff __attribute__((unused)),
@@ -310,10 +405,10 @@ int emb_read_change_user_result(MYSQL *mysql,
MYSQL_METHODS embedded_methods=
{
- emb_mysql_read_query_result,
+ emb_read_query_result,
emb_advanced_command,
emb_read_rows,
- emb_mysql_store_result,
+ emb_store_result,
emb_fetch_lengths,
emb_flush_use_result,
emb_list_fields,
@@ -323,8 +418,9 @@ MYSQL_METHODS embedded_methods=
emb_unbuffered_fetch,
emb_free_embedded_thd,
emb_read_statistics,
- emb_next_result,
- emb_read_change_user_result
+ emb_read_query_result,
+ emb_read_change_user_result,
+ emb_read_rows_from_cursor
};
C_MODE_END
@@ -483,6 +579,7 @@ void init_embedded_mysql(MYSQL *mysql, int client_flag, char *db)
THD *thd = (THD *)mysql->thd;
thd->mysql= mysql;
mysql->server_version= server_version;
+ init_alloc_root(&mysql->field_alloc, 8192, 0);
}
void *create_embedded_thd(int client_flag, char *db)
@@ -490,6 +587,7 @@ void *create_embedded_thd(int client_flag, char *db)
THD * thd= new THD;
thd->thread_id= thread_id++;
+ thd->thread_stack= (char*) &thd;
if (thd->store_globals())
{
fprintf(stderr,"store_globals failed.\n");
@@ -517,9 +615,10 @@ void *create_embedded_thd(int client_flag, char *db)
thd->security_ctx->db_access= DB_ACLS;
thd->security_ctx->master_access= ~NO_ACCESS;
#endif
- thd->net.query_cache_query= 0;
-
- thd->data= 0;
+ thd->cur_data= 0;
+ thd->first_data= 0;
+ thd->data_tail= &thd->first_data;
+ bzero((char*) &thd->net, sizeof(thd->net));
thread_count++;
return thd;
@@ -531,11 +630,15 @@ err:
#ifdef NO_EMBEDDED_ACCESS_CHECKS
int check_embedded_connection(MYSQL *mysql)
{
+ int result;
THD *thd= (THD*)mysql->thd;
Security_context *sctx= thd->security_ctx;
- sctx->host_or_ip= sctx->host= (char*)my_localhost;
+ sctx->host_or_ip= sctx->host= (char*) my_localhost;
+ strmake(sctx->priv_host, (char*) my_localhost, MAX_HOSTNAME-1);
sctx->priv_user= sctx->user= my_strdup(mysql->user, MYF(0));
- return check_user(thd, COM_CONNECT, NULL, 0, thd->db, true);
+ result= check_user(thd, COM_CONNECT, NULL, 0, thd->db, true);
+ emb_read_query_result(mysql);
+ return result;
}
#else
@@ -616,26 +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)
{
List_iterator_fast<Item> it(*list);
Item *item;
MYSQL_FIELD *client_field;
- MYSQL *mysql= thd->mysql;
MEM_ROOT *field_alloc;
CHARSET_INFO *thd_cs= thd->variables.character_set_results;
CHARSET_INFO *cs= system_charset_info;
-
+ MYSQL_DATA *data;
DBUG_ENTER("send_fields");
- if (!mysql) // bootstrap file handling
+ if (!thd->mysql) // bootstrap file handling
DBUG_RETURN(0);
- field_count= list->elements;
- field_alloc= &mysql->field_alloc;
- if (!(client_field= thd->mysql->fields=
- (MYSQL_FIELD *)alloc_root(field_alloc,
- sizeof(MYSQL_FIELD) * field_count)))
+ if (begin_dataset())
+ goto err;
+
+ data= thd->cur_data;
+ data->fields= field_count= list->elements;
+ field_alloc= &data->alloc;
+
+ if (!(client_field= data->embedded_info->fields_list=
+ (MYSQL_FIELD*)alloc_root(field_alloc, sizeof(MYSQL_FIELD)*field_count)))
goto err;
while ((item= it++))
@@ -643,6 +867,10 @@ bool Protocol::send_fields(List<Item> *list, uint flags)
Send_field server_field;
item->make_field(&server_field);
+ /* Keep things compatible for old clients */
+ if (server_field.type == MYSQL_TYPE_VARCHAR)
+ server_field.type= MYSQL_TYPE_VAR_STRING;
+
client_field->db= dup_str_aux(field_alloc, server_field.db_name,
strlen(server_field.db_name), cs, thd_cs);
client_field->table= dup_str_aux(field_alloc, server_field.table_name,
@@ -703,7 +931,9 @@ bool Protocol::send_fields(List<Item> *list, uint flags)
client_field->max_length= 0;
++client_field;
}
- thd->mysql->field_count= field_count;
+
+ if (flags & SEND_EOF)
+ write_eof_packet(thd);
DBUG_RETURN(prepare_for_send(list));
err:
@@ -723,25 +953,11 @@ bool Protocol::write()
bool Protocol_prep::write()
{
MYSQL_ROWS *cur;
- MYSQL_DATA *data= thd->data;
-
- if (!data)
- {
- if (!(data= (MYSQL_DATA*) my_malloc(sizeof(MYSQL_DATA),
- MYF(MY_WME | MY_ZEROFILL))))
- return true;
-
- alloc= &data->alloc;
- init_alloc_root(alloc,8192,0); /* Assume rowlength < 8192 */
- alloc->min_malloc=sizeof(MYSQL_ROWS);
- data->rows=0;
- data->fields=field_count;
- data->prev_ptr= &data->data;
- thd->data= data;
- }
+ MYSQL_DATA *data= thd->cur_data;
data->rows++;
- if (!(cur= (MYSQL_ROWS *)alloc_root(alloc, sizeof(MYSQL_ROWS)+packet->length())))
+ if (!(cur= (MYSQL_ROWS *)alloc_root(alloc,
+ sizeof(MYSQL_ROWS)+packet->length())))
{
my_error(ER_OUT_OF_RESOURCES,MYF(0));
return true;
@@ -750,8 +966,8 @@ bool Protocol_prep::write()
memcpy(cur->data, packet->ptr()+1, packet->length()-1);
cur->length= packet->length(); /* To allow us to do sanity checks */
- *data->prev_ptr= cur;
- data->prev_ptr= &cur->next;
+ *data->embedded_info->prev_ptr= cur;
+ data->embedded_info->prev_ptr= &cur->next;
cur->next= 0;
return false;
@@ -761,46 +977,52 @@ void
send_ok(THD *thd,ha_rows affected_rows,ulonglong id,const char *message)
{
DBUG_ENTER("send_ok");
- MYSQL *mysql= current_thd->mysql;
+ MYSQL_DATA *data;
+ MYSQL *mysql= thd->mysql;
+
if (!mysql) // bootstrap file handling
DBUG_VOID_RETURN;
- mysql->affected_rows= affected_rows;
- mysql->insert_id= id;
+ if (thd->net.no_send_ok) // hack for re-parsing queries
+ DBUG_VOID_RETURN;
+ if (!(data= thd->alloc_new_dataset()))
+ return;
+ data->embedded_info->affected_rows= affected_rows;
+ data->embedded_info->insert_id= id;
if (message)
- {
- strmake(thd->net.last_error, message, sizeof(thd->net.last_error)-1);
- mysql->info= thd->net.last_error;
- }
+ strmake(data->embedded_info->info, message,
+ sizeof(data->embedded_info->info)-1);
+
+ write_eof_packet(thd);
+ thd->cur_data= 0;
DBUG_VOID_RETURN;
}
void
send_eof(THD *thd)
{
+ write_eof_packet(thd);
+ thd->cur_data= 0;
}
+
+void net_send_error_packet(THD *thd, uint sql_errno, const char *err)
+{
+ MYSQL_DATA *data= thd->cur_data ? thd->cur_data : thd->alloc_new_dataset();
+ struct embedded_query_result *ei= data->embedded_info;
+
+ ei->last_errno= sql_errno;
+ strmake(ei->info, err, sizeof(ei->info)-1);
+ strmov(ei->sqlstate, mysql_errno_to_sqlstate(sql_errno));
+ thd->cur_data= 0;
+}
+
+
void Protocol_simple::prepare_for_resend()
{
MYSQL_ROWS *cur;
- MYSQL_DATA *data= thd->data;
-
+ MYSQL_DATA *data= thd->cur_data;
DBUG_ENTER("send_data");
- if (!data)
- {
- if (!(data= (MYSQL_DATA*) my_malloc(sizeof(MYSQL_DATA),
- MYF(MY_WME | MY_ZEROFILL))))
- goto err;
-
- alloc= &data->alloc;
- init_alloc_root(alloc,8192,0); /* Assume rowlength < 8192 */
- alloc->min_malloc=sizeof(MYSQL_ROWS);
- data->rows=0;
- data->fields=field_count;
- data->prev_ptr= &data->data;
- thd->data= data;
- }
-
data->rows++;
if (!(cur= (MYSQL_ROWS *)alloc_root(alloc, sizeof(MYSQL_ROWS)+(field_count + 1) * sizeof(char *))))
{
@@ -809,10 +1031,10 @@ void Protocol_simple::prepare_for_resend()
}
cur->data= (MYSQL_ROW)(((char *)cur) + sizeof(MYSQL_ROWS));
- *data->prev_ptr= cur;
- data->prev_ptr= &cur->next;
+ *data->embedded_info->prev_ptr= cur;
+ data->embedded_info->prev_ptr= &cur->next;
next_field=cur->data;
- next_mysql_field= thd->mysql->fields;
+ next_mysql_field= data->embedded_info->fields_list;
err:
DBUG_VOID_RETURN;
}