summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <monty@mashka.mysql.fi>2003-05-26 19:01:20 +0300
committerunknown <monty@mashka.mysql.fi>2003-05-26 19:01:20 +0300
commit5d3eec14dd3e8b2e4656e5559114650bee54a5e6 (patch)
tree8384ed6e6835d6903702a8f44da157d99f0ff97c /sql
parent3565727359aaea5f2fab3740d71d36fb9015f77a (diff)
downloadmariadb-git-5d3eec14dd3e8b2e4656e5559114650bee54a5e6.tar.gz
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
Diffstat (limited to 'sql')
-rw-r--r--sql/field.cc2
-rw-r--r--sql/field.h3
-rw-r--r--sql/mysql_priv.h2
-rw-r--r--sql/mysqld.cc32
-rw-r--r--sql/protocol.cc84
-rw-r--r--sql/protocol.h1
-rw-r--r--sql/repl_failsafe.cc2
-rw-r--r--sql/sql_parse.cc31
8 files changed, 87 insertions, 70 deletions
diff --git a/sql/field.cc b/sql/field.cc
index 5c3961a949e..3397e9fa0ea 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -5519,6 +5519,6 @@ void Field::set_warning(const uint level, const uint code)
{
THD *thd= current_thd;
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);
}
diff --git a/sql/field.h b/sql/field.h
index cf08b1a9717..f16af9cfe0f 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -212,8 +212,7 @@ public:
virtual bool get_time(TIME *ltime);
virtual CHARSET_INFO *charset(void) const { return &my_charset_bin; }
virtual void set_charset(CHARSET_INFO *charset) { }
- virtual void set_warning(const unsigned int level,
- const unsigned int code);
+ void set_warning(const unsigned int level, const unsigned int code);
friend bool reopen_table(THD *,struct st_table *,bool);
friend int cre_myisam(my_string name, register TABLE *form, uint options,
ulonglong auto_increment_value);
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index c618b6bacd3..712c8853a20 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -384,7 +384,7 @@ void table_cache_init(void);
void table_cache_free(void);
uint cached_tables(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 no_grant=0, bool no_errors=0);
bool check_table_access(THD *thd, ulong want_access, TABLE_LIST *tables,
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 6603e4c306a..fe78c0fe27c 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -597,7 +597,6 @@ static void close_connections(void)
/* Force remaining threads to die by closing the connection to the client */
- (void) my_net_init(&net, (st_vio*) 0);
for (;;)
{
DBUG_PRINT("quit",("Locking LOCK_thread_count"));
@@ -609,17 +608,16 @@ static void close_connections(void)
break;
}
#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,
tmp->thread_id,tmp->user ? tmp->user : "");
- close_connection(&net,0,0);
+ close_connection(tmp,0,0);
}
#endif
DBUG_PRINT("quit",("Unlocking LOCK_thread_count"));
(void) pthread_mutex_unlock(&LOCK_thread_count);
}
- net_end(&net);
/* All threads has now been aborted */
DBUG_PRINT("quit",("Waiting for threads to die (count=%u)",thread_count));
(void) pthread_mutex_lock(&LOCK_thread_count);
@@ -1215,19 +1213,20 @@ void yyerror(const char *s)
#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_PRINT("enter",("fd: %s error: '%s'",
- net->vio? vio_description(net->vio):"(not connected)",
- errcode ? ER(errcode) : ""));
+ thd->net.vio ? vio_description(thd->net.vio) :
+ "(not connected)",
+ errcode ? ER(errcode) : ""));
if (lock)
(void) pthread_mutex_lock(&LOCK_thread_count);
- if ((vio=net->vio) != 0)
+ if ((vio=thd->net.vio) != 0)
{
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 */
}
if (lock)
@@ -2717,7 +2716,7 @@ static void create_new_thread(THD *thd)
if (thread_count - delayed_insert_threads >= max_connections+1 || abort_loop)
{
DBUG_PRINT("error",("Too many connections"));
- close_connection(net,ER_CON_COUNT_ERROR);
+ close_connection(thd, ER_CON_COUNT_ERROR, 1);
delete thd;
DBUG_VOID_RETURN;
}
@@ -2772,7 +2771,7 @@ static void create_new_thread(THD *thd)
(void) pthread_mutex_unlock(&LOCK_thread_count);
net_printf(thd,ER_CANT_CREATE_THREAD,error);
(void) pthread_mutex_lock(&LOCK_thread_count);
- close_connection(net,0,0);
+ close_connection(thd,0,0);
delete thd;
(void) pthread_mutex_unlock(&LOCK_thread_count);
DBUG_VOID_RETURN;
@@ -3093,7 +3092,7 @@ extern "C" pthread_handler_decl(handle_connections_namedpipes,arg)
if (!(thd->net.vio = vio_new_win32pipe(hConnectedPipe)) ||
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;
continue;
}
@@ -3294,7 +3293,7 @@ Send number of connection to client
event_client_read,event_server_wrote,event_server_read)) ||
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;
error_allow = TRUE;
}
@@ -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)))
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)
my_use_symdir=0;
diff --git a/sql/protocol.cc b/sql/protocol.cc
index 09531f0922c..848321c1576 100644
--- a/sql/protocol.cc
+++ b/sql/protocol.cc
@@ -52,7 +52,7 @@ void send_error(THD *thd, uint sql_errno, const char *err)
{
#ifndef EMBEDDED_LIBRARY
uint length;
- char buff[MYSQL_ERRMSG_SIZE+2];
+ char buff[MYSQL_ERRMSG_SIZE+2], *pos;
#endif
NET *net= &thd->net;
DBUG_ENTER("send_error");
@@ -98,7 +98,14 @@ void send_error(THD *thd, uint sql_errno, const char *err)
if (net->return_errno)
{ // new client code; Add errno before message
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;
}
else
@@ -113,26 +120,6 @@ void send_error(THD *thd, uint sql_errno, const char *err)
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
@@ -173,7 +160,7 @@ net_printf(THD *thd, uint errcode, ...)
#ifndef EMBEDDED_LIBRARY
const char *text_pos;
#else
- char text_pos[500];
+ char text_pos[1024];
#endif
int head_length= NET_HEADER_SIZE;
NET *net= &thd->net;
@@ -199,9 +186,11 @@ net_printf(THD *thd, uint errcode, ...)
format=va_arg(args,char*);
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
- text_pos=(char*) net->buff+head_length+offset+1;
+ text_pos=(char*) net->buff + head_length + offset + 1;
#endif
(void) vsprintf(my_const_cast(char*) (text_pos),format,args);
length=(uint) strlen((char*) text_pos);
@@ -228,7 +217,15 @@ net_printf(THD *thd, uint errcode, ...)
net->buff[3]= (net->compress) ? 0 : (uchar) (net->pkt_nr++);
net->buff[head_length]=(uchar) 255; // Error package
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));
#else
net->last_errno= errcode;
@@ -502,6 +499,7 @@ bool Protocol::send_fields(List<Item> *list, uint flag)
String tmp((char*) buff,sizeof(buff),&my_charset_bin);
Protocol_simple prot(thd);
String *packet= prot.storage_packet();
+ CHARSET_INFO *thd_charset= thd->charset();
DBUG_ENTER("send_fields");
if (flag & 1)
@@ -526,36 +524,37 @@ bool Protocol::send_fields(List<Item> *list, uint flag)
if (thd->client_capabilities & CLIENT_PROTOCOL_41)
{
- if (prot.store(field.db_name, (uint) strlen(field.db_name),
- cs, thd->charset()) ||
+ if (prot.store("std", 3, 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),
- cs, thd->charset()) ||
+ cs, thd_charset) ||
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),
- cs, thd->charset()) ||
+ cs, thd_charset) ||
prot.store(field.org_col_name, (uint) strlen(field.org_col_name),
- cs, thd->charset()) ||
+ cs, thd_charset) ||
packet->realloc(packet->length()+12))
goto err;
/* Store fixed length fields */
pos= (char*) packet->ptr()+packet->length();
- *pos++= 11; // Length of packed fields
+ *pos++= 12; // Length of packed fields
int2store(pos, field.charsetnr);
- int3store(pos+2, field.length);
- pos[5]= field.type;
- int2store(pos+6,field.flags);
- pos[8]= (char) field.decimals;
- pos[9]= 0; // For the future
+ int4store(pos+2, field.length);
+ pos[6]= field.type;
+ int2store(pos+7,field.flags);
+ pos[9]= (char) field.decimals;
pos[10]= 0; // For the future
- pos+= 11;
+ pos[11]= 0; // For the future
+ pos+= 12;
}
else
{
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),
- cs, thd->charset()) ||
+ cs, thd_charset) ||
packet->realloc(packet->length()+10))
goto err;
pos= (char*) packet->ptr()+packet->length();
@@ -893,9 +892,10 @@ bool Protocol_simple::store_time(TIME *tm)
#endif
char buff[40];
uint length;
+ uint day= (tm->year || tm->month) ? 0 : tm->day;
length= my_sprintf(buff,(buff, "%s%02ld:%02d:%02d",
tm->neg ? "-" : "",
- (long) tm->day*3600L+(long) tm->hour,
+ (long) day*24L+(long) tm->hour,
(int) tm->minute,
(int) tm->second));
return net_store_data((char*) buff, length);
diff --git a/sql/protocol.h b/sql/protocol.h
index dd644afd335..2110f1877c2 100644
--- a/sql/protocol.h
+++ b/sql/protocol.h
@@ -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,
const char *info=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,uint length);
char *net_store_data(char *to,const char *from, uint length);
diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc
index 58769827bed..896537dfe04 100644
--- a/sql/repl_failsafe.cc
+++ b/sql/repl_failsafe.cc
@@ -72,7 +72,7 @@ static int init_failsafe_rpl_thread(THD* thd)
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);
DBUG_RETURN(-1);
}
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index e8f028e3720..e6ffec7ef26 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -601,8 +601,8 @@ check_connections(THD *thd)
{
/* buff[] needs to big enough to hold the server_version variable */
char buff[SERVER_VERSION_LENGTH + SCRAMBLE_LENGTH+64];
- int client_flags = (CLIENT_LONG_FLAG | CLIENT_CONNECT_WITH_DB |
- CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION);
+ ulong client_flags = (CLIENT_LONG_FLAG | CLIENT_CONNECT_WITH_DB |
+ CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION);
if (opt_using_transactions)
client_flags|=CLIENT_TRANSACTIONS;
@@ -644,11 +644,26 @@ check_connections(THD *thd)
return(ER_OUT_OF_RESOURCES);
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)
{
thd->client_capabilities|= ((ulong) uint2korr(net->read_pos+2)) << 16;
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
{
@@ -778,7 +793,7 @@ pthread_handler_decl(handle_one_connection,arg)
// The following calls needs to be done before we call DBUG_ macros
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);
end_thread(thd,0);
return 0;
@@ -805,7 +820,7 @@ pthread_handler_decl(handle_one_connection,arg)
#endif
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);
end_thread(thd,0);
return 0;
@@ -863,7 +878,7 @@ pthread_handler_decl(handle_one_connection,arg)
}
end_thread:
- close_connection(net);
+ close_connection(thd, 0, 1);
end_thread(thd,1);
/*
If end_thread returns, we are either running with --one-thread
@@ -889,7 +904,7 @@ extern "C" pthread_handler_decl(handle_bootstrap,arg)
/* The following must be called before DBUG_ENTER */
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();
goto end;
}
@@ -1419,7 +1434,7 @@ restore_user:
#ifndef OS2
send_eof(thd); // This is for 'quit request'
#endif
- close_connection(net);
+ close_connection(thd, 0, 1);
close_thread_tables(thd); // Free before kill
free_root(&thd->mem_root,MYF(0));
free_root(&thd->transaction.mem_root,MYF(0));