Commit 5d3eec14 authored by unknown's avatar unknown

New 4.1 protocol; SQLSTATE, CLIENT_MULTI_RESULTS, client character set

 


Docs/internals.texi:
  Updated protocol information
include/mysql.h:
  Added catalog to MYSQL_FIELD
  Added sqlstate handling to protocol
include/mysql_com.h:
  New 4.1 protocol
libmysql/libmysql.c:
  Added sqlstate handling
  Added CLIENT_MULTI_RESULTS
sql/field.cc:
  Indentation cleanup
sql/field.h:
  Indentation cleanup
sql/mysql_priv.h:
  Changed arguments to close_connection()
sql/mysqld.cc:
  Changed arguments to close_connection()
  Added checking of extra arguments to mysqld
sql/protocol.cc:
  Fixed bug in TIME handling
  Added SQLSTATE on errors
  Removed net_send_error()
sql/protocol.h:
  Removed net_send_error()
sql/repl_failsafe.cc:
  Fixed arguments to close_connection()
sql/sql_parse.cc:
  New 4.1 protocol
parent 35657273
...@@ -1766,7 +1766,10 @@ following connection establishment sequence is followed: ...@@ -1766,7 +1766,10 @@ following connection establishment sequence is followed:
+--------------------------------------------------------------------+ +--------------------------------------------------------------------+
| Header | CLIENT_xxx options supported | max_allowed_packet | | Header | CLIENT_xxx options supported | max_allowed_packet |
| | by client | for client | | | by client | for client |
| | 2 Bytes | 3 bytes | | | 4 Bytes | 4 bytes |
|--------------------------------------------------------------------|
| Character set | Reserved for the future |
| 1 Bytes | 23 bytes |
|--------------------------------------------------------------------| |--------------------------------------------------------------------|
| User Name | 0x00 | Crypted Password | 0x00 | Database Name | | User Name | 0x00 | Crypted Password | 0x00 | Database Name |
| n Bytes | 1 Byte | 8 Bytes | 1 Byte | n Bytes | | n Bytes | 1 Byte | 8 Bytes | 1 Byte | n Bytes |
...@@ -2326,7 +2329,7 @@ Warnings ...@@ -2326,7 +2329,7 @@ Warnings
@item @item
Prepared statements Prepared statements
@item @item
Binary protocol (will be faster than the current protocol that Binary protocol (is be faster than the current protocol that
converts everything to strings) converts everything to strings)
@end itemize @end itemize
...@@ -2335,7 +2338,7 @@ What has changed in 4.1 are: ...@@ -2335,7 +2338,7 @@ What has changed in 4.1 are:
@itemize @bullet @itemize @bullet
@item @item
A lot of new field information (database, real table name etc) A lot of new field information (catalog, database, real table name etc)
@item @item
The 'ok' packet has more status fields The 'ok' packet has more status fields
@item @item
...@@ -2374,15 +2377,16 @@ The field description result set contains the meta info for a result set. ...@@ -2374,15 +2377,16 @@ The field description result set contains the meta info for a result set.
@multitable @columnfractions .20 .80 @multitable @columnfractions .20 .80
@item Type @tab Comment @item Type @tab Comment
@item string @tab Catalog name (for 5.x)
@item string @tab Database name @item string @tab Database name
@item string @tab Table name alias (or table name if no alias) @item string @tab Table name alias (or table name if no alias)
@item string @tab Real table name @item string @tab Real table name
@item string @tab Alias for column name (or column name if not used) @item string @tab Alias for column name (or column name if not used)
@item 11 byte @tab Fixed length fields in one field part: @item 12 byte @tab Fixed length fields in one field part:
@itemize @itemize
@item 2 byte int @tab Character set number @item 2 byte int @tab Character set number
@item 3 byte int @tab Length of column definition @item 4 byte int @tab Length of column definition
@item 1 byte int @tab Enum value for field type @item 1 byte int @tab Enum value for field type
@item 3 byte int @tab 2 byte column flags (NOT_NULL_FLAG etc..) + 1 byte number of decimals. @item 3 byte int @tab 2 byte column flags (NOT_NULL_FLAG etc..) + 1 byte number of decimals.
@item 2 byte int @tab zero (reserved for future use) @item 2 byte int @tab zero (reserved for future use)
...@@ -2457,7 +2461,9 @@ The error packet has the following structure: ...@@ -2457,7 +2461,9 @@ The error packet has the following structure:
@item Size @tab Comment @item Size @tab Comment
@item 1 @tab 255 Error packet marker @item 1 @tab 255 Error packet marker
@item 2 @tab Error code @item 2 @tab Error code
@item 1-255 @tab Null terminated error message @item 1 @tab '#' marker that SQLSTATE follows
@item 6 @tab SQLSTATE code (000000 for many messages)
@item 1-512 @tab Null terminated error message
@end multitable @end multitable
The client/server protocol is designed in such a way that a packet The client/server protocol is designed in such a way that a packet
......
...@@ -83,6 +83,7 @@ typedef struct st_mysql_field { ...@@ -83,6 +83,7 @@ typedef struct st_mysql_field {
char *table; /* Table of column if column was a field */ char *table; /* Table of column if column was a field */
char *org_table; /* Org table name, if table was an alias */ char *org_table; /* Org table name, if table was an alias */
char *db; /* Database for table */ char *db; /* Database for table */
char *catalog; /* Catalog for table */
char *def; /* Default value (set by mysql_list_fields) */ char *def; /* Default value (set by mysql_list_fields) */
unsigned long length; /* Width of column */ unsigned long length; /* Width of column */
unsigned long max_length; /* Max width of selected set */ unsigned long max_length; /* Max width of selected set */
...@@ -91,6 +92,7 @@ typedef struct st_mysql_field { ...@@ -91,6 +92,7 @@ typedef struct st_mysql_field {
unsigned int table_length; unsigned int table_length;
unsigned int org_table_length; unsigned int org_table_length;
unsigned int db_length; unsigned int db_length;
unsigned int catalog_length;
unsigned int def_length; unsigned int def_length;
unsigned int flags; /* Div flags */ unsigned int flags; /* Div flags */
unsigned int decimals; /* Number of decimals in field */ unsigned int decimals; /* Number of decimals in field */
...@@ -346,6 +348,7 @@ my_ulonglong STDCALL mysql_affected_rows(MYSQL *mysql); ...@@ -346,6 +348,7 @@ my_ulonglong STDCALL mysql_affected_rows(MYSQL *mysql);
my_ulonglong STDCALL mysql_insert_id(MYSQL *mysql); my_ulonglong STDCALL mysql_insert_id(MYSQL *mysql);
unsigned int STDCALL mysql_errno(MYSQL *mysql); unsigned int STDCALL mysql_errno(MYSQL *mysql);
const char * STDCALL mysql_error(MYSQL *mysql); const char * STDCALL mysql_error(MYSQL *mysql);
const char *STDCALL mysql_sqlstate(MYSQL *mysql);
unsigned int STDCALL mysql_warning_count(MYSQL *mysql); unsigned int STDCALL mysql_warning_count(MYSQL *mysql);
const char * STDCALL mysql_info(MYSQL *mysql); const char * STDCALL mysql_info(MYSQL *mysql);
unsigned long STDCALL mysql_thread_id(MYSQL *mysql); unsigned long STDCALL mysql_thread_id(MYSQL *mysql);
...@@ -543,6 +546,7 @@ typedef struct st_mysql_stmt ...@@ -543,6 +546,7 @@ typedef struct st_mysql_stmt
unsigned int last_errno; /* error code */ unsigned int last_errno; /* error code */
enum PREP_STMT_STATE state; /* statement state */ enum PREP_STMT_STATE state; /* statement state */
char last_error[MYSQL_ERRMSG_SIZE]; /* error message */ char last_error[MYSQL_ERRMSG_SIZE]; /* error message */
char sqlstate[SQLSTATE_LENGTH+1];
my_bool long_alloced; /* flag to indicate long alloced */ my_bool long_alloced; /* flag to indicate long alloced */
my_bool send_types_to_server; /* Types sent to server */ my_bool send_types_to_server; /* Types sent to server */
my_bool param_buffers; /* param bound buffers */ my_bool param_buffers; /* param bound buffers */
...@@ -560,6 +564,7 @@ my_bool STDCALL mysql_bind_result(MYSQL_STMT * stmt, MYSQL_BIND * bnd); ...@@ -560,6 +564,7 @@ my_bool STDCALL mysql_bind_result(MYSQL_STMT * stmt, MYSQL_BIND * bnd);
my_bool STDCALL mysql_stmt_close(MYSQL_STMT * stmt); my_bool STDCALL mysql_stmt_close(MYSQL_STMT * stmt);
unsigned int STDCALL mysql_stmt_errno(MYSQL_STMT * stmt); unsigned int STDCALL mysql_stmt_errno(MYSQL_STMT * stmt);
const char *STDCALL mysql_stmt_error(MYSQL_STMT * stmt); const char *STDCALL mysql_stmt_error(MYSQL_STMT * stmt);
const char *STDCALL mysql_stmt_sqlstate(MYSQL_STMT * stmt);
my_bool STDCALL mysql_commit(MYSQL * mysql); my_bool STDCALL mysql_commit(MYSQL * mysql);
my_bool STDCALL mysql_rollback(MYSQL * mysql); my_bool STDCALL mysql_rollback(MYSQL * mysql);
my_bool STDCALL mysql_autocommit(MYSQL * mysql, my_bool auto_mode); my_bool STDCALL mysql_autocommit(MYSQL * mysql, my_bool auto_mode);
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#define HOSTNAME_LENGTH 60 #define HOSTNAME_LENGTH 60
#define USERNAME_LENGTH 16 #define USERNAME_LENGTH 16
#define SERVER_VERSION_LENGTH 60 #define SERVER_VERSION_LENGTH 60
#define SQLSTATE_LENGTH 6
#define LOCAL_HOST "localhost" #define LOCAL_HOST "localhost"
#define LOCAL_HOST_NAMEDPIPE "." #define LOCAL_HOST_NAMEDPIPE "."
...@@ -100,20 +101,22 @@ enum enum_server_command ...@@ -100,20 +101,22 @@ enum enum_server_command
#define CLIENT_ODBC 64 /* Odbc client */ #define CLIENT_ODBC 64 /* Odbc client */
#define CLIENT_LOCAL_FILES 128 /* Can use LOAD DATA LOCAL */ #define CLIENT_LOCAL_FILES 128 /* Can use LOAD DATA LOCAL */
#define CLIENT_IGNORE_SPACE 256 /* Ignore spaces before '(' */ #define CLIENT_IGNORE_SPACE 256 /* Ignore spaces before '(' */
#define CLIENT_PROTOCOL_41 512 /* New 4.1 protocol */
#define CLIENT_INTERACTIVE 1024 /* This is an interactive client */ #define CLIENT_INTERACTIVE 1024 /* This is an interactive client */
#define CLIENT_SSL 2048 /* Switch to SSL after handshake */ #define CLIENT_SSL 2048 /* Switch to SSL after handshake */
#define CLIENT_IGNORE_SIGPIPE 4096 /* IGNORE sigpipes */ #define CLIENT_IGNORE_SIGPIPE 4096 /* IGNORE sigpipes */
#define CLIENT_TRANSACTIONS 8192 /* Client knows about transactions */ #define CLIENT_TRANSACTIONS 8192 /* Client knows about transactions */
#define CLIENT_PROTOCOL_41 16384 /* New 4.1 protocol */ #define CLIENT_RESERVED 16384 /* Old flag for 4.1 protocol */
#define CLIENT_SECURE_CONNECTION 32768 /* New 4.1 authentication */ #define CLIENT_SECURE_CONNECTION 32768 /* New 4.1 authentication */
#define CLIENT_MULTI_QUERIES 65536 /* Enable/disable multi query support */ #define CLIENT_MULTI_QUERIES 65536 /* Enable/disable multiquery support */
#define CLIENT_MULTI_RESULTS 131072 /* Enable/disable multi-results */
#define SERVER_STATUS_IN_TRANS 1 /* Transaction has started */ #define SERVER_STATUS_IN_TRANS 1 /* Transaction has started */
#define SERVER_STATUS_AUTOCOMMIT 2 /* Server in auto_commit mode */ #define SERVER_STATUS_AUTOCOMMIT 2 /* Server in auto_commit mode */
#define SERVER_STATUS_MORE_RESULTS 4 /* More results on server */ #define SERVER_STATUS_MORE_RESULTS 4 /* More results on server */
#define SERVER_MORE_RESULTS_EXISTS 8 /* Multi query - next query exists */ #define SERVER_MORE_RESULTS_EXISTS 8 /* Multi query - next query exists */
#define MYSQL_ERRMSG_SIZE 200 #define MYSQL_ERRMSG_SIZE 512
#define NET_READ_TIMEOUT 30 /* Timeout on read */ #define NET_READ_TIMEOUT 30 /* Timeout on read */
#define NET_WRITE_TIMEOUT 60 /* Timeout on write */ #define NET_WRITE_TIMEOUT 60 /* Timeout on write */
#define NET_WAIT_TIMEOUT 8*60*60 /* Wait for new query */ #define NET_WAIT_TIMEOUT 8*60*60 /* Wait for new query */
...@@ -149,7 +152,7 @@ typedef struct st_net { ...@@ -149,7 +152,7 @@ typedef struct st_net {
queries in cache that have not stored its results yet queries in cache that have not stored its results yet
*/ */
#endif #endif
char last_error[MYSQL_ERRMSG_SIZE]; char last_error[MYSQL_ERRMSG_SIZE], sqlstate[SQLSTATE_LENGTH+1];
unsigned int last_errno; unsigned int last_errno;
unsigned char error; unsigned char error;
gptr query_cache_query; gptr query_cache_query;
......
This diff is collapsed.
...@@ -5519,6 +5519,6 @@ void Field::set_warning(const uint level, const uint code) ...@@ -5519,6 +5519,6 @@ void Field::set_warning(const uint level, const uint code)
{ {
THD *thd= current_thd; THD *thd= current_thd;
thd->cuted_fields++; thd->cuted_fields++;
push_warning_printf(thd, (MYSQL_ERROR::enum_warning_level)level, push_warning_printf(thd, (MYSQL_ERROR::enum_warning_level) level,
code, ER(code), field_name, thd->row_count); code, ER(code), field_name, thd->row_count);
} }
...@@ -212,8 +212,7 @@ class Field ...@@ -212,8 +212,7 @@ class Field
virtual bool get_time(TIME *ltime); virtual bool get_time(TIME *ltime);
virtual CHARSET_INFO *charset(void) const { return &my_charset_bin; } virtual CHARSET_INFO *charset(void) const { return &my_charset_bin; }
virtual void set_charset(CHARSET_INFO *charset) { } virtual void set_charset(CHARSET_INFO *charset) { }
virtual void set_warning(const unsigned int level, void set_warning(const unsigned int level, const unsigned int code);
const unsigned int code);
friend bool reopen_table(THD *,struct st_table *,bool); friend bool reopen_table(THD *,struct st_table *,bool);
friend int cre_myisam(my_string name, register TABLE *form, uint options, friend int cre_myisam(my_string name, register TABLE *form, uint options,
ulonglong auto_increment_value); ulonglong auto_increment_value);
......
...@@ -384,7 +384,7 @@ void table_cache_init(void); ...@@ -384,7 +384,7 @@ void table_cache_init(void);
void table_cache_free(void); void table_cache_free(void);
uint cached_tables(void); uint cached_tables(void);
void kill_mysql(void); void kill_mysql(void);
void close_connection(NET *net,uint errcode=0,bool lock=1); void close_connection(THD *thd, uint errcode, bool lock);
bool check_access(THD *thd, ulong access, const char *db=0, ulong *save_priv=0, bool check_access(THD *thd, ulong access, const char *db=0, ulong *save_priv=0,
bool no_grant=0, bool no_errors=0); bool no_grant=0, bool no_errors=0);
bool check_table_access(THD *thd, ulong want_access, TABLE_LIST *tables, bool check_table_access(THD *thd, ulong want_access, TABLE_LIST *tables,
......
...@@ -597,7 +597,6 @@ static void close_connections(void) ...@@ -597,7 +597,6 @@ static void close_connections(void)
/* Force remaining threads to die by closing the connection to the client */ /* Force remaining threads to die by closing the connection to the client */
(void) my_net_init(&net, (st_vio*) 0);
for (;;) for (;;)
{ {
DBUG_PRINT("quit",("Locking LOCK_thread_count")); DBUG_PRINT("quit",("Locking LOCK_thread_count"));
...@@ -609,17 +608,16 @@ static void close_connections(void) ...@@ -609,17 +608,16 @@ static void close_connections(void)
break; break;
} }
#ifndef __bsdi__ // Bug in BSDI kernel #ifndef __bsdi__ // Bug in BSDI kernel
if ((net.vio=tmp->net.vio) != 0) if (tmp->net.vio)
{ {
sql_print_error(ER(ER_FORCING_CLOSE),my_progname, sql_print_error(ER(ER_FORCING_CLOSE),my_progname,
tmp->thread_id,tmp->user ? tmp->user : ""); tmp->thread_id,tmp->user ? tmp->user : "");
close_connection(&net,0,0); close_connection(tmp,0,0);
} }
#endif #endif
DBUG_PRINT("quit",("Unlocking LOCK_thread_count")); DBUG_PRINT("quit",("Unlocking LOCK_thread_count"));
(void) pthread_mutex_unlock(&LOCK_thread_count); (void) pthread_mutex_unlock(&LOCK_thread_count);
} }
net_end(&net);
/* All threads has now been aborted */ /* All threads has now been aborted */
DBUG_PRINT("quit",("Waiting for threads to die (count=%u)",thread_count)); DBUG_PRINT("quit",("Waiting for threads to die (count=%u)",thread_count));
(void) pthread_mutex_lock(&LOCK_thread_count); (void) pthread_mutex_lock(&LOCK_thread_count);
...@@ -1215,19 +1213,20 @@ void yyerror(const char *s) ...@@ -1215,19 +1213,20 @@ void yyerror(const char *s)
#ifndef EMBEDDED_LIBRARY #ifndef EMBEDDED_LIBRARY
void close_connection(NET *net,uint errcode,bool lock) void close_connection(THD *thd, uint errcode, bool lock)
{ {
st_vio* vio; st_vio *vio;
DBUG_ENTER("close_connection"); DBUG_ENTER("close_connection");
DBUG_PRINT("enter",("fd: %s error: '%s'", DBUG_PRINT("enter",("fd: %s error: '%s'",
net->vio? vio_description(net->vio):"(not connected)", thd->net.vio ? vio_description(thd->net.vio) :
"(not connected)",
errcode ? ER(errcode) : "")); errcode ? ER(errcode) : ""));
if (lock) if (lock)
(void) pthread_mutex_lock(&LOCK_thread_count); (void) pthread_mutex_lock(&LOCK_thread_count);
if ((vio=net->vio) != 0) if ((vio=thd->net.vio) != 0)
{ {
if (errcode) if (errcode)
net_send_error(net,errcode,ER(errcode)); /* purecov: inspected */ send_error(thd, errcode, ER(errcode)); /* purecov: inspected */
vio_close(vio); /* vio is freed in delete thd */ vio_close(vio); /* vio is freed in delete thd */
} }
if (lock) if (lock)
...@@ -2717,7 +2716,7 @@ static void create_new_thread(THD *thd) ...@@ -2717,7 +2716,7 @@ static void create_new_thread(THD *thd)
if (thread_count - delayed_insert_threads >= max_connections+1 || abort_loop) if (thread_count - delayed_insert_threads >= max_connections+1 || abort_loop)
{ {
DBUG_PRINT("error",("Too many connections")); DBUG_PRINT("error",("Too many connections"));
close_connection(net,ER_CON_COUNT_ERROR); close_connection(thd, ER_CON_COUNT_ERROR, 1);
delete thd; delete thd;
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
...@@ -2772,7 +2771,7 @@ static void create_new_thread(THD *thd) ...@@ -2772,7 +2771,7 @@ static void create_new_thread(THD *thd)
(void) pthread_mutex_unlock(&LOCK_thread_count); (void) pthread_mutex_unlock(&LOCK_thread_count);
net_printf(thd,ER_CANT_CREATE_THREAD,error); net_printf(thd,ER_CANT_CREATE_THREAD,error);
(void) pthread_mutex_lock(&LOCK_thread_count); (void) pthread_mutex_lock(&LOCK_thread_count);
close_connection(net,0,0); close_connection(thd,0,0);
delete thd; delete thd;
(void) pthread_mutex_unlock(&LOCK_thread_count); (void) pthread_mutex_unlock(&LOCK_thread_count);
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
...@@ -3093,7 +3092,7 @@ extern "C" pthread_handler_decl(handle_connections_namedpipes,arg) ...@@ -3093,7 +3092,7 @@ extern "C" pthread_handler_decl(handle_connections_namedpipes,arg)
if (!(thd->net.vio = vio_new_win32pipe(hConnectedPipe)) || if (!(thd->net.vio = vio_new_win32pipe(hConnectedPipe)) ||
my_net_init(&thd->net, thd->net.vio)) my_net_init(&thd->net, thd->net.vio))
{ {
close_connection(&thd->net,ER_OUT_OF_RESOURCES); close_connection(thd, ER_OUT_OF_RESOURCES, 1);
delete thd; delete thd;
continue; continue;
} }
...@@ -3294,7 +3293,7 @@ Send number of connection to client ...@@ -3294,7 +3293,7 @@ Send number of connection to client
event_client_read,event_server_wrote,event_server_read)) || event_client_read,event_server_wrote,event_server_read)) ||
my_net_init(&thd->net, thd->net.vio)) my_net_init(&thd->net, thd->net.vio))
{ {
close_connection(&thd->net,ER_OUT_OF_RESOURCES); close_connection(thd, ER_OUT_OF_RESOURCES, 1);
delete thd; delete thd;
error_allow = TRUE; error_allow = TRUE;
} }
...@@ -5284,6 +5283,11 @@ static void get_options(int argc,char **argv) ...@@ -5284,6 +5283,11 @@ static void get_options(int argc,char **argv)
if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option))) if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option)))
exit(ho_error); exit(ho_error);
if (argc > 0)
{
fprintf(stderr, "%s: Too many arguments.\nUse --help to get a list of available options\n", my_progname);
exit(ho_error);
}
#if defined(HAVE_BROKEN_REALPATH) #if defined(HAVE_BROKEN_REALPATH)
my_use_symdir=0; my_use_symdir=0;
......
...@@ -52,7 +52,7 @@ void send_error(THD *thd, uint sql_errno, const char *err) ...@@ -52,7 +52,7 @@ void send_error(THD *thd, uint sql_errno, const char *err)
{ {
#ifndef EMBEDDED_LIBRARY #ifndef EMBEDDED_LIBRARY
uint length; uint length;
char buff[MYSQL_ERRMSG_SIZE+2]; char buff[MYSQL_ERRMSG_SIZE+2], *pos;
#endif #endif
NET *net= &thd->net; NET *net= &thd->net;
DBUG_ENTER("send_error"); DBUG_ENTER("send_error");
...@@ -98,7 +98,14 @@ void send_error(THD *thd, uint sql_errno, const char *err) ...@@ -98,7 +98,14 @@ void send_error(THD *thd, uint sql_errno, const char *err)
if (net->return_errno) if (net->return_errno)
{ // new client code; Add errno before message { // new client code; Add errno before message
int2store(buff,sql_errno); int2store(buff,sql_errno);
length= (uint) (strmake(buff+2,err,MYSQL_ERRMSG_SIZE-1) - buff); pos= buff+2;
if (thd->client_capabilities & CLIENT_PROTOCOL_41)
{
/* The first # is to make the protocol backward compatible */
strmov(buff+2, "#000000");
pos= buff + 2 + SQLSTATE_LENGTH +1;
}
length= (uint) (strmake(pos, err, MYSQL_ERRMSG_SIZE-1) - buff);
err=buff; err=buff;
} }
else else
...@@ -113,26 +120,6 @@ void send_error(THD *thd, uint sql_errno, const char *err) ...@@ -113,26 +120,6 @@ void send_error(THD *thd, uint sql_errno, const char *err)
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
/*
Send an error to the client when a connection is forced close
This is used by mysqld.cc, which doesn't have a THD
*/
#ifndef EMBEDDED_LIBRARY
void net_send_error(NET *net, uint sql_errno, const char *err)
{
char buff[2];
uint length;
DBUG_ENTER("send_net_error");
int2store(buff,sql_errno);
length=(uint) strlen(err);
set_if_smaller(length,MYSQL_ERRMSG_SIZE-1);
net_write_command(net,(uchar) 255, buff, 2, err, length);
DBUG_VOID_RETURN;
}
#endif
/* /*
Send a warning to the end user Send a warning to the end user
...@@ -173,7 +160,7 @@ net_printf(THD *thd, uint errcode, ...) ...@@ -173,7 +160,7 @@ net_printf(THD *thd, uint errcode, ...)
#ifndef EMBEDDED_LIBRARY #ifndef EMBEDDED_LIBRARY
const char *text_pos; const char *text_pos;
#else #else
char text_pos[500]; char text_pos[1024];
#endif #endif
int head_length= NET_HEADER_SIZE; int head_length= NET_HEADER_SIZE;
NET *net= &thd->net; NET *net= &thd->net;
...@@ -199,9 +186,11 @@ net_printf(THD *thd, uint errcode, ...) ...@@ -199,9 +186,11 @@ net_printf(THD *thd, uint errcode, ...)
format=va_arg(args,char*); format=va_arg(args,char*);
errcode= ER_UNKNOWN_ERROR; errcode= ER_UNKNOWN_ERROR;
} }
offset= net->return_errno ? 2 : 0; offset= (net->return_errno ?
((thd->client_capabilities & CLIENT_PROTOCOL_41) ?
2+SQLSTATE_LENGTH+1 : 2) : 0);
#ifndef EMBEDDED_LIBRARY #ifndef EMBEDDED_LIBRARY
text_pos=(char*) net->buff+head_length+offset+1; text_pos=(char*) net->buff + head_length + offset + 1;
#endif #endif
(void) vsprintf(my_const_cast(char*) (text_pos),format,args); (void) vsprintf(my_const_cast(char*) (text_pos),format,args);
length=(uint) strlen((char*) text_pos); length=(uint) strlen((char*) text_pos);
...@@ -228,7 +217,15 @@ net_printf(THD *thd, uint errcode, ...) ...@@ -228,7 +217,15 @@ net_printf(THD *thd, uint errcode, ...)
net->buff[3]= (net->compress) ? 0 : (uchar) (net->pkt_nr++); net->buff[3]= (net->compress) ? 0 : (uchar) (net->pkt_nr++);
net->buff[head_length]=(uchar) 255; // Error package net->buff[head_length]=(uchar) 255; // Error package
if (offset) if (offset)
int2store(text_pos-2, errcode); {
uchar *pos= net->buff+head_length+1;
int2store(pos, errcode);
if (thd->client_capabilities & CLIENT_PROTOCOL_41)
{
/* The first # is to make the protocol backward compatible */
memcpy(pos+2, "#000000", SQLSTATE_LENGTH +1);
}
}
VOID(net_real_write(net,(char*) net->buff,length+head_length+1+offset)); VOID(net_real_write(net,(char*) net->buff,length+head_length+1+offset));
#else #else
net->last_errno= errcode; net->last_errno= errcode;
...@@ -502,6 +499,7 @@ bool Protocol::send_fields(List<Item> *list, uint flag) ...@@ -502,6 +499,7 @@ bool Protocol::send_fields(List<Item> *list, uint flag)
String tmp((char*) buff,sizeof(buff),&my_charset_bin); String tmp((char*) buff,sizeof(buff),&my_charset_bin);
Protocol_simple prot(thd); Protocol_simple prot(thd);
String *packet= prot.storage_packet(); String *packet= prot.storage_packet();
CHARSET_INFO *thd_charset= thd->charset();
DBUG_ENTER("send_fields"); DBUG_ENTER("send_fields");
if (flag & 1) if (flag & 1)
...@@ -526,36 +524,37 @@ bool Protocol::send_fields(List<Item> *list, uint flag) ...@@ -526,36 +524,37 @@ bool Protocol::send_fields(List<Item> *list, uint flag)
if (thd->client_capabilities & CLIENT_PROTOCOL_41) if (thd->client_capabilities & CLIENT_PROTOCOL_41)
{ {
if (prot.store(field.db_name, (uint) strlen(field.db_name), if (prot.store("std", 3, cs, thd_charset) ||
cs, thd->charset()) || prot.store(field.db_name, (uint) strlen(field.db_name),
cs, thd_charset) ||
prot.store(field.table_name, (uint) strlen(field.table_name), prot.store(field.table_name, (uint) strlen(field.table_name),
cs, thd->charset()) || cs, thd_charset) ||
prot.store(field.org_table_name, (uint) strlen(field.org_table_name), prot.store(field.org_table_name, (uint) strlen(field.org_table_name),
cs, thd->charset()) || cs, thd_charset) ||
prot.store(field.col_name, (uint) strlen(field.col_name), prot.store(field.col_name, (uint) strlen(field.col_name),
cs, thd->charset()) || cs, thd_charset) ||
prot.store(field.org_col_name, (uint) strlen(field.org_col_name), prot.store(field.org_col_name, (uint) strlen(field.org_col_name),
cs, thd->charset()) || cs, thd_charset) ||
packet->realloc(packet->length()+12)) packet->realloc(packet->length()+12))
goto err; goto err;
/* Store fixed length fields */ /* Store fixed length fields */
pos= (char*) packet->ptr()+packet->length(); pos= (char*) packet->ptr()+packet->length();
*pos++= 11; // Length of packed fields *pos++= 12; // Length of packed fields
int2store(pos, field.charsetnr); int2store(pos, field.charsetnr);
int3store(pos+2, field.length); int4store(pos+2, field.length);
pos[5]= field.type; pos[6]= field.type;
int2store(pos+6,field.flags); int2store(pos+7,field.flags);
pos[8]= (char) field.decimals; pos[9]= (char) field.decimals;
pos[9]= 0; // For the future
pos[10]= 0; // For the future pos[10]= 0; // For the future
pos+= 11; pos[11]= 0; // For the future
pos+= 12;
} }
else else
{ {
if (prot.store(field.table_name, (uint) strlen(field.table_name), if (prot.store(field.table_name, (uint) strlen(field.table_name),
cs, thd->charset()) || cs, thd_charset) ||
prot.store(field.col_name, (uint) strlen(field.col_name), prot.store(field.col_name, (uint) strlen(field.col_name),
cs, thd->charset()) || cs, thd_charset) ||
packet->realloc(packet->length()+10)) packet->realloc(packet->length()+10))
goto err; goto err;
pos= (char*) packet->ptr()+packet->length(); pos= (char*) packet->ptr()+packet->length();
...@@ -893,9 +892,10 @@ bool Protocol_simple::store_time(TIME *tm) ...@@ -893,9 +892,10 @@ bool Protocol_simple::store_time(TIME *tm)
#endif #endif
char buff[40]; char buff[40];
uint length; uint length;
uint day= (tm->year || tm->month) ? 0 : tm->day;
length= my_sprintf(buff,(buff, "%s%02ld:%02d:%02d", length= my_sprintf(buff,(buff, "%s%02ld:%02d:%02d",
tm->neg ? "-" : "", tm->neg ? "-" : "",
(long) tm->day*3600L+(long) tm->hour, (long) day*24L+(long) tm->hour,
(int) tm->minute, (int) tm->minute,
(int) tm->second)); (int) tm->second));
return net_store_data((char*) buff, length); return net_store_data((char*) buff, length);
......
...@@ -162,7 +162,6 @@ void net_printf(THD *thd,uint sql_errno, ...); ...@@ -162,7 +162,6 @@ void net_printf(THD *thd,uint sql_errno, ...);
void send_ok(THD *thd, ha_rows affected_rows=0L, ulonglong id=0L, void send_ok(THD *thd, ha_rows affected_rows=0L, ulonglong id=0L,
const char *info=0); const char *info=0);
void send_eof(THD *thd, bool no_flush=0); void send_eof(THD *thd, bool no_flush=0);
void net_send_error(NET *net, uint sql_errno, const char *err);
char *net_store_length(char *packet,ulonglong length); char *net_store_length(char *packet,ulonglong length);
char *net_store_length(char *packet,uint length); char *net_store_length(char *packet,uint length);
char *net_store_data(char *to,const char *from, uint length); char *net_store_data(char *to,const char *from, uint length);
......
...@@ -72,7 +72,7 @@ static int init_failsafe_rpl_thread(THD* thd) ...@@ -72,7 +72,7 @@ static int init_failsafe_rpl_thread(THD* thd)
if (init_thr_lock() || thd->store_globals()) if (init_thr_lock() || thd->store_globals())
{ {
close_connection(&thd->net,ER_OUT_OF_RESOURCES); // is this needed? close_connection(thd, ER_OUT_OF_RESOURCES, 1); // is this needed?
end_thread(thd,0); end_thread(thd,0);
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
......
...@@ -601,7 +601,7 @@ check_connections(THD *thd) ...@@ -601,7 +601,7 @@ check_connections(THD *thd)
{ {
/* buff[] needs to big enough to hold the server_version variable */ /* buff[] needs to big enough to hold the server_version variable */
char buff[SERVER_VERSION_LENGTH + SCRAMBLE_LENGTH+64]; char buff[SERVER_VERSION_LENGTH + SCRAMBLE_LENGTH+64];
int client_flags = (CLIENT_LONG_FLAG | CLIENT_CONNECT_WITH_DB | ulong client_flags = (CLIENT_LONG_FLAG | CLIENT_CONNECT_WITH_DB |
CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION); CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION);
if (opt_using_transactions) if (opt_using_transactions)
...@@ -644,11 +644,26 @@ check_connections(THD *thd) ...@@ -644,11 +644,26 @@ check_connections(THD *thd)
return(ER_OUT_OF_RESOURCES); return(ER_OUT_OF_RESOURCES);
thd->client_capabilities=uint2korr(net->read_pos); thd->client_capabilities=uint2korr(net->read_pos);
#ifdef TO_BE_REMOVED_IN_4_1_RELEASE
/*
This is just a safety check against any client that would use the old
CLIENT_CHANGE_USER flag
*/
if ((thd->client_capabilities & CLIENT_PROTOCOL_41) &&
!(thd->client_capabilities & (CLIENT_RESERVED |
CLIENT_SECURE_CONNECTION |
CLIENT_MULTI_RESULTS)))
thd->client_capabilities&= ~CLIENT_PROTOCOL_41;
#endif
if (thd->client_capabilities & CLIENT_PROTOCOL_41) if (thd->client_capabilities & CLIENT_PROTOCOL_41)
{ {
thd->client_capabilities|= ((ulong) uint2korr(net->read_pos+2)) << 16; thd->client_capabilities|= ((ulong) uint2korr(net->read_pos+2)) << 16;
thd->max_client_packet_length= uint4korr(net->read_pos+4); thd->max_client_packet_length= uint4korr(net->read_pos+4);
end= (char*) net->read_pos+8; if (!(thd->variables.character_set_client=
get_charset((uint) net->read_pos[8], MYF(0))))
thd->variables.character_set_client=
global_system_variables.character_set_client;
end= (char*) net->read_pos+32;
} }
else else
{ {
...@@ -778,7 +793,7 @@ pthread_handler_decl(handle_one_connection,arg) ...@@ -778,7 +793,7 @@ pthread_handler_decl(handle_one_connection,arg)
// The following calls needs to be done before we call DBUG_ macros // The following calls needs to be done before we call DBUG_ macros
if (!(test_flags & TEST_NO_THREADS) & my_thread_init()) if (!(test_flags & TEST_NO_THREADS) & my_thread_init())
{ {
close_connection(&thd->net,ER_OUT_OF_RESOURCES); close_connection(thd, ER_OUT_OF_RESOURCES, 1);
statistic_increment(aborted_connects,&LOCK_status); statistic_increment(aborted_connects,&LOCK_status);
end_thread(thd,0); end_thread(thd,0);
return 0; return 0;
...@@ -805,7 +820,7 @@ pthread_handler_decl(handle_one_connection,arg) ...@@ -805,7 +820,7 @@ pthread_handler_decl(handle_one_connection,arg)
#endif #endif
if (thd->store_globals()) if (thd->store_globals())
{ {
close_connection(&thd->net,ER_OUT_OF_RESOURCES); close_connection(thd, ER_OUT_OF_RESOURCES, 1);
statistic_increment(aborted_connects,&LOCK_status); statistic_increment(aborted_connects,&LOCK_status);
end_thread(thd,0); end_thread(thd,0);
return 0; return 0;
...@@ -863,7 +878,7 @@ pthread_handler_decl(handle_one_connection,arg) ...@@ -863,7 +878,7 @@ pthread_handler_decl(handle_one_connection,arg)
} }
end_thread: end_thread:
close_connection(net); close_connection(thd, 0, 1);
end_thread(thd,1); end_thread(thd,1);
/* /*
If end_thread returns, we are either running with --one-thread If end_thread returns, we are either running with --one-thread
...@@ -889,7 +904,7 @@ extern "C" pthread_handler_decl(handle_bootstrap,arg) ...@@ -889,7 +904,7 @@ extern "C" pthread_handler_decl(handle_bootstrap,arg)
/* The following must be called before DBUG_ENTER */ /* The following must be called before DBUG_ENTER */
if (my_thread_init() || thd->store_globals()) if (my_thread_init() || thd->store_globals())
{ {
close_connection(&thd->net,ER_OUT_OF_RESOURCES); close_connection(thd, ER_OUT_OF_RESOURCES, 1);
thd->fatal_error(); thd->fatal_error();
goto end; goto end;
} }
...@@ -1419,7 +1434,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, ...@@ -1419,7 +1434,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
#ifndef OS2 #ifndef OS2
send_eof(thd); // This is for 'quit request' send_eof(thd); // This is for 'quit request'
#endif #endif
close_connection(net); close_connection(thd, 0, 1);
close_thread_tables(thd); // Free before kill close_thread_tables(thd); // Free before kill
free_root(&thd->mem_root,MYF(0)); free_root(&thd->mem_root,MYF(0));
free_root(&thd->transaction.mem_root,MYF(0)); free_root(&thd->transaction.mem_root,MYF(0));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment