protocol.cpp
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:31k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2000-2003 MySQL AB
  2.    This program is free software; you can redistribute it and/or modify
  3.    it under the terms of the GNU General Public License as published by
  4.    the Free Software Foundation; either version 2 of the License, or
  5.    (at your option) any later version.
  6.    This program is distributed in the hope that it will be useful,
  7.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  8.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  9.    GNU General Public License for more details.
  10.    You should have received a copy of the GNU General Public License
  11.    along with this program; if not, write to the Free Software
  12.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  13. /*
  14.   Low level functions for storing data to be send to the MySQL client
  15.   The actual communction is handled by the net_xxx functions in net_serv.cc
  16. */
  17. #ifdef USE_PRAGMA_IMPLEMENTATION
  18. #pragma implementation // gcc: Class implementation
  19. #endif
  20. #include "mysql_priv.h"
  21. #include <stdarg.h>
  22. static const unsigned int PACKET_BUFFER_EXTRA_ALLOC= 1024;
  23. #ifndef EMBEDDED_LIBRARY
  24. bool Protocol::net_store_data(const char *from, uint length)
  25. #else
  26. bool Protocol_prep::net_store_data(const char *from, uint length)
  27. #endif
  28. {
  29.   ulong packet_length=packet->length();
  30.   /* 
  31.      The +9 comes from that strings of length longer than 16M require
  32.      9 bytes to be stored (see net_store_length).
  33.   */
  34.   if (packet_length+9+length > packet->alloced_length() &&
  35.       packet->realloc(packet_length+9+length))
  36.     return 1;
  37.   char *to=(char*) net_store_length((char*) packet->ptr()+packet_length,
  38.     (ulonglong) length);
  39.   memcpy(to,from,length);
  40.   packet->length((uint) (to+length-packet->ptr()));
  41.   return 0;
  42. }
  43. /* Send a error string to client */
  44. void send_error(THD *thd, uint sql_errno, const char *err)
  45. {
  46. #ifndef EMBEDDED_LIBRARY 
  47.   uint length;
  48.   char buff[MYSQL_ERRMSG_SIZE+2], *pos;
  49. #endif
  50.   const char *orig_err= err;
  51.   NET *net= &thd->net;
  52.   DBUG_ENTER("send_error");
  53.   DBUG_PRINT("enter",("sql_errno: %d  err: %s", sql_errno,
  54.       err ? err : net->last_error[0] ?
  55.       net->last_error : "NULL"));
  56. #ifndef EMBEDDED_LIBRARY  /* TODO query cache in embedded library*/
  57.   query_cache_abort(net);
  58. #endif
  59.   thd->query_error=  1; // needed to catch query errors during replication
  60.   if (!err)
  61.   {
  62.     if (sql_errno)
  63.       err=ER(sql_errno);
  64.     else
  65.     {
  66.       if ((err=net->last_error)[0])
  67. sql_errno=net->last_errno;
  68.       else
  69.       {
  70. sql_errno=ER_UNKNOWN_ERROR;
  71. err=ER(sql_errno);  /* purecov: inspected */
  72.       }
  73.     }
  74.     orig_err= err;
  75.   }
  76. #ifdef EMBEDDED_LIBRARY
  77.   net->last_errno= sql_errno;
  78.   strmake(net->last_error, err, sizeof(net->last_error)-1);
  79.   strmov(net->sqlstate, mysql_errno_to_sqlstate(sql_errno));
  80. #else
  81.   if (net->vio == 0)
  82.   {
  83.     if (thd->bootstrap)
  84.     {
  85.       /* In bootstrap it's ok to print on stderr */
  86.       fprintf(stderr,"ERROR: %d  %sn",sql_errno,err);
  87.     }
  88.     DBUG_VOID_RETURN;
  89.   }
  90.   if (net->return_errno)
  91.   { // new client code; Add errno before message
  92.     int2store(buff,sql_errno);
  93.     pos= buff+2;
  94.     if (thd->client_capabilities & CLIENT_PROTOCOL_41)
  95.     {
  96.       /* The first # is to make the protocol backward compatible */
  97.       buff[2]= '#';
  98.       pos= strmov(buff+3, mysql_errno_to_sqlstate(sql_errno));
  99.     }
  100.     length= (uint) (strmake(pos, err, MYSQL_ERRMSG_SIZE-1) - buff);
  101.     err=buff;
  102.   }
  103.   else
  104.   {
  105.     length=(uint) strlen(err);
  106.     set_if_smaller(length,MYSQL_ERRMSG_SIZE-1);
  107.   }
  108.   VOID(net_write_command(net,(uchar) 255, "", 0, (char*) err,length));
  109. #endif  /* EMBEDDED_LIBRARY*/
  110.   if (!thd->killed)
  111.     push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, sql_errno,
  112.                  orig_err ? orig_err : ER(sql_errno));
  113.   thd->is_fatal_error=0; // Error message is given
  114.   thd->net.report_error= 0;
  115.   /* Abort multi-result sets */
  116.   thd->lex->found_colon= 0;
  117.   thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
  118.   DBUG_VOID_RETURN;
  119. }
  120. /*
  121.   Send a warning to the end user
  122.   SYNOPSIS
  123.     send_warning()
  124.     thd Thread handler
  125.     sql_errno Warning number (error message)
  126.     err Error string.  If not set, use ER(sql_errno)
  127.   DESCRIPTION
  128.     Register the warning so that the user can get it with mysql_warnings()
  129.     Send an ok (+ warning count) to the end user.
  130. */
  131. void send_warning(THD *thd, uint sql_errno, const char *err)
  132. {
  133.   DBUG_ENTER("send_warning");  
  134.   push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, sql_errno,
  135.        err ? err : ER(sql_errno));
  136.   send_ok(thd);
  137.   DBUG_VOID_RETURN;
  138. }
  139. /*
  140.    Write error package and flush to client
  141.    It's a little too low level, but I don't want to use another buffer for
  142.    this
  143. */
  144. void
  145. net_printf(THD *thd, uint errcode, ...)
  146. {
  147.   va_list args;
  148.   uint length,offset;
  149.   const char *format;
  150. #ifndef EMBEDDED_LIBRARY
  151.   const char *text_pos;
  152.   int head_length= NET_HEADER_SIZE;
  153. #else
  154.   char text_pos[1024];
  155. #endif
  156.   NET *net= &thd->net;
  157.   DBUG_ENTER("net_printf");
  158.   DBUG_PRINT("enter",("message: %u",errcode));
  159.   thd->query_error=  1; // needed to catch query errors during replication
  160. #ifndef EMBEDDED_LIBRARY
  161.   query_cache_abort(net); // Safety
  162. #endif
  163.   va_start(args,errcode);
  164.   /*
  165.     The following is needed to make net_printf() work with 0 argument for
  166.     errorcode and use the argument after that as the format string. This
  167.     is useful for rare errors that are not worth the hassle to put in
  168.     errmsg.sys, but at the same time, the message is not fixed text
  169.   */
  170.   if (errcode)
  171.     format= ER(errcode);
  172.   else
  173.   {
  174.     format=va_arg(args,char*);
  175.     errcode= ER_UNKNOWN_ERROR;
  176.   }
  177.   offset= (net->return_errno ?
  178.    ((thd->client_capabilities & CLIENT_PROTOCOL_41) ?
  179.     2+SQLSTATE_LENGTH+1 : 2) : 0);
  180. #ifndef EMBEDDED_LIBRARY
  181.   text_pos=(char*) net->buff + head_length + offset + 1;
  182.   length= (uint) ((char*)net->buff_end - text_pos);
  183. #else
  184.   length=sizeof(text_pos)-1;
  185. #endif
  186.   length=my_vsnprintf(my_const_cast(char*) (text_pos),
  187.                       min(length, sizeof(net->last_error)),
  188.                       format,args);
  189.   va_end(args);
  190.   /* Replication slave relies on net->last_* to see if there was error */
  191.   net->last_errno= errcode;
  192.   strmake(net->last_error, text_pos, sizeof(net->last_error)-1);
  193. #ifndef EMBEDDED_LIBRARY
  194.   if (net->vio == 0)
  195.   {
  196.     if (thd->bootstrap)
  197.     {
  198.       /*
  199. In bootstrap it's ok to print on stderr
  200. This may also happen when we get an error from a slave thread
  201.       */
  202.       fprintf(stderr,"ERROR: %d  %sn",errcode,text_pos);
  203.       thd->fatal_error();
  204.     }
  205.     DBUG_VOID_RETURN;
  206.   }
  207.   int3store(net->buff,length+1+offset);
  208.   net->buff[3]= (net->compress) ? 0 : (uchar) (net->pkt_nr++);
  209.   net->buff[head_length]=(uchar) 255; // Error package
  210.   if (offset)
  211.   {
  212.     uchar *pos= net->buff+head_length+1;
  213.     int2store(pos, errcode);
  214.     if (thd->client_capabilities & CLIENT_PROTOCOL_41)
  215.     {
  216.       pos[2]= '#';      /* To make the protocol backward compatible */
  217.       memcpy(pos+3, mysql_errno_to_sqlstate(errcode), SQLSTATE_LENGTH);
  218.     }
  219.   }
  220.   VOID(net_real_write(net,(char*) net->buff,length+head_length+1+offset));
  221. #else
  222.   net->last_errno= errcode;
  223.   strmake(net->last_error, text_pos, length);
  224.   strmake(net->sqlstate, mysql_errno_to_sqlstate(errcode), SQLSTATE_LENGTH);
  225. #endif
  226.   if (!thd->killed)
  227.     push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, errcode,
  228.                  text_pos ? text_pos : ER(errcode));
  229.   thd->is_fatal_error=0; // Error message is given
  230.   DBUG_VOID_RETURN;
  231. }
  232. /*
  233.   Return ok to the client.
  234.   SYNOPSIS
  235.     send_ok()
  236.     thd Thread handler
  237.     affected_rows Number of rows changed by statement
  238.     id Auto_increment id for first row (if used)
  239.     message Message to send to the client (Used by mysql_status)
  240.   DESCRIPTION
  241.     The ok packet has the following structure
  242.     0 Marker (1 byte)
  243.     affected_rows Stored in 1-9 bytes
  244.     id Stored in 1-9 bytes
  245.     server_status Copy of thd->server_status;  Can be used by client
  246. to check if we are inside an transaction
  247. New in 4.0 protocol
  248.     warning_count Stored in 2 bytes; New in 4.1 protocol
  249.     message Stored as packed length (1-9 bytes) + message
  250. Is not stored if no message
  251.    If net->no_send_ok return without sending packet
  252. */    
  253. #ifndef EMBEDDED_LIBRARY
  254. void
  255. send_ok(THD *thd, ha_rows affected_rows, ulonglong id, const char *message)
  256. {
  257.   NET *net= &thd->net;
  258.   char buff[MYSQL_ERRMSG_SIZE+10],*pos;
  259.   DBUG_ENTER("send_ok");
  260.   if (net->no_send_ok || !net->vio) // hack for re-parsing queries
  261.     DBUG_VOID_RETURN;
  262.   buff[0]=0; // No fields
  263.   pos=net_store_length(buff+1,(ulonglong) affected_rows);
  264.   pos=net_store_length(pos, (ulonglong) id);
  265.   if (thd->client_capabilities & CLIENT_PROTOCOL_41)
  266.   {
  267.     DBUG_PRINT("info",
  268.        ("affected_rows: %lu  id: %lu  status: %u  warning_count: %u",
  269. (ulong) affected_rows,
  270. (ulong) id,
  271. (uint) (thd->server_status & 0xffff),
  272. (uint) thd->total_warn_count));
  273.     int2store(pos,thd->server_status);
  274.     pos+=2;
  275.     /* We can only return up to 65535 warnings in two bytes */
  276.     uint tmp= min(thd->total_warn_count, 65535);
  277.     int2store(pos, tmp);
  278.     pos+= 2;
  279.   }
  280.   else if (net->return_status) // For 4.0 protocol
  281.   {
  282.     int2store(pos,thd->server_status);
  283.     pos+=2;
  284.   }
  285.   if (message)
  286.     pos=net_store_data((char*) pos, message, strlen(message));
  287.   VOID(my_net_write(net,buff,(uint) (pos-buff)));
  288.   VOID(net_flush(net));
  289.   /* We can't anymore send an error to the client */
  290.   thd->net.report_error= 0;
  291.   DBUG_VOID_RETURN;
  292. }
  293. static char eof_buff[1]= { (char) 254 };        /* Marker for end of fields */
  294. /*
  295.   Send eof (= end of result set) to the client
  296.   SYNOPSIS
  297.     send_eof()
  298.     thd Thread handler
  299.     no_flush Set to 1 if there will be more data to the client,
  300. like in send_fields().
  301.   DESCRIPTION
  302.     The eof packet has the following structure
  303.     254 Marker (1 byte)
  304.     warning_count Stored in 2 bytes; New in 4.1 protocol
  305.     status_flag Stored in 2 bytes;
  306. For flags like SERVER_STATUS_MORE_RESULTS
  307.     Note that the warning count will not be sent if 'no_flush' is set as
  308.     we don't want to report the warning count until all data is sent to the
  309.     client.
  310. */    
  311. void
  312. send_eof(THD *thd, bool no_flush)
  313. {
  314.   NET *net= &thd->net;
  315.   DBUG_ENTER("send_eof");
  316.   if (net->vio != 0)
  317.   {
  318.     if (thd->client_capabilities & CLIENT_PROTOCOL_41)
  319.     {
  320.       uchar buff[5];
  321.       uint tmp= min(thd->total_warn_count, 65535);
  322.       buff[0]=254;
  323.       int2store(buff+1, tmp);
  324.       /*
  325. The following test should never be true, but it's better to do it
  326. because if 'is_fatal_error' is set the server is not going to execute
  327. other queries (see the if test in dispatch_command / COM_QUERY)
  328.       */
  329.       if (thd->is_fatal_error)
  330. thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
  331.       int2store(buff+3, thd->server_status);
  332.       VOID(my_net_write(net,(char*) buff,5));
  333.       VOID(net_flush(net));
  334.     }
  335.     else
  336.     {
  337.       VOID(my_net_write(net,eof_buff,1));
  338.       if (!no_flush)
  339. VOID(net_flush(net));
  340.     }
  341.   }
  342.   DBUG_VOID_RETURN;
  343. }
  344. /*
  345.     Please client to send scrambled_password in old format.
  346.   SYNOPSYS
  347.     send_old_password_request()
  348.     thd thread handle
  349.      
  350.   RETURN VALUE
  351.     0  ok
  352.    !0  error
  353. */
  354. bool send_old_password_request(THD *thd)
  355. {
  356.   NET *net= &thd->net;
  357.   return my_net_write(net, eof_buff, 1) || net_flush(net);
  358. }
  359. #endif /* EMBEDDED_LIBRARY */
  360. /*
  361.   Faster net_store_length when we know that length is less than 65536.
  362.   We keep a separate version for that range because it's widely used in
  363.   libmysql.
  364.   uint is used as agrument type because of MySQL type conventions:
  365.   uint for 0..65536
  366.   ulong for 0..4294967296
  367.   ulonglong for bigger numbers.
  368. */
  369. char *net_store_length(char *pkg, uint length)
  370. {
  371.   uchar *packet=(uchar*) pkg;
  372.   if (length < 251)
  373.   {
  374.     *packet=(uchar) length;
  375.     return (char*) packet+1;
  376.   }
  377.   *packet++=252;
  378.   int2store(packet,(uint) length);
  379.   return (char*) packet+2;
  380. }
  381. /****************************************************************************
  382.   Functions used by the protocol functions (like send_ok) to store strings
  383.   and numbers in the header result packet.
  384. ****************************************************************************/
  385. /* The following will only be used for short strings < 65K */
  386. char *net_store_data(char *to,const char *from, uint length)
  387. {
  388.   to=net_store_length(to,length);
  389.   memcpy(to,from,length);
  390.   return to+length;
  391. }
  392. char *net_store_data(char *to,int32 from)
  393. {
  394.   char buff[20];
  395.   uint length=(uint) (int10_to_str(from,buff,10)-buff);
  396.   to=net_store_length(to,length);
  397.   memcpy(to,buff,length);
  398.   return to+length;
  399. }
  400. char *net_store_data(char *to,longlong from)
  401. {
  402.   char buff[22];
  403.   uint length=(uint) (longlong10_to_str(from,buff,10)-buff);
  404.   to=net_store_length(to,length);
  405.   memcpy(to,buff,length);
  406.   return to+length;
  407. }
  408. /*****************************************************************************
  409.   Default Protocol functions
  410. *****************************************************************************/
  411. void Protocol::init(THD *thd_arg)
  412. {
  413.   thd=thd_arg;
  414.   packet= &thd->packet;
  415.   convert= &thd->convert_buffer;
  416. #ifndef DEBUG_OFF
  417.   field_types= 0;
  418. #endif
  419. }
  420. bool Protocol::flush()
  421. {
  422. #ifndef EMBEDDED_LIBRARY
  423.   return net_flush(&thd->net);
  424. #else
  425.   return 0;
  426. #endif
  427. }
  428. /*
  429.   Send name and type of result to client.
  430.   SYNOPSIS
  431.     send_fields()
  432.     THD Thread data object
  433.     list List of items to send to client
  434.     flag Bit mask with the following functions:
  435. 1 send number of rows
  436. 2 send default values
  437.   DESCRIPTION
  438.     Sum fields has table name empty and field_name.
  439.   RETURN VALUES
  440.     0 ok
  441.     1 Error  (Note that in this case the error is not sent to the client)
  442. */
  443. #ifndef EMBEDDED_LIBRARY
  444. bool Protocol::send_fields(List<Item> *list, uint flag)
  445. {
  446.   List_iterator_fast<Item> it(*list);
  447.   Item *item;
  448.   char buff[80];
  449.   String tmp((char*) buff,sizeof(buff),&my_charset_bin);
  450.   Protocol_simple prot(thd);
  451.   String *local_packet= prot.storage_packet();
  452.   CHARSET_INFO *thd_charset= thd->variables.character_set_results;
  453.   DBUG_ENTER("send_fields");
  454.   if (flag & 1)
  455.   { // Packet with number of elements
  456.     char *pos=net_store_length(buff, (uint) list->elements);
  457.     (void) my_net_write(&thd->net, buff,(uint) (pos-buff));
  458.   }
  459. #ifndef DEBUG_OFF
  460.   field_types= (enum_field_types*) thd->alloc(sizeof(field_types) *
  461.       list->elements);
  462.   uint count= 0;
  463. #endif
  464.   while ((item=it++))
  465.   {
  466.     char *pos;
  467.     CHARSET_INFO *cs= system_charset_info;
  468.     Send_field field;
  469.     item->make_field(&field);
  470.     prot.prepare_for_resend();
  471.     if (thd->client_capabilities & CLIENT_PROTOCOL_41)
  472.     {
  473.       if (prot.store("def", 3, cs, thd_charset) ||
  474.   prot.store(field.db_name, (uint) strlen(field.db_name),
  475.      cs, thd_charset) ||
  476.   prot.store(field.table_name, (uint) strlen(field.table_name),
  477.      cs, thd_charset) ||
  478.   prot.store(field.org_table_name, (uint) strlen(field.org_table_name),
  479.      cs, thd_charset) ||
  480.   prot.store(field.col_name, (uint) strlen(field.col_name),
  481.      cs, thd_charset) ||
  482.   prot.store(field.org_col_name, (uint) strlen(field.org_col_name),
  483.      cs, thd_charset) ||
  484.   local_packet->realloc(local_packet->length()+12))
  485. goto err;
  486.       /* Store fixed length fields */
  487.       pos= (char*) local_packet->ptr()+local_packet->length();
  488.       *pos++= 12; // Length of packed fields
  489.       if (item->collation.collation == &my_charset_bin || thd_charset == NULL)
  490.       {
  491.         /* No conversion */
  492.         int2store(pos, field.charsetnr);
  493.         int4store(pos+2, field.length);
  494.       }
  495.       else
  496.       {
  497.         /* With conversion */
  498.         int2store(pos, thd_charset->number);
  499.         uint char_len= field.length / item->collation.collation->mbmaxlen;
  500.         int4store(pos+2, char_len * thd_charset->mbmaxlen);
  501.       }
  502.       pos[6]= field.type;
  503.       int2store(pos+7,field.flags);
  504.       pos[9]= (char) field.decimals;
  505.       pos[10]= 0; // For the future
  506.       pos[11]= 0; // For the future
  507.       pos+= 12;
  508.     }
  509.     else
  510.     {
  511.       if (prot.store(field.table_name, (uint) strlen(field.table_name),
  512.      cs, thd_charset) ||
  513.   prot.store(field.col_name, (uint) strlen(field.col_name),
  514.      cs, thd_charset) ||
  515.   local_packet->realloc(local_packet->length()+10))
  516. goto err;
  517.       pos= (char*) local_packet->ptr()+local_packet->length();
  518. #ifdef TO_BE_DELETED_IN_6
  519.       if (!(thd->client_capabilities & CLIENT_LONG_FLAG))
  520.       {
  521. pos[0]=3;
  522. int3store(pos+1,field.length);
  523. pos[4]=1;
  524. pos[5]=field.type;
  525. pos[6]=2;
  526. pos[7]= (char) field.flags;
  527. pos[8]= (char) field.decimals;
  528. pos+= 9;
  529.       }
  530.       else
  531. #endif
  532.       {
  533. pos[0]=3;
  534. int3store(pos+1,field.length);
  535. pos[4]=1;
  536. pos[5]=field.type;
  537. pos[6]=3;
  538. int2store(pos+7,field.flags);
  539. pos[9]= (char) field.decimals;
  540. pos+= 10;
  541.       }
  542.     }
  543.     local_packet->length((uint) (pos - local_packet->ptr()));
  544.     if (flag & 2)
  545.       item->send(&prot, &tmp); // Send default value
  546.     if (prot.write())
  547.       break; /* purecov: inspected */
  548. #ifndef DEBUG_OFF
  549.     field_types[count++]= field.type;
  550. #endif
  551.   }
  552.   my_net_write(&thd->net, eof_buff, 1);
  553.   DBUG_RETURN(prepare_for_send(list));
  554. err:
  555.   send_error(thd,ER_OUT_OF_RESOURCES); /* purecov: inspected */
  556.   DBUG_RETURN(1); /* purecov: inspected */
  557. }
  558. bool Protocol::send_records_num(List<Item> *list, ulonglong records)
  559. {
  560.   char *pos;
  561.   char buff[20];
  562.   pos=net_store_length(buff, (uint) list->elements);
  563.   pos=net_store_length(pos, records);
  564.   return my_net_write(&thd->net, buff,(uint) (pos-buff));
  565. }
  566. bool Protocol::write()
  567. {
  568.   DBUG_ENTER("Protocol::write");
  569.   DBUG_RETURN(my_net_write(&thd->net, packet->ptr(), packet->length()));
  570. }
  571. #endif /* EMBEDDED_LIBRARY */
  572. /*
  573.   Send  end terminated string
  574.   SYNOPSIS
  575.     store()
  576.     from NullS or  terminated string
  577.   NOTES
  578.     In most cases one should use store(from, length) instead of this function
  579.   RETURN VALUES
  580.     0 ok
  581.     1 error
  582. */
  583. bool Protocol::store(const char *from, CHARSET_INFO *cs)
  584. {
  585.   if (!from)
  586.     return store_null();
  587.   uint length= strlen(from);
  588.   return store(from, length, cs);
  589. }
  590. /*
  591.   Send a set of strings as one long string with ',' in between
  592. */
  593. bool Protocol::store(I_List<i_string>* str_list)
  594. {
  595.   char buf[256];
  596.   String tmp(buf, sizeof(buf), &my_charset_bin);
  597.   uint32 len;
  598.   I_List_iterator<i_string> it(*str_list);
  599.   i_string* s;
  600.   tmp.length(0);
  601.   while ((s=it++))
  602.   {
  603.     tmp.append(s->ptr);
  604.     tmp.append(',');
  605.   }
  606.   if ((len= tmp.length()))
  607.     len--; // Remove last ','
  608.   return store((char*) tmp.ptr(), len,  tmp.charset());
  609. }
  610. /****************************************************************************
  611.   Functions to handle the simple (default) protocol where everything is
  612.   This protocol is the one that is used by default between the MySQL server
  613.   and client when you are not using prepared statements.
  614.   All data are sent as 'packed-string-length' followed by 'string-data'
  615. ****************************************************************************/
  616. #ifndef EMBEDDED_LIBRARY
  617. void Protocol_simple::prepare_for_resend()
  618. {
  619.   packet->length(0);
  620. #ifndef DEBUG_OFF
  621.   field_pos= 0;
  622. #endif
  623. }
  624. bool Protocol_simple::store_null()
  625. {
  626. #ifndef DEBUG_OFF
  627.   field_pos++;
  628. #endif
  629.   char buff[1];
  630.   buff[0]= (char)251;
  631.   return packet->append(buff, sizeof(buff), PACKET_BUFFER_EXTRA_ALLOC);
  632. }
  633. #endif
  634. /*
  635.   Auxilary function to convert string to the given character set
  636.   and store in network buffer.
  637. */
  638. bool Protocol::store_string_aux(const char *from, uint length,
  639.                                 CHARSET_INFO *fromcs, CHARSET_INFO *tocs)
  640. {
  641.   /* 'tocs' is set 0 when client issues SET character_set_results=NULL */
  642.   if (tocs && !my_charset_same(fromcs, tocs) &&
  643.       fromcs != &my_charset_bin &&
  644.       tocs != &my_charset_bin)
  645.   {
  646.     uint dummy_errors;
  647.     return convert->copy(from, length, fromcs, tocs, &dummy_errors) ||
  648.            net_store_data(convert->ptr(), convert->length());
  649.   }
  650.   return net_store_data(from, length);
  651. }
  652. bool Protocol_simple::store(const char *from, uint length,
  653.     CHARSET_INFO *fromcs, CHARSET_INFO *tocs)
  654. {
  655. #ifndef DEBUG_OFF
  656.   DBUG_ASSERT(field_types == 0 ||
  657.       field_types[field_pos] == MYSQL_TYPE_DECIMAL ||
  658.       (field_types[field_pos] >= MYSQL_TYPE_ENUM &&
  659.        field_types[field_pos] <= MYSQL_TYPE_GEOMETRY));
  660.   field_pos++;
  661. #endif
  662.   return store_string_aux(from, length, fromcs, tocs);
  663. }
  664. bool Protocol_simple::store(const char *from, uint length,
  665.     CHARSET_INFO *fromcs)
  666. {
  667.   CHARSET_INFO *tocs= this->thd->variables.character_set_results;
  668. #ifndef DEBUG_OFF
  669.   DBUG_ASSERT(field_types == 0 ||
  670.       field_types[field_pos] == MYSQL_TYPE_DECIMAL ||
  671.       (field_types[field_pos] >= MYSQL_TYPE_ENUM &&
  672.        field_types[field_pos] <= MYSQL_TYPE_GEOMETRY));
  673.   field_pos++;
  674. #endif
  675.   return store_string_aux(from, length, fromcs, tocs);
  676. }
  677. bool Protocol_simple::store_tiny(longlong from)
  678. {
  679. #ifndef DEBUG_OFF
  680.   DBUG_ASSERT(field_types == 0 || field_types[field_pos] == MYSQL_TYPE_TINY);
  681.   field_pos++;
  682. #endif
  683.   char buff[20];
  684.   return net_store_data((char*) buff,
  685. (uint) (int10_to_str((int) from,buff, -10)-buff));
  686. }
  687. bool Protocol_simple::store_short(longlong from)
  688. {
  689. #ifndef DEBUG_OFF
  690.   DBUG_ASSERT(field_types == 0 ||
  691.       field_types[field_pos] == MYSQL_TYPE_SHORT);
  692.   field_pos++;
  693. #endif
  694.   char buff[20];
  695.   return net_store_data((char*) buff,
  696. (uint) (int10_to_str((int) from,buff, -10)-buff));
  697. }
  698. bool Protocol_simple::store_long(longlong from)
  699. {
  700. #ifndef DEBUG_OFF
  701.   DBUG_ASSERT(field_types == 0 ||
  702.               field_types[field_pos] == MYSQL_TYPE_INT24 ||
  703.               field_types[field_pos] == MYSQL_TYPE_LONG);
  704.   field_pos++;
  705. #endif
  706.   char buff[20];
  707.   return net_store_data((char*) buff,
  708. (uint) (int10_to_str((long int)from,buff, (from <0)?-10:10)-buff));
  709. }
  710. bool Protocol_simple::store_longlong(longlong from, bool unsigned_flag)
  711. {
  712. #ifndef DEBUG_OFF
  713.   DBUG_ASSERT(field_types == 0 ||
  714.       field_types[field_pos] == MYSQL_TYPE_LONGLONG);
  715.   field_pos++;
  716. #endif
  717.   char buff[22];
  718.   return net_store_data((char*) buff,
  719. (uint) (longlong10_to_str(from,buff,
  720.   unsigned_flag ? 10 : -10)-
  721. buff));
  722. }
  723. bool Protocol_simple::store(float from, uint32 decimals, String *buffer)
  724. {
  725. #ifndef DEBUG_OFF
  726.   DBUG_ASSERT(field_types == 0 ||
  727.       field_types[field_pos] == MYSQL_TYPE_FLOAT);
  728.   field_pos++;
  729. #endif
  730.   buffer->set((double) from, decimals, thd->charset());
  731.   return net_store_data((char*) buffer->ptr(), buffer->length());
  732. }
  733. bool Protocol_simple::store(double from, uint32 decimals, String *buffer)
  734. {
  735. #ifndef DEBUG_OFF
  736.   DBUG_ASSERT(field_types == 0 ||
  737.       field_types[field_pos] == MYSQL_TYPE_DOUBLE);
  738.   field_pos++;
  739. #endif
  740.   buffer->set(from, decimals, thd->charset());
  741.   return net_store_data((char*) buffer->ptr(), buffer->length());
  742. }
  743. bool Protocol_simple::store(Field *field)
  744. {
  745.   if (field->is_null())
  746.     return store_null();
  747. #ifndef DEBUG_OFF
  748.   field_pos++;
  749. #endif
  750.   char buff[MAX_FIELD_WIDTH];
  751.   String str(buff,sizeof(buff), &my_charset_bin);
  752.   CHARSET_INFO *tocs= this->thd->variables.character_set_results;
  753.   field->val_str(&str);
  754.   return store_string_aux(str.ptr(), str.length(), str.charset(), tocs);
  755. }
  756. /*
  757.    TODO:
  758.         Second_part format ("%06") needs to change when 
  759.         we support 0-6 decimals for time.
  760. */
  761. bool Protocol_simple::store(TIME *tm)
  762. {
  763. #ifndef DEBUG_OFF
  764.   DBUG_ASSERT(field_types == 0 ||
  765.       field_types[field_pos] == MYSQL_TYPE_DATETIME ||
  766.       field_types[field_pos] == MYSQL_TYPE_TIMESTAMP);
  767.   field_pos++;
  768. #endif
  769.   char buff[40];
  770.   uint length;
  771.   length= my_sprintf(buff,(buff, "%04d-%02d-%02d %02d:%02d:%02d",
  772.    (int) tm->year,
  773.    (int) tm->month,
  774.    (int) tm->day,
  775.    (int) tm->hour,
  776.    (int) tm->minute,
  777.    (int) tm->second));
  778.   if (tm->second_part)
  779.     length+= my_sprintf(buff+length,(buff+length, ".%06d", (int)tm->second_part));
  780.   return net_store_data((char*) buff, length);
  781. }
  782. bool Protocol_simple::store_date(TIME *tm)
  783. {
  784. #ifndef DEBUG_OFF
  785.   DBUG_ASSERT(field_types == 0 ||
  786.       field_types[field_pos] == MYSQL_TYPE_DATE);
  787.   field_pos++;
  788. #endif
  789.   char buff[MAX_DATE_STRING_REP_LENGTH];
  790.   int length= my_date_to_str(tm, buff);
  791.   return net_store_data(buff, (uint) length);
  792. }
  793. /*
  794.    TODO:
  795.         Second_part format ("%06") needs to change when 
  796.         we support 0-6 decimals for time.
  797. */
  798. bool Protocol_simple::store_time(TIME *tm)
  799. {
  800. #ifndef DEBUG_OFF
  801.   DBUG_ASSERT(field_types == 0 ||
  802.       field_types[field_pos] == MYSQL_TYPE_TIME);
  803.   field_pos++;
  804. #endif
  805.   char buff[40];
  806.   uint length;
  807.   uint day= (tm->year || tm->month) ? 0 : tm->day;
  808.   length= my_sprintf(buff,(buff, "%s%02ld:%02d:%02d",
  809.    tm->neg ? "-" : "",
  810.    (long) day*24L+(long) tm->hour,
  811.    (int) tm->minute,
  812.    (int) tm->second));
  813.   if (tm->second_part)
  814.     length+= my_sprintf(buff+length,(buff+length, ".%06d", (int)tm->second_part));
  815.   return net_store_data((char*) buff, length);
  816. }
  817. /****************************************************************************
  818.   Functions to handle the binary protocol used with prepared statements
  819.   Data format:
  820.    [ok:1]                            reserved ok packet
  821.    [null_field:(field_count+7+2)/8]  reserved to send null data. The size is
  822.                                      calculated using:
  823.                                      bit_fields= (field_count+7+2)/8; 
  824.                                      2 bits are reserved for identifying type
  825.      of package.
  826.    [[length]data]                    data field (the length applies only for 
  827.                                      string/binary/time/timestamp fields and 
  828.                                      rest of them are not sent as they have 
  829.                                      the default length that client understands
  830.                                      based on the field type
  831.    [..]..[[length]data]              data
  832. ****************************************************************************/
  833. bool Protocol_prep::prepare_for_send(List<Item> *item_list)
  834. {
  835.   Protocol::prepare_for_send(item_list);
  836.   bit_fields= (field_count+9)/8;
  837.   if (packet->alloc(bit_fields+1))
  838.     return 1;
  839.   /* prepare_for_resend will be called after this one */
  840.   return 0;
  841. }
  842. void Protocol_prep::prepare_for_resend()
  843. {
  844.   packet->length(bit_fields+1);
  845.   bzero((char*) packet->ptr(), 1+bit_fields);
  846.   field_pos=0;
  847. }
  848. bool Protocol_prep::store(const char *from, uint length, CHARSET_INFO *fromcs)
  849. {
  850.   CHARSET_INFO *tocs= thd->variables.character_set_results;
  851. #ifndef DEBUG_OFF
  852.   DBUG_ASSERT(field_types == 0 ||
  853.       field_types[field_pos] == MYSQL_TYPE_DECIMAL ||
  854.       (field_types[field_pos] >= MYSQL_TYPE_ENUM &&
  855.        field_types[field_pos] <= MYSQL_TYPE_GEOMETRY));
  856. #endif
  857.   field_pos++;
  858.   return store_string_aux(from, length, fromcs, tocs);
  859. }
  860. bool Protocol_prep::store(const char *from,uint length,
  861.   CHARSET_INFO *fromcs, CHARSET_INFO *tocs)
  862. {
  863. #ifndef DEBUG_OFF
  864.   DBUG_ASSERT(field_types == 0 ||
  865.       field_types[field_pos] == MYSQL_TYPE_DECIMAL ||
  866.       (field_types[field_pos] >= MYSQL_TYPE_ENUM &&
  867.        field_types[field_pos] <= MYSQL_TYPE_GEOMETRY));
  868. #endif
  869.   field_pos++;
  870.   return store_string_aux(from, length, fromcs, tocs);
  871. }
  872. bool Protocol_prep::store_null()
  873. {
  874.   uint offset= (field_pos+2)/8+1, bit= (1 << ((field_pos+2) & 7));
  875.   /* Room for this as it's allocated in prepare_for_send */
  876.   char *to= (char*) packet->ptr()+offset;
  877.   *to= (char) ((uchar) *to | (uchar) bit);
  878.   field_pos++;
  879.   return 0;
  880. }
  881. bool Protocol_prep::store_tiny(longlong from)
  882. {
  883. #ifndef DEBUG_OFF
  884.   DBUG_ASSERT(field_types == 0 ||
  885.       field_types[field_pos] == MYSQL_TYPE_TINY);
  886. #endif
  887.   char buff[1];
  888.   field_pos++;
  889.   buff[0]= (uchar) from;
  890.   return packet->append(buff, sizeof(buff), PACKET_BUFFER_EXTRA_ALLOC);
  891. }
  892. bool Protocol_prep::store_short(longlong from)
  893. {
  894. #ifndef DEBUG_OFF
  895.   DBUG_ASSERT(field_types == 0 ||
  896.         field_types[field_pos] == MYSQL_TYPE_SHORT ||
  897.         field_types[field_pos] == MYSQL_TYPE_YEAR);
  898. #endif
  899.   field_pos++;
  900.   char *to= packet->prep_append(2, PACKET_BUFFER_EXTRA_ALLOC);
  901.   if (!to)
  902.     return 1;
  903.   int2store(to, (int) from);
  904.   return 0;
  905. }
  906. bool Protocol_prep::store_long(longlong from)
  907. {
  908. #ifndef DEBUG_OFF
  909.   DBUG_ASSERT(field_types == 0 ||
  910.       field_types[field_pos] == MYSQL_TYPE_INT24 ||
  911.       field_types[field_pos] == MYSQL_TYPE_LONG);
  912. #endif
  913.   field_pos++;
  914.   char *to= packet->prep_append(4, PACKET_BUFFER_EXTRA_ALLOC);
  915.   if (!to)
  916.     return 1;
  917.   int4store(to, from);
  918.   return 0;
  919. }
  920. bool Protocol_prep::store_longlong(longlong from, bool unsigned_flag)
  921. {
  922. #ifndef DEBUG_OFF
  923.   DBUG_ASSERT(field_types == 0 ||
  924.       field_types[field_pos] == MYSQL_TYPE_LONGLONG);
  925. #endif
  926.   field_pos++;
  927.   char *to= packet->prep_append(8, PACKET_BUFFER_EXTRA_ALLOC);
  928.   if (!to)
  929.     return 1;
  930.   int8store(to, from);
  931.   return 0;
  932. }
  933. bool Protocol_prep::store(float from, uint32 decimals, String *buffer)
  934. {
  935. #ifndef DEBUG_OFF
  936.   DBUG_ASSERT(field_types == 0 ||
  937.       field_types[field_pos] == MYSQL_TYPE_FLOAT);
  938. #endif
  939.   field_pos++;
  940.   char *to= packet->prep_append(4, PACKET_BUFFER_EXTRA_ALLOC);
  941.   if (!to)
  942.     return 1;
  943.   float4store(to, from);
  944.   return 0;
  945. }
  946. bool Protocol_prep::store(double from, uint32 decimals, String *buffer)
  947. {
  948. #ifndef DEBUG_OFF
  949.   DBUG_ASSERT(field_types == 0 ||
  950.       field_types[field_pos] == MYSQL_TYPE_DOUBLE);
  951. #endif
  952.   field_pos++;
  953.   char *to= packet->prep_append(8, PACKET_BUFFER_EXTRA_ALLOC);
  954.   if (!to)
  955.     return 1;
  956.   float8store(to, from);
  957.   return 0;
  958. }
  959. bool Protocol_prep::store(Field *field)
  960. {
  961.   /*
  962.     We should not increment field_pos here as send_binary() will call another
  963.     protocol function to do this for us
  964.   */
  965.   if (field->is_null())
  966.     return store_null();
  967.   return field->send_binary(this);
  968. }
  969. bool Protocol_prep::store(TIME *tm)
  970. {
  971. #ifndef DEBUG_OFF
  972.   DBUG_ASSERT(field_types == 0 ||
  973.       field_types[field_pos] == MYSQL_TYPE_DATETIME ||
  974.       field_types[field_pos] == MYSQL_TYPE_DATE ||
  975.       field_types[field_pos] == MYSQL_TYPE_TIMESTAMP);
  976. #endif
  977.   char buff[12],*pos;
  978.   uint length;
  979.   field_pos++;
  980.   pos= buff+1;
  981.   int2store(pos, tm->year);
  982.   pos[2]= (uchar) tm->month;
  983.   pos[3]= (uchar) tm->day;
  984.   pos[4]= (uchar) tm->hour;
  985.   pos[5]= (uchar) tm->minute;
  986.   pos[6]= (uchar) tm->second;
  987.   int4store(pos+7, tm->second_part);
  988.   if (tm->second_part)
  989.     length=11;
  990.   else if (tm->hour || tm->minute || tm->second)
  991.     length=7;
  992.   else if (tm->year || tm->month || tm->day)
  993.     length=4;
  994.   else
  995.     length=0;
  996.   buff[0]=(char) length; // Length is stored first
  997.   return packet->append(buff, length+1, PACKET_BUFFER_EXTRA_ALLOC);
  998. }
  999. bool Protocol_prep::store_date(TIME *tm)
  1000. {
  1001.   tm->hour= tm->minute= tm->second=0;
  1002.   tm->second_part= 0;
  1003.   return Protocol_prep::store(tm);
  1004. }
  1005. bool Protocol_prep::store_time(TIME *tm)
  1006. {
  1007. #ifndef DEBUG_OFF
  1008.   DBUG_ASSERT(field_types == 0 ||
  1009.       field_types[field_pos] == MYSQL_TYPE_TIME);
  1010. #endif
  1011.   char buff[13], *pos;
  1012.   uint length;
  1013.   field_pos++;
  1014.   pos= buff+1;
  1015.   pos[0]= tm->neg ? 1 : 0;
  1016.   if (tm->hour >= 24)
  1017.   {
  1018.     /* Fix if we come from Item::send */
  1019.     uint days= tm->hour/24;
  1020.     tm->hour-= days*24;
  1021.     tm->day+= days;
  1022.   }
  1023.   int4store(pos+1, tm->day);
  1024.   pos[5]= (uchar) tm->hour;
  1025.   pos[6]= (uchar) tm->minute;
  1026.   pos[7]= (uchar) tm->second;
  1027.   int4store(pos+8, tm->second_part);
  1028.   if (tm->second_part)
  1029.     length=12;
  1030.   else if (tm->hour || tm->minute || tm->second || tm->day)
  1031.     length=8;
  1032.   else
  1033.     length=0;
  1034.   buff[0]=(char) length; // Length is stored first
  1035.   return packet->append(buff, length+1, PACKET_BUFFER_EXTRA_ALLOC);
  1036. }
  1037. #ifdef EMBEDDED_LIBRARY
  1038. /* Should be removed when we define the Protocol_cursor's future */
  1039. bool Protocol_cursor::write()
  1040. {
  1041.   return Protocol_simple::write();
  1042. }
  1043. #endif