summaryrefslogtreecommitdiff
path: root/sql/protocol.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/protocol.cc')
-rw-r--r--sql/protocol.cc207
1 files changed, 93 insertions, 114 deletions
diff --git a/sql/protocol.cc b/sql/protocol.cc
index 6a17ae2f95b..57922cdc677 100644
--- a/sql/protocol.cc
+++ b/sql/protocol.cc
@@ -24,6 +24,7 @@
#endif
#include "mysql_priv.h"
+#include "sp_rcontext.h"
#include <stdarg.h>
static const unsigned int PACKET_BUFFER_EXTRA_ALLOC= 1024;
@@ -52,22 +53,30 @@ bool Protocol_prep::net_store_data(const char *from, uint length)
/* Send a error string to client */
-void 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
- const char *orig_err= err;
NET *net= &thd->net;
- DBUG_ENTER("send_error");
+ bool generate_warning= thd->killed != THD::KILL_CONNECTION;
+ DBUG_ENTER("net_send_error");
DBUG_PRINT("enter",("sql_errno: %d err: %s", sql_errno,
err ? err : net->last_error[0] ?
net->last_error : "NULL"));
-#ifndef EMBEDDED_LIBRARY /* TODO query cache in embedded library*/
- query_cache_abort(net);
-#endif
+ if (net && net->no_send_error)
+ {
+ thd->clear_error();
+ DBUG_PRINT("info", ("sending error messages prohibited"));
+ DBUG_VOID_RETURN;
+ }
+ if (thd->spcont && thd->spcont->find_handler(sql_errno,
+ MYSQL_ERROR::WARN_LEVEL_ERROR))
+ {
+ DBUG_VOID_RETURN;
+ }
thd->query_error= 1; // needed to catch query errors during replication
if (!err)
{
@@ -76,14 +85,22 @@ void send_error(THD *thd, uint sql_errno, const char *err)
else
{
if ((err=net->last_error)[0])
+ {
sql_errno=net->last_errno;
+ generate_warning= 0; // This warning has already been given
+ }
else
{
sql_errno=ER_UNKNOWN_ERROR;
err=ER(sql_errno); /* purecov: inspected */
}
}
- orig_err= err;
+ }
+
+ if (generate_warning)
+ {
+ /* Error that we have not got with my_error() */
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, sql_errno, err);
}
#ifdef EMBEDDED_LIBRARY
@@ -122,43 +139,14 @@ void send_error(THD *thd, uint sql_errno, const char *err)
}
VOID(net_write_command(net,(uchar) 255, "", 0, (char*) err,length));
#endif /* EMBEDDED_LIBRARY*/
- if (!thd->killed)
- push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, sql_errno,
- orig_err ? orig_err : ER(sql_errno));
thd->is_fatal_error=0; // Error message is given
thd->net.report_error= 0;
/* Abort multi-result sets */
- thd->lex->found_colon= 0;
thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
DBUG_VOID_RETURN;
}
-
-/*
- Send a warning to the end user
-
- SYNOPSIS
- send_warning()
- thd Thread handler
- sql_errno Warning number (error message)
- err Error string. If not set, use ER(sql_errno)
-
- DESCRIPTION
- Register the warning so that the user can get it with mysql_warnings()
- Send an ok (+ warning count) to the end user.
-*/
-
-void send_warning(THD *thd, uint sql_errno, const char *err)
-{
- DBUG_ENTER("send_warning");
- push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, sql_errno,
- err ? err : ER(sql_errno));
- send_ok(thd);
- DBUG_VOID_RETURN;
-}
-
-
/*
Write error package and flush to client
It's a little too low level, but I don't want to use another buffer for
@@ -166,7 +154,7 @@ void send_warning(THD *thd, uint sql_errno, const char *err)
*/
void
-net_printf(THD *thd, uint errcode, ...)
+net_printf_error(THD *thd, uint errcode, ...)
{
va_list args;
uint length,offset;
@@ -179,17 +167,29 @@ net_printf(THD *thd, uint errcode, ...)
#endif
NET *net= &thd->net;
- DBUG_ENTER("net_printf");
+ DBUG_ENTER("net_printf_error");
DBUG_PRINT("enter",("message: %u",errcode));
+ if (net && net->no_send_error)
+ {
+ thd->clear_error();
+ DBUG_PRINT("info", ("sending error messages prohibited"));
+ DBUG_VOID_RETURN;
+ }
+
+ if (thd->spcont && thd->spcont->find_handler(errcode,
+ MYSQL_ERROR::WARN_LEVEL_ERROR))
+ {
+ DBUG_VOID_RETURN;
+ }
thd->query_error= 1; // needed to catch query errors during replication
#ifndef EMBEDDED_LIBRARY
query_cache_abort(net); // Safety
#endif
va_start(args,errcode);
/*
- The following is needed to make net_printf() work with 0 argument for
- errorcode and use the argument after that as the format string. This
+ The following is needed to make net_printf_error() work with 0 argument
+ for errorcode and use the argument after that as the format string. This
is useful for rare errors that are not worth the hassle to put in
errmsg.sys, but at the same time, the message is not fixed text
*/
@@ -252,7 +252,7 @@ net_printf(THD *thd, uint errcode, ...)
strmake(net->last_error, text_pos, length);
strmake(net->sqlstate, mysql_errno_to_sqlstate(errcode), SQLSTATE_LENGTH);
#endif
- if (!thd->killed)
+ if (thd->killed != THD::KILL_CONNECTION)
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, errcode,
text_pos ? text_pos : ER(errcode));
thd->is_fatal_error=0; // Error message is given
@@ -326,6 +326,9 @@ send_ok(THD *thd, ha_rows affected_rows, ulonglong id, const char *message)
VOID(net_flush(net));
/* We can't anymore send an error to the client */
thd->net.report_error= 0;
+ thd->net.no_send_error= 1;
+ DBUG_PRINT("info", ("OK sent, so no more error sending allowed"));
+
DBUG_VOID_RETURN;
}
@@ -358,12 +361,14 @@ send_eof(THD *thd, bool no_flush)
{
NET *net= &thd->net;
DBUG_ENTER("send_eof");
- if (net->vio != 0)
+ if (net->vio != 0 && !net->no_send_eof)
{
if (thd->client_capabilities & CLIENT_PROTOCOL_41)
{
uchar buff[5];
- uint tmp= min(thd->total_warn_count, 65535);
+ /* Don't send warn count during SP execution, as the warn_list
+ is cleared between substatements, and mysqltest gets confused */
+ uint tmp= (thd->spcont ? 0 : min(thd->total_warn_count, 65535));
buff[0]=254;
int2store(buff+1, tmp);
/*
@@ -383,6 +388,8 @@ send_eof(THD *thd, bool no_flush)
if (!no_flush)
VOID(net_flush(net));
}
+ thd->net.no_send_error= 1;
+ DBUG_PRINT("info", ("EOF sent, so no more error sending allowed"));
}
DBUG_VOID_RETURN;
}
@@ -497,6 +504,7 @@ bool Protocol::flush()
flag Bit mask with the following functions:
1 send number of rows
2 send default values
+ 4 don't write eof packet
DESCRIPTION
Sum fields has table name empty and field_name.
@@ -507,7 +515,7 @@ bool Protocol::flush()
*/
#ifndef EMBEDDED_LIBRARY
-bool Protocol::send_fields(List<Item> *list, uint flag)
+bool Protocol::send_fields(List<Item> *list, uint flags)
{
List_iterator_fast<Item> it(*list);
Item *item;
@@ -518,7 +526,7 @@ bool Protocol::send_fields(List<Item> *list, uint flag)
CHARSET_INFO *thd_charset= thd->variables.character_set_results;
DBUG_ENTER("send_fields");
- if (flag & 1)
+ if (flags & SEND_NUM_ROWS)
{ // Packet with number of elements
char *pos=net_store_length(buff, (uint) list->elements);
(void) my_net_write(&thd->net, buff,(uint) (pos-buff));
@@ -536,6 +544,11 @@ bool Protocol::send_fields(List<Item> *list, uint flag)
CHARSET_INFO *cs= system_charset_info;
Send_field field;
item->make_field(&field);
+
+ /* Keep things compatible for old clients */
+ if (field.type == MYSQL_TYPE_VARCHAR)
+ field.type= MYSQL_TYPE_VAR_STRING;
+
prot.prepare_for_resend();
if (thd->client_capabilities & CLIENT_PROTOCOL_41)
@@ -612,7 +625,7 @@ bool Protocol::send_fields(List<Item> *list, uint flag)
}
}
local_packet->length((uint) (pos - local_packet->ptr()));
- if (flag & 2)
+ if (flags & SEND_DEFAULTS)
item->send(&prot, &tmp); // Send default value
if (prot.write())
break; /* purecov: inspected */
@@ -621,25 +634,17 @@ bool Protocol::send_fields(List<Item> *list, uint flag)
#endif
}
- my_net_write(&thd->net, eof_buff, 1);
+ if (flags & SEND_EOF)
+ my_net_write(&thd->net, eof_buff, 1);
DBUG_RETURN(prepare_for_send(list));
err:
- send_error(thd,ER_OUT_OF_RESOURCES); /* purecov: inspected */
+ my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES),
+ MYF(0)); /* purecov: inspected */
DBUG_RETURN(1); /* purecov: inspected */
}
-bool Protocol::send_records_num(List<Item> *list, ulonglong records)
-{
- char *pos;
- char buff[20];
- pos=net_store_length(buff, (uint) list->elements);
- pos=net_store_length(pos, records);
- return my_net_write(&thd->net, buff,(uint) (pos-buff));
-}
-
-
bool Protocol::write()
{
DBUG_ENTER("Protocol::write");
@@ -752,6 +757,8 @@ bool Protocol_simple::store(const char *from, uint length,
#ifndef DEBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_DECIMAL ||
+ field_types[field_pos] == MYSQL_TYPE_BIT ||
+ field_types[field_pos] == MYSQL_TYPE_NEWDECIMAL ||
(field_types[field_pos] >= MYSQL_TYPE_ENUM &&
field_types[field_pos] <= MYSQL_TYPE_GEOMETRY));
field_pos++;
@@ -767,6 +774,8 @@ bool Protocol_simple::store(const char *from, uint length,
#ifndef DEBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_DECIMAL ||
+ field_types[field_pos] == MYSQL_TYPE_BIT ||
+ field_types[field_pos] == MYSQL_TYPE_NEWDECIMAL ||
(field_types[field_pos] >= MYSQL_TYPE_ENUM &&
field_types[field_pos] <= MYSQL_TYPE_GEOMETRY));
field_pos++;
@@ -791,6 +800,7 @@ bool Protocol_simple::store_short(longlong from)
{
#ifndef DEBUG_OFF
DBUG_ASSERT(field_types == 0 ||
+ field_types[field_pos] == MYSQL_TYPE_YEAR ||
field_types[field_pos] == MYSQL_TYPE_SHORT);
field_pos++;
#endif
@@ -829,6 +839,20 @@ bool Protocol_simple::store_longlong(longlong from, bool unsigned_flag)
}
+bool Protocol_simple::store_decimal(const my_decimal *d)
+{
+#ifndef DEBUG_OFF
+ DBUG_ASSERT(field_types == 0 ||
+ field_types[field_pos] == MYSQL_TYPE_NEWDECIMAL);
+ field_pos++;
+#endif
+ char buff[DECIMAL_MAX_STR_LENGTH];
+ String str(buff, sizeof(buff), &my_charset_bin);
+ (void) my_decimal2string(E_DEC_FATAL_ERROR, d, 0, 0, 0, &str);
+ return net_store_data(str.ptr(), str.length());
+}
+
+
bool Protocol_simple::store(float from, uint32 decimals, String *buffer)
{
#ifndef DEBUG_OFF
@@ -980,12 +1004,6 @@ void Protocol_prep::prepare_for_resend()
bool Protocol_prep::store(const char *from, uint length, CHARSET_INFO *fromcs)
{
CHARSET_INFO *tocs= thd->variables.character_set_results;
-#ifndef DEBUG_OFF
- DBUG_ASSERT(field_types == 0 ||
- field_types[field_pos] == MYSQL_TYPE_DECIMAL ||
- (field_types[field_pos] >= MYSQL_TYPE_ENUM &&
- field_types[field_pos] <= MYSQL_TYPE_GEOMETRY));
-#endif
field_pos++;
return store_string_aux(from, length, fromcs, tocs);
}
@@ -993,12 +1011,6 @@ bool Protocol_prep::store(const char *from, uint length, CHARSET_INFO *fromcs)
bool Protocol_prep::store(const char *from,uint length,
CHARSET_INFO *fromcs, CHARSET_INFO *tocs)
{
-#ifndef DEBUG_OFF
- DBUG_ASSERT(field_types == 0 ||
- field_types[field_pos] == MYSQL_TYPE_DECIMAL ||
- (field_types[field_pos] >= MYSQL_TYPE_ENUM &&
- field_types[field_pos] <= MYSQL_TYPE_GEOMETRY));
-#endif
field_pos++;
return store_string_aux(from, length, fromcs, tocs);
}
@@ -1016,10 +1028,6 @@ bool Protocol_prep::store_null()
bool Protocol_prep::store_tiny(longlong from)
{
-#ifndef DEBUG_OFF
- DBUG_ASSERT(field_types == 0 ||
- field_types[field_pos] == MYSQL_TYPE_TINY);
-#endif
char buff[1];
field_pos++;
buff[0]= (uchar) from;
@@ -1029,11 +1037,6 @@ bool Protocol_prep::store_tiny(longlong from)
bool Protocol_prep::store_short(longlong from)
{
-#ifndef DEBUG_OFF
- DBUG_ASSERT(field_types == 0 ||
- field_types[field_pos] == MYSQL_TYPE_SHORT ||
- field_types[field_pos] == MYSQL_TYPE_YEAR);
-#endif
field_pos++;
char *to= packet->prep_append(2, PACKET_BUFFER_EXTRA_ALLOC);
if (!to)
@@ -1045,11 +1048,6 @@ bool Protocol_prep::store_short(longlong from)
bool Protocol_prep::store_long(longlong from)
{
-#ifndef DEBUG_OFF
- DBUG_ASSERT(field_types == 0 ||
- field_types[field_pos] == MYSQL_TYPE_INT24 ||
- field_types[field_pos] == MYSQL_TYPE_LONG);
-#endif
field_pos++;
char *to= packet->prep_append(4, PACKET_BUFFER_EXTRA_ALLOC);
if (!to)
@@ -1061,10 +1059,6 @@ bool Protocol_prep::store_long(longlong from)
bool Protocol_prep::store_longlong(longlong from, bool unsigned_flag)
{
-#ifndef DEBUG_OFF
- DBUG_ASSERT(field_types == 0 ||
- field_types[field_pos] == MYSQL_TYPE_LONGLONG);
-#endif
field_pos++;
char *to= packet->prep_append(8, PACKET_BUFFER_EXTRA_ALLOC);
if (!to)
@@ -1073,13 +1067,21 @@ bool Protocol_prep::store_longlong(longlong from, bool unsigned_flag)
return 0;
}
-
-bool Protocol_prep::store(float from, uint32 decimals, String *buffer)
+bool Protocol_prep::store_decimal(const my_decimal *d)
{
#ifndef DEBUG_OFF
DBUG_ASSERT(field_types == 0 ||
- field_types[field_pos] == MYSQL_TYPE_FLOAT);
+ field_types[field_pos] == MYSQL_TYPE_NEWDECIMAL);
+ field_pos++;
#endif
+ char buff[DECIMAL_MAX_STR_LENGTH];
+ String str(buff, sizeof(buff), &my_charset_bin);
+ (void) my_decimal2string(E_DEC_FATAL_ERROR, d, 0, 0, 0, &str);
+ return store(str.ptr(), str.length(), str.charset());
+}
+
+bool Protocol_prep::store(float from, uint32 decimals, String *buffer)
+{
field_pos++;
char *to= packet->prep_append(4, PACKET_BUFFER_EXTRA_ALLOC);
if (!to)
@@ -1091,10 +1093,6 @@ bool Protocol_prep::store(float from, uint32 decimals, String *buffer)
bool Protocol_prep::store(double from, uint32 decimals, String *buffer)
{
-#ifndef DEBUG_OFF
- DBUG_ASSERT(field_types == 0 ||
- field_types[field_pos] == MYSQL_TYPE_DOUBLE);
-#endif
field_pos++;
char *to= packet->prep_append(8, PACKET_BUFFER_EXTRA_ALLOC);
if (!to)
@@ -1118,12 +1116,6 @@ bool Protocol_prep::store(Field *field)
bool Protocol_prep::store(TIME *tm)
{
-#ifndef DEBUG_OFF
- DBUG_ASSERT(field_types == 0 ||
- field_types[field_pos] == MYSQL_TYPE_DATETIME ||
- field_types[field_pos] == MYSQL_TYPE_DATE ||
- field_types[field_pos] == MYSQL_TYPE_TIMESTAMP);
-#endif
char buff[12],*pos;
uint length;
field_pos++;
@@ -1158,10 +1150,6 @@ bool Protocol_prep::store_date(TIME *tm)
bool Protocol_prep::store_time(TIME *tm)
{
-#ifndef DEBUG_OFF
- DBUG_ASSERT(field_types == 0 ||
- field_types[field_pos] == MYSQL_TYPE_TIME);
-#endif
char buff[13], *pos;
uint length;
field_pos++;
@@ -1188,12 +1176,3 @@ bool Protocol_prep::store_time(TIME *tm)
buff[0]=(char) length; // Length is stored first
return packet->append(buff, length+1, PACKET_BUFFER_EXTRA_ALLOC);
}
-
-#ifdef EMBEDDED_LIBRARY
-/* Should be removed when we define the Protocol_cursor's future */
-bool Protocol_cursor::write()
-{
- return Protocol_simple::write();
-}
-#endif
-