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

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. #include "mysql_priv.h"
  14. #include "sql_repl.h"
  15. #include "repl_failsafe.h"
  16. #include <m_ctype.h>
  17. #include <myisam.h>
  18. #include <my_dir.h>
  19. #ifdef HAVE_INNOBASE_DB
  20. #include "ha_innodb.h"
  21. #endif
  22. #ifdef HAVE_NDBCLUSTER_DB
  23. #include "ha_ndbcluster.h"
  24. #endif
  25. #ifdef HAVE_OPENSSL
  26. /*
  27.   Without SSL the handshake consists of one packet. This packet
  28.   has both client capabilites and scrambled password.
  29.   With SSL the handshake might consist of two packets. If the first
  30.   packet (client capabilities) has CLIENT_SSL flag set, we have to
  31.   switch to SSL and read the second packet. The scrambled password
  32.   is in the second packet and client_capabilites field will be ignored.
  33.   Maybe it is better to accept flags other than CLIENT_SSL from the
  34.   second packet?
  35. */
  36. #define SSL_HANDSHAKE_SIZE      2
  37. #define NORMAL_HANDSHAKE_SIZE   6
  38. #define MIN_HANDSHAKE_SIZE      2
  39. #else
  40. #define MIN_HANDSHAKE_SIZE      6
  41. #endif /* HAVE_OPENSSL */
  42. #ifdef SOLARIS
  43. extern "C" int gethostname(char *name, int namelen);
  44. #endif
  45. static void time_out_user_resource_limits(THD *thd, USER_CONN *uc);
  46. #ifndef NO_EMBEDDED_ACCESS_CHECKS
  47. static int check_for_max_user_connections(THD *thd, USER_CONN *uc);
  48. #endif
  49. static void decrease_user_connections(USER_CONN *uc);
  50. static bool check_db_used(THD *thd,TABLE_LIST *tables);
  51. static bool check_multi_update_lock(THD *thd, TABLE_LIST *tables, 
  52.     List<Item> *fields, SELECT_LEX *select_lex);
  53. static void remove_escape(char *name);
  54. static void refresh_status(void);
  55. static bool append_file_to_dir(THD *thd, const char **filename_ptr,
  56.        const char *table_name);
  57.              
  58. static TABLE_LIST* get_table_by_alias(TABLE_LIST* tl, const char* db,
  59.   const char* alias);      
  60. const char *any_db="*any*"; // Special symbol for check_access
  61. const char *command_name[]={
  62.   "Sleep", "Quit", "Init DB", "Query", "Field List", "Create DB",
  63.   "Drop DB", "Refresh", "Shutdown", "Statistics", "Processlist",
  64.   "Connect","Kill","Debug","Ping","Time","Delayed insert","Change user",
  65.   "Binlog Dump","Table Dump",  "Connect Out", "Register Slave",
  66.   "Prepare", "Execute", "Long Data", "Close stmt",
  67.   "Reset stmt", "Set option",
  68.   "Error" // Last command number
  69. };
  70. static char empty_c_string[1]= {0}; // Used for not defined 'db'
  71. #ifdef __WIN__
  72. static void  test_signal(int sig_ptr)
  73. {
  74. #if !defined( DBUG_OFF)
  75.   MessageBox(NULL,"Test signal","DBUG",MB_OK);
  76. #endif
  77. #if defined(OS2)
  78.   fprintf(stderr, "Test signal %dn", sig_ptr);
  79.   fflush(stderr);
  80. #endif
  81. }
  82. static void init_signals(void)
  83. {
  84.   int signals[7] = {SIGINT,SIGILL,SIGFPE,SIGSEGV,SIGTERM,SIGBREAK,SIGABRT } ;
  85.   for (int i=0 ; i < 7 ; i++)
  86.     signal( signals[i], test_signal) ;
  87. }
  88. #endif
  89. static void unlock_locked_tables(THD *thd)
  90. {
  91.   if (thd->locked_tables)
  92.   {
  93.     thd->lock=thd->locked_tables;
  94.     thd->locked_tables=0; // Will be automaticly closed
  95.     close_thread_tables(thd); // Free tables
  96.   }
  97. }
  98. static bool end_active_trans(THD *thd)
  99. {
  100.   int error=0;
  101.   if (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN |
  102.       OPTION_TABLE_LOCK))
  103.   {
  104.     thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE);
  105.     thd->server_status&= ~SERVER_STATUS_IN_TRANS;
  106.     if (ha_commit(thd))
  107.       error=1;
  108.   }
  109.   return error;
  110. }
  111. #ifdef HAVE_REPLICATION
  112. /*
  113.   Returns true if all tables should be ignored
  114. */
  115. inline bool all_tables_not_ok(THD *thd, TABLE_LIST *tables)
  116. {
  117.   return (table_rules_on && tables && !tables_ok(thd,tables));
  118. }
  119. #endif
  120. static HASH hash_user_connections;
  121. static int get_or_create_user_conn(THD *thd, const char *user,
  122.    const char *host,
  123.    USER_RESOURCES *mqh)
  124. {
  125.   int return_val= 0;
  126.   uint temp_len, user_len;
  127.   char temp_user[USERNAME_LENGTH+HOSTNAME_LENGTH+2];
  128.   struct  user_conn *uc;
  129.   DBUG_ASSERT(user != 0);
  130.   DBUG_ASSERT(host != 0);
  131.   user_len= strlen(user);
  132.   temp_len= (strmov(strmov(temp_user, user)+1, host) - temp_user)+1;
  133.   (void) pthread_mutex_lock(&LOCK_user_conn);
  134.   if (!(uc = (struct  user_conn *) hash_search(&hash_user_connections,
  135.        (byte*) temp_user, temp_len)))
  136.   {
  137.     /* First connection for user; Create a user connection object */
  138.     if (!(uc= ((struct user_conn*)
  139.        my_malloc(sizeof(struct user_conn) + temp_len+1,
  140.  MYF(MY_WME)))))
  141.     {
  142.       send_error(thd, 0, NullS); // Out of memory
  143.       return_val= 1;
  144.       goto end;
  145.     }
  146.     uc->user=(char*) (uc+1);
  147.     memcpy(uc->user,temp_user,temp_len+1);
  148.     uc->user_len= user_len;
  149.     uc->host= uc->user + uc->user_len +  1;
  150.     uc->len= temp_len;
  151.     uc->connections= 0;
  152.     uc->questions= uc->updates= uc->conn_per_hour=0;
  153.     uc->user_resources= *mqh;
  154.     uc->intime= thd->thr_create_time;
  155.     if (my_hash_insert(&hash_user_connections, (byte*) uc))
  156.     {
  157.       my_free((char*) uc,0);
  158.       send_error(thd, 0, NullS); // Out of memory
  159.       return_val= 1;
  160.       goto end;
  161.     }
  162.   }
  163.   thd->user_connect=uc;
  164.   uc->connections++;
  165. end:
  166.   (void) pthread_mutex_unlock(&LOCK_user_conn);
  167.   return return_val;
  168. }
  169. /*
  170.     Check if user exist and password supplied is correct. 
  171.   SYNOPSIS
  172.     check_user()
  173.     thd          thread handle, thd->{host,user,ip} are used
  174.     command      originator of the check: now check_user is called
  175.                  during connect and change user procedures; used for 
  176.                  logging.
  177.     passwd       scrambled password recieved from client
  178.     passwd_len   length of scrambled password
  179.     db           database name to connect to, may be NULL
  180.     check_count  dont know exactly
  181.     Note, that host, user and passwd may point to communication buffer.
  182.     Current implementation does not depened on that, but future changes
  183.     should be done with this in mind; 'thd' is INOUT, all other params
  184.     are 'IN'.
  185.   RETURN VALUE
  186.     0  OK; thd->user, thd->master_access, thd->priv_user, thd->db and
  187.        thd->db_access are updated; OK is sent to client;
  188.    -1  access denied or handshake error; error is sent to client;
  189.    >0  error, not sent to client
  190. */
  191. int check_user(THD *thd, enum enum_server_command command, 
  192.        const char *passwd, uint passwd_len, const char *db,
  193.        bool check_count)
  194. {
  195.   DBUG_ENTER("check_user");
  196.   
  197. #ifdef NO_EMBEDDED_ACCESS_CHECKS
  198.   thd->master_access= GLOBAL_ACLS; // Full rights
  199.   /* Change database if necessary: OK or FAIL is sent in mysql_change_db */
  200.   if (db && db[0])
  201.   {
  202.     thd->db= 0;
  203.     thd->db_length= 0;
  204.     if (mysql_change_db(thd, db))
  205.     {
  206.       if (thd->user_connect)
  207. decrease_user_connections(thd->user_connect);
  208.       DBUG_RETURN(-1);
  209.     }
  210.   }
  211.   else
  212.     send_ok(thd);
  213.   DBUG_RETURN(0);
  214. #else
  215.   my_bool opt_secure_auth_local;
  216.   pthread_mutex_lock(&LOCK_global_system_variables);
  217.   opt_secure_auth_local= opt_secure_auth;
  218.   pthread_mutex_unlock(&LOCK_global_system_variables);
  219.   
  220.   /*
  221.     If the server is running in secure auth mode, short scrambles are 
  222.     forbidden.
  223.   */
  224.   if (opt_secure_auth_local && passwd_len == SCRAMBLE_LENGTH_323)
  225.   {
  226.     net_printf(thd, ER_NOT_SUPPORTED_AUTH_MODE);
  227.     mysql_log.write(thd, COM_CONNECT, ER(ER_NOT_SUPPORTED_AUTH_MODE));
  228.     DBUG_RETURN(-1);
  229.   }
  230.   if (passwd_len != 0 &&
  231.       passwd_len != SCRAMBLE_LENGTH &&
  232.       passwd_len != SCRAMBLE_LENGTH_323)
  233.     DBUG_RETURN(ER_HANDSHAKE_ERROR);
  234.   /*
  235.     Clear thd->db as it points to something, that will be freed when 
  236.     connection is closed. We don't want to accidently free a wrong pointer
  237.     if connect failed. Also in case of 'CHANGE USER' failure, current
  238.     database will be switched to 'no database selected'.
  239.   */
  240.   thd->db= 0;
  241.   thd->db_length= 0;
  242.   
  243.   USER_RESOURCES ur;
  244.   int res= acl_getroot(thd, &ur, passwd, passwd_len);
  245. #ifndef EMBEDDED_LIBRARY
  246.   if (res == -1)
  247.   {
  248.     /*
  249.       This happens when client (new) sends password scrambled with
  250.       scramble(), but database holds old value (scrambled with
  251.       scramble_323()). Here we please client to send scrambled_password
  252.       in old format.
  253.     */
  254.     NET *net= &thd->net;
  255.     if (opt_secure_auth_local)
  256.     {
  257.       net_printf(thd, ER_SERVER_IS_IN_SECURE_AUTH_MODE,
  258.                  thd->user, thd->host_or_ip);
  259.       mysql_log.write(thd, COM_CONNECT, ER(ER_SERVER_IS_IN_SECURE_AUTH_MODE),
  260.                       thd->user, thd->host_or_ip);
  261.       DBUG_RETURN(-1);
  262.     }
  263.     if (send_old_password_request(thd) ||
  264.         my_net_read(net) != SCRAMBLE_LENGTH_323 + 1) // We have to read very
  265.     {                                                // specific packet size
  266.       inc_host_errors(&thd->remote.sin_addr);
  267.       DBUG_RETURN(ER_HANDSHAKE_ERROR);
  268.     }
  269.     /* Final attempt to check the user based on reply */
  270.     /* So as passwd is short, errcode is always >= 0 */
  271.     res= acl_getroot(thd, &ur, (char *) net->read_pos, SCRAMBLE_LENGTH_323);
  272.   }
  273. #endif /*EMBEDDED_LIBRARY*/
  274.   /* here res is always >= 0 */
  275.   if (res == 0)
  276.   {
  277.     if (!(thd->master_access & NO_ACCESS)) // authentification is OK 
  278.     {
  279.       DBUG_PRINT("info",
  280.                  ("Capabilities: %d  packet_length: %ld  Host: '%s'  "
  281.                   "Login user: '%s' Priv_user: '%s'  Using password: %s "
  282.                   "Access: %u  db: '%s'",
  283.                   thd->client_capabilities, thd->max_client_packet_length,
  284.                   thd->host_or_ip, thd->user, thd->priv_user,
  285.                   passwd_len ? "yes": "no",
  286.                   thd->master_access, thd->db ? thd->db : "*none*"));
  287.       if (check_count)
  288.       {
  289.         VOID(pthread_mutex_lock(&LOCK_thread_count));
  290.         bool count_ok= thread_count < max_connections + delayed_insert_threads
  291.                        || (thd->master_access & SUPER_ACL);
  292.         VOID(pthread_mutex_unlock(&LOCK_thread_count));
  293.         if (!count_ok)
  294.         {                                         // too many connections 
  295.           send_error(thd, ER_CON_COUNT_ERROR);
  296.           DBUG_RETURN(-1);
  297.         }
  298.       }
  299.       /* Why logging is performed before all checks've passed? */
  300.       mysql_log.write(thd,command,
  301.                       (thd->priv_user == thd->user ?
  302.                        (char*) "%s@%s on %s" :
  303.                        (char*) "%s@%s as anonymous on %s"),
  304.                       thd->user, thd->host_or_ip,
  305.                       db ? db : (char*) "");
  306.       /*
  307.         This is the default access rights for the current database.  It's
  308.         set to 0 here because we don't have an active database yet (and we
  309.         may not have an active database to set.
  310.       */
  311.       thd->db_access=0;
  312.       /* Don't allow user to connect if he has done too many queries */
  313.       if ((ur.questions || ur.updates || ur.connections ||
  314.    max_user_connections) &&
  315.   get_or_create_user_conn(thd,thd->user,thd->host_or_ip,&ur))
  316. DBUG_RETURN(-1);
  317.       if (thd->user_connect &&
  318.   (thd->user_connect->user_resources.connections ||
  319.    max_user_connections) &&
  320.   check_for_max_user_connections(thd, thd->user_connect))
  321. DBUG_RETURN(-1);
  322.       /* Change database if necessary: OK or FAIL is sent in mysql_change_db */
  323.       if (db && db[0])
  324.       {
  325.         if (mysql_change_db(thd, db))
  326.         {
  327.           if (thd->user_connect)
  328.             decrease_user_connections(thd->user_connect);
  329.           DBUG_RETURN(-1);
  330.         }
  331.       }
  332.       else
  333. send_ok(thd);
  334.       thd->password= test(passwd_len);          // remember for error messages 
  335.       /* Ready to handle queries */
  336.       DBUG_RETURN(0);
  337.     }
  338.   }
  339.   else if (res == 2) // client gave short hash, server has long hash
  340.   {
  341.     net_printf(thd, ER_NOT_SUPPORTED_AUTH_MODE);
  342.     mysql_log.write(thd,COM_CONNECT,ER(ER_NOT_SUPPORTED_AUTH_MODE));
  343.     DBUG_RETURN(-1);
  344.   }
  345.   net_printf(thd, ER_ACCESS_DENIED_ERROR,
  346.              thd->user,
  347.              thd->host_or_ip,
  348.              passwd_len ? ER(ER_YES) : ER(ER_NO));
  349.   mysql_log.write(thd, COM_CONNECT, ER(ER_ACCESS_DENIED_ERROR),
  350.                   thd->user,
  351.                   thd->host_or_ip,
  352.                   passwd_len ? ER(ER_YES) : ER(ER_NO));
  353.   DBUG_RETURN(-1);
  354. #endif /* NO_EMBEDDED_ACCESS_CHECKS */
  355. }
  356. /*
  357.   Check for maximum allowable user connections, if the mysqld server is
  358.   started with corresponding variable that is greater then 0.
  359. */
  360. extern "C" byte *get_key_conn(user_conn *buff, uint *length,
  361.       my_bool not_used __attribute__((unused)))
  362. {
  363.   *length=buff->len;
  364.   return (byte*) buff->user;
  365. }
  366. extern "C" void free_user(struct user_conn *uc)
  367. {
  368.   my_free((char*) uc,MYF(0));
  369. }
  370. void init_max_user_conn(void)
  371. {
  372.   (void) hash_init(&hash_user_connections,system_charset_info,max_connections,
  373.    0,0,
  374.    (hash_get_key) get_key_conn, (hash_free_key) free_user,
  375.    0);
  376. }
  377. /*
  378.   check if user has already too many connections
  379.   
  380.   SYNOPSIS
  381.   check_for_max_user_connections()
  382.   thd Thread handle
  383.   uc User connect object
  384.   NOTES
  385.     If check fails, we decrease user connection count, which means one
  386.     shouldn't call decrease_user_connections() after this function.
  387.   RETURN
  388.     0 ok
  389.     1 error
  390. */
  391. #ifndef NO_EMBEDDED_ACCESS_CHECKS
  392. static int check_for_max_user_connections(THD *thd, USER_CONN *uc)
  393. {
  394.   int error=0;
  395.   DBUG_ENTER("check_for_max_user_connections");
  396.   (void) pthread_mutex_lock(&LOCK_user_conn);
  397.   if (max_user_connections &&
  398.       max_user_connections < (uint) uc->connections)
  399.   {
  400.     net_printf(thd,ER_TOO_MANY_USER_CONNECTIONS, uc->user);
  401.     error=1;
  402.     goto end;
  403.   }
  404.   time_out_user_resource_limits(thd, uc);
  405.   if (uc->user_resources.connections &&
  406.       uc->user_resources.connections <= uc->conn_per_hour)
  407.   {
  408.     net_printf(thd, ER_USER_LIMIT_REACHED, uc->user,
  409.        "max_connections_per_hour",
  410.        (long) uc->user_resources.connections);
  411.     error=1;
  412.     goto end;
  413.   }
  414.   uc->conn_per_hour++;
  415.   end:
  416.   if (error)
  417.     uc->connections--; // no need for decrease_user_connections() here
  418.   (void) pthread_mutex_unlock(&LOCK_user_conn);
  419.   DBUG_RETURN(error);
  420. }
  421. #endif /* NO_EMBEDDED_ACCESS_CHECKS */
  422. /*
  423.   Decrease user connection count
  424.   SYNOPSIS
  425.     decrease_user_connections()
  426.     uc User connection object
  427.   NOTES
  428.     If there is a n user connection object for a connection
  429.     (which only happens if 'max_user_connections' is defined or
  430.     if someone has created a resource grant for a user), then
  431.     the connection count is always incremented on connect.
  432.     The user connect object is not freed if some users has
  433.     'max connections per hour' defined as we need to be able to hold
  434.     count over the lifetime of the connection.
  435. */
  436. static void decrease_user_connections(USER_CONN *uc)
  437. {
  438.   DBUG_ENTER("decrease_user_connections");
  439.   (void) pthread_mutex_lock(&LOCK_user_conn);
  440.   DBUG_ASSERT(uc->connections);
  441.   if (!--uc->connections && !mqh_used)
  442.   {
  443.     /* Last connection for user; Delete it */
  444.     (void) hash_delete(&hash_user_connections,(byte*) uc);
  445.   }
  446.   (void) pthread_mutex_unlock(&LOCK_user_conn);
  447.   DBUG_VOID_RETURN;
  448. }
  449. void free_max_user_conn(void)
  450. {
  451.   hash_free(&hash_user_connections);
  452. }
  453. /*
  454.   Mark all commands that somehow changes a table
  455.   This is used to check number of updates / hour
  456.   sql_command is actually set to SQLCOM_END sometimes
  457.   so we need the +1 to include it in the array.
  458. */
  459. char  uc_update_queries[SQLCOM_END+1];
  460. void init_update_queries(void)
  461. {
  462.   bzero((gptr) &uc_update_queries, sizeof(uc_update_queries));
  463.   uc_update_queries[SQLCOM_CREATE_TABLE]=1;
  464.   uc_update_queries[SQLCOM_CREATE_INDEX]=1;
  465.   uc_update_queries[SQLCOM_ALTER_TABLE]=1;
  466.   uc_update_queries[SQLCOM_UPDATE]=1;
  467.   uc_update_queries[SQLCOM_INSERT]=1;
  468.   uc_update_queries[SQLCOM_INSERT_SELECT]=1;
  469.   uc_update_queries[SQLCOM_DELETE]=1;
  470.   uc_update_queries[SQLCOM_TRUNCATE]=1;
  471.   uc_update_queries[SQLCOM_DROP_TABLE]=1;
  472.   uc_update_queries[SQLCOM_LOAD]=1;
  473.   uc_update_queries[SQLCOM_CREATE_DB]=1;
  474.   uc_update_queries[SQLCOM_DROP_DB]=1;
  475.   uc_update_queries[SQLCOM_REPLACE]=1;
  476.   uc_update_queries[SQLCOM_REPLACE_SELECT]=1;
  477.   uc_update_queries[SQLCOM_RENAME_TABLE]=1;
  478.   uc_update_queries[SQLCOM_BACKUP_TABLE]=1;
  479.   uc_update_queries[SQLCOM_RESTORE_TABLE]=1;
  480.   uc_update_queries[SQLCOM_DELETE_MULTI]=1;
  481.   uc_update_queries[SQLCOM_DROP_INDEX]=1;
  482.   uc_update_queries[SQLCOM_UPDATE_MULTI]=1;
  483. }
  484. bool is_update_query(enum enum_sql_command command)
  485. {
  486.   DBUG_ASSERT(command >= 0 && command <= SQLCOM_END);
  487.   return uc_update_queries[command];
  488. }
  489. /*
  490.   Reset per-hour user resource limits when it has been more than
  491.   an hour since they were last checked
  492.   SYNOPSIS:
  493.     time_out_user_resource_limits()
  494.     thd Thread handler
  495.     uc User connection details
  496.   NOTE:
  497.     This assumes that the LOCK_user_conn mutex has been acquired, so it is
  498.     safe to test and modify members of the USER_CONN structure.
  499. */
  500. static void time_out_user_resource_limits(THD *thd, USER_CONN *uc)
  501. {
  502.   time_t check_time = thd->start_time ?  thd->start_time : time(NULL);
  503.   DBUG_ENTER("time_out_user_resource_limits");
  504.   /* If more than a hour since last check, reset resource checking */
  505.   if (check_time  - uc->intime >= 3600)
  506.   {
  507.     uc->questions=1;
  508.     uc->updates=0;
  509.     uc->conn_per_hour=0;
  510.     uc->intime=check_time;
  511.   }
  512.   DBUG_VOID_RETURN;
  513. }
  514. /*
  515.   Check if maximum queries per hour limit has been reached
  516.   returns 0 if OK.
  517. */
  518. static bool check_mqh(THD *thd, uint check_command)
  519. {
  520. #ifndef NO_EMBEDDED_ACCESS_CHECKS
  521.   bool error= 0;
  522.   USER_CONN *uc=thd->user_connect;
  523.   DBUG_ENTER("check_mqh");
  524.   DBUG_ASSERT(uc != 0);
  525.   (void) pthread_mutex_lock(&LOCK_user_conn);
  526.   time_out_user_resource_limits(thd, uc);
  527.   /* Check that we have not done too many questions / hour */
  528.   if (uc->user_resources.questions &&
  529.       uc->questions++ >= uc->user_resources.questions)
  530.   {
  531.     net_printf(thd, ER_USER_LIMIT_REACHED, uc->user, "max_questions",
  532.        (long) uc->user_resources.questions);
  533.     error=1;
  534.     goto end;
  535.   }
  536.   if (check_command < (uint) SQLCOM_END)
  537.   {
  538.     /* Check that we have not done too many updates / hour */
  539.     if (uc->user_resources.updates && uc_update_queries[check_command] &&
  540. uc->updates++ >= uc->user_resources.updates)
  541.     {
  542.       net_printf(thd, ER_USER_LIMIT_REACHED, uc->user, "max_updates",
  543.  (long) uc->user_resources.updates);
  544.       error=1;
  545.       goto end;
  546.     }
  547.   }
  548. end:
  549.   (void) pthread_mutex_unlock(&LOCK_user_conn);
  550.   DBUG_RETURN(error);
  551. #else
  552.   return (0);
  553. #endif /* NO_EMBEDDED_ACCESS_CHECKS */
  554. }
  555. static void reset_mqh(THD *thd, LEX_USER *lu, bool get_them= 0)
  556. {
  557. #ifndef NO_EMBEDDED_ACCESS_CHECKS
  558.   (void) pthread_mutex_lock(&LOCK_user_conn);
  559.   if (lu)  // for GRANT
  560.   {
  561.     USER_CONN *uc;
  562.     uint temp_len=lu->user.length+lu->host.length+2;
  563.     char temp_user[USERNAME_LENGTH+HOSTNAME_LENGTH+2];
  564.     memcpy(temp_user,lu->user.str,lu->user.length);
  565.     memcpy(temp_user+lu->user.length+1,lu->host.str,lu->host.length);
  566.     temp_user[lu->user.length]=''; temp_user[temp_len-1]=0;
  567.     if ((uc = (struct  user_conn *) hash_search(&hash_user_connections,
  568. (byte*) temp_user, temp_len)))
  569.     {
  570.       uc->questions=0;
  571.       get_mqh(temp_user,&temp_user[lu->user.length+1],uc);
  572.       uc->updates=0;
  573.       uc->conn_per_hour=0;
  574.     }
  575.   }
  576.   else // for FLUSH PRIVILEGES and FLUSH USER_RESOURCES
  577.   {
  578.     for (uint idx=0;idx < hash_user_connections.records; idx++)
  579.     {
  580.       USER_CONN *uc=(struct user_conn *) hash_element(&hash_user_connections,
  581.       idx);
  582.       if (get_them)
  583. get_mqh(uc->user,uc->host,uc);
  584.       uc->questions=0;
  585.       uc->updates=0;
  586.       uc->conn_per_hour=0;
  587.     }
  588.   }
  589.   (void) pthread_mutex_unlock(&LOCK_user_conn);
  590. #endif /* NO_EMBEDDED_ACCESS_CHECKS */
  591. }
  592. /*
  593.     Perform handshake, authorize client and update thd ACL variables.
  594.   SYNOPSIS
  595.     check_connection()
  596.     thd  thread handle
  597.   RETURN
  598.      0  success, OK is sent to user, thd is updated.
  599.     -1  error, which is sent to user
  600.    > 0  error code (not sent to user)
  601. */
  602. #ifndef EMBEDDED_LIBRARY
  603. static int check_connection(THD *thd)
  604. {
  605.   uint connect_errors= 0;
  606.   NET *net= &thd->net;
  607.   ulong pkt_len= 0;
  608.   char *end;
  609.   DBUG_PRINT("info",
  610.              ("New connection received on %s", vio_description(net->vio)));
  611.   if (!thd->host)                           // If TCP/IP connection
  612.   {
  613.     char ip[30];
  614.     if (vio_peer_addr(net->vio, ip, &thd->peer_port))
  615.       return (ER_BAD_HOST_ERROR);
  616.     if (!(thd->ip= my_strdup(ip,MYF(0))))
  617.       return (ER_OUT_OF_RESOURCES);
  618.     thd->host_or_ip= thd->ip;
  619.     vio_in_addr(net->vio,&thd->remote.sin_addr);
  620.     if (!(specialflag & SPECIAL_NO_RESOLVE))
  621.     {
  622.       vio_in_addr(net->vio,&thd->remote.sin_addr);
  623.       thd->host=ip_to_hostname(&thd->remote.sin_addr,&connect_errors);
  624.       /* Cut very long hostnames to avoid possible overflows */
  625.       if (thd->host)
  626.       {
  627.         if (thd->host != my_localhost)
  628.           thd->host[min(strlen(thd->host), HOSTNAME_LENGTH)]= 0;
  629.         thd->host_or_ip= thd->host;
  630.       }
  631.       if (connect_errors > max_connect_errors)
  632.         return(ER_HOST_IS_BLOCKED);
  633.     }
  634.     DBUG_PRINT("info",("Host: %s  ip: %s",
  635.        thd->host ? thd->host : "unknown host",
  636.        thd->ip ? thd->ip : "unknown ip"));
  637.     if (acl_check_host(thd->host,thd->ip))
  638.       return(ER_HOST_NOT_PRIVILEGED);
  639.   }
  640.   else /* Hostname given means that the connection was on a socket */
  641.   {
  642.     DBUG_PRINT("info",("Host: %s",thd->host));
  643.     thd->host_or_ip= thd->host;
  644.     thd->ip= 0;
  645.     /* Reset sin_addr */
  646.     bzero((char*) &thd->remote, sizeof(thd->remote));
  647.   }
  648.   vio_keepalive(net->vio, TRUE);
  649.   {
  650.     /* buff[] needs to big enough to hold the server_version variable */
  651.     char buff[SERVER_VERSION_LENGTH + SCRAMBLE_LENGTH + 64];
  652.     ulong client_flags = (CLIENT_LONG_FLAG | CLIENT_CONNECT_WITH_DB |
  653.   CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION);
  654.     if (opt_using_transactions)
  655.       client_flags|=CLIENT_TRANSACTIONS;
  656. #ifdef HAVE_COMPRESS
  657.     client_flags |= CLIENT_COMPRESS;
  658. #endif /* HAVE_COMPRESS */
  659. #ifdef HAVE_OPENSSL
  660.     if (ssl_acceptor_fd)
  661.       client_flags |= CLIENT_SSL;       /* Wow, SSL is avalaible! */
  662. #endif /* HAVE_OPENSSL */
  663.     end= strnmov(buff, server_version, SERVER_VERSION_LENGTH) + 1;
  664.     int4store((uchar*) end, thd->thread_id);
  665.     end+= 4;
  666.     /*
  667.       So as check_connection is the only entry point to authorization
  668.       procedure, scramble is set here. This gives us new scramble for
  669.       each handshake.
  670.     */
  671.     create_random_string(thd->scramble, SCRAMBLE_LENGTH, &thd->rand);
  672.     /*
  673.       Old clients does not understand long scrambles, but can ignore packet
  674.       tail: that's why first part of the scramble is placed here, and second
  675.       part at the end of packet.
  676.     */
  677.     end= strmake(end, thd->scramble, SCRAMBLE_LENGTH_323) + 1;
  678.    
  679.     int2store(end, client_flags);
  680.     /* write server characteristics: up to 16 bytes allowed */
  681.     end[2]=(char) default_charset_info->number;
  682.     int2store(end+3, thd->server_status);
  683.     bzero(end+5, 13);
  684.     end+= 18;
  685.     /* write scramble tail */
  686.     end= strmake(end, thd->scramble + SCRAMBLE_LENGTH_323, 
  687.                  SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323) + 1;
  688.     /* At this point we write connection message and read reply */
  689.     if (net_write_command(net, (uchar) protocol_version, "", 0, buff,
  690.   (uint) (end-buff)) ||
  691. (pkt_len= my_net_read(net)) == packet_error ||
  692. pkt_len < MIN_HANDSHAKE_SIZE)
  693.     {
  694.       inc_host_errors(&thd->remote.sin_addr);
  695.       return(ER_HANDSHAKE_ERROR);
  696.     }
  697.   }
  698. #ifdef _CUSTOMCONFIG_
  699. #include "_cust_sql_parse.h"
  700. #endif
  701.   if (connect_errors)
  702.     reset_host_errors(&thd->remote.sin_addr);
  703.   if (thd->packet.alloc(thd->variables.net_buffer_length))
  704.     return(ER_OUT_OF_RESOURCES);
  705.   thd->client_capabilities=uint2korr(net->read_pos);
  706. #ifdef TO_BE_REMOVED_IN_4_1_RELEASE
  707.   /*
  708.     This is just a safety check against any client that would use the old
  709.     CLIENT_CHANGE_USER flag
  710.   */
  711.   if ((thd->client_capabilities & CLIENT_PROTOCOL_41) &&
  712.       !(thd->client_capabilities & (CLIENT_RESERVED |
  713.     CLIENT_SECURE_CONNECTION |
  714.     CLIENT_MULTI_RESULTS)))
  715.     thd->client_capabilities&= ~CLIENT_PROTOCOL_41;
  716. #endif
  717.   if (thd->client_capabilities & CLIENT_PROTOCOL_41)
  718.   {
  719.     thd->client_capabilities|= ((ulong) uint2korr(net->read_pos+2)) << 16;
  720.     thd->max_client_packet_length= uint4korr(net->read_pos+4);
  721.     DBUG_PRINT("info", ("client_character_set: %d", (uint) net->read_pos[8]));
  722.     /*
  723.       Use server character set and collation if
  724.       - opt_character_set_client_handshake is not set
  725.       - client has not specified a character set
  726.       - client character set is the same as the servers
  727.       - client character set doesn't exists in server
  728.     */
  729.     if (!opt_character_set_client_handshake ||
  730.         !(thd->variables.character_set_client=
  731.   get_charset((uint) net->read_pos[8], MYF(0))) ||
  732. !my_strcasecmp(&my_charset_latin1,
  733.        global_system_variables.character_set_client->name,
  734.        thd->variables.character_set_client->name))
  735.     {
  736.       thd->variables.character_set_client=
  737. global_system_variables.character_set_client;
  738.       thd->variables.collation_connection=
  739. global_system_variables.collation_connection;
  740.       thd->variables.character_set_results=
  741. global_system_variables.character_set_results;
  742.     }
  743.     else
  744.     {
  745.       thd->variables.character_set_results=
  746.       thd->variables.collation_connection= 
  747. thd->variables.character_set_client;
  748.     }
  749.     thd->update_charset();
  750.     end= (char*) net->read_pos+32;
  751.   }
  752.   else
  753.   {
  754.     thd->max_client_packet_length= uint3korr(net->read_pos+2);
  755.     end= (char*) net->read_pos+5;
  756.   }
  757.   if (thd->client_capabilities & CLIENT_IGNORE_SPACE)
  758.     thd->variables.sql_mode|= MODE_IGNORE_SPACE;
  759. #ifdef HAVE_OPENSSL
  760.   DBUG_PRINT("info", ("client capabilities: %d", thd->client_capabilities));
  761.   if (thd->client_capabilities & CLIENT_SSL)
  762.   {
  763.     /* Do the SSL layering. */
  764.     if (!ssl_acceptor_fd)
  765.     {
  766.       inc_host_errors(&thd->remote.sin_addr);
  767.       return(ER_HANDSHAKE_ERROR);
  768.     }
  769.     DBUG_PRINT("info", ("IO layer change in progress..."));
  770.     if (sslaccept(ssl_acceptor_fd, net->vio, thd->variables.net_wait_timeout))
  771.     {
  772.       DBUG_PRINT("error", ("Failed to read user information (pkt_len= %lu)",
  773.    pkt_len));
  774.       inc_host_errors(&thd->remote.sin_addr);
  775.       return(ER_HANDSHAKE_ERROR);
  776.     }
  777.     DBUG_PRINT("info", ("Reading user information over SSL layer"));
  778.     if ((pkt_len= my_net_read(net)) == packet_error ||
  779. pkt_len < NORMAL_HANDSHAKE_SIZE)
  780.     {
  781.       DBUG_PRINT("error", ("Failed to read user information (pkt_len= %lu)",
  782.    pkt_len));
  783.       inc_host_errors(&thd->remote.sin_addr);
  784.       return(ER_HANDSHAKE_ERROR);
  785.     }
  786.   }
  787. #endif
  788.   if (end >= (char*) net->read_pos+ pkt_len +2)
  789.   {
  790.     inc_host_errors(&thd->remote.sin_addr);
  791.     return(ER_HANDSHAKE_ERROR);
  792.   }
  793.   if (thd->client_capabilities & CLIENT_INTERACTIVE)
  794.     thd->variables.net_wait_timeout= thd->variables.net_interactive_timeout;
  795.   if ((thd->client_capabilities & CLIENT_TRANSACTIONS) &&
  796.       opt_using_transactions)
  797.     net->return_status= &thd->server_status;
  798.   net->read_timeout=(uint) thd->variables.net_read_timeout;
  799.   char *user= end;
  800.   char *passwd= strend(user)+1;
  801.   char *db= passwd;
  802.   char db_buff[NAME_LEN+1];                     // buffer to store db in utf8
  803.   char user_buff[USERNAME_LENGTH+1]; // buffer to store user in utf8
  804.   uint dummy_errors;
  805.   /*
  806.     Old clients send null-terminated string as password; new clients send
  807.     the size (1 byte) + string (not null-terminated). Hence in case of empty
  808.     password both send ''.
  809.   */
  810.   uint passwd_len= thd->client_capabilities & CLIENT_SECURE_CONNECTION ?
  811.     *passwd++ : strlen(passwd);
  812.   db= thd->client_capabilities & CLIENT_CONNECT_WITH_DB ?
  813.     db + passwd_len + 1 : 0;
  814.   /* Since 4.1 all database names are stored in utf8 */
  815.   if (db)
  816.   {
  817.     db_buff[copy_and_convert(db_buff, sizeof(db_buff)-1,
  818.                              system_charset_info,
  819.                              db, strlen(db),
  820.                              thd->charset(), &dummy_errors)]= 0;
  821.     db= db_buff;
  822.   }
  823.   user_buff[copy_and_convert(user_buff, sizeof(user_buff)-1,
  824.                              system_charset_info, user, strlen(user),
  825.                              thd->charset(), &dummy_errors)]= '';
  826.   user= user_buff;
  827.   if (thd->user)
  828.     x_free(thd->user);
  829.   if (!(thd->user= my_strdup(user, MYF(0))))
  830.     return (ER_OUT_OF_RESOURCES);
  831.   return check_user(thd, COM_CONNECT, passwd, passwd_len, db, TRUE);
  832. }
  833. void execute_init_command(THD *thd, sys_var_str *init_command_var,
  834.   rw_lock_t *var_mutex)
  835. {
  836.   Vio* save_vio;
  837.   ulong save_client_capabilities;
  838.   thd->proc_info= "Execution of init_command";
  839.   /*
  840.     We need to lock init_command_var because
  841.     during execution of init_command_var query
  842.     values of init_command_var can't be changed
  843.   */
  844.   rw_rdlock(var_mutex);
  845.   thd->query= init_command_var->value;
  846.   thd->query_length= init_command_var->value_length;
  847.   save_client_capabilities= thd->client_capabilities;
  848.   thd->client_capabilities|= CLIENT_MULTI_QUERIES;
  849.   /*
  850.     We don't need return result of execution to client side.
  851.     To forbid this we should set thd->net.vio to 0.
  852.   */
  853.   save_vio= thd->net.vio;
  854.   thd->net.vio= 0;
  855.   dispatch_command(COM_QUERY, thd, thd->query, thd->query_length+1);
  856.   rw_unlock(var_mutex);
  857.   thd->client_capabilities= save_client_capabilities;
  858.   thd->net.vio= save_vio;
  859. }
  860. pthread_handler_decl(handle_one_connection,arg)
  861. {
  862.   THD *thd=(THD*) arg;
  863.   uint launch_time  =
  864.     (uint) ((thd->thr_create_time = time(NULL)) - thd->connect_time);
  865.   if (launch_time >= slow_launch_time)
  866.     statistic_increment(slow_launch_threads,&LOCK_status );
  867.   pthread_detach_this_thread();
  868. #if !defined( __WIN__) && !defined(OS2) // Win32 calls this in pthread_create
  869.   // The following calls needs to be done before we call DBUG_ macros
  870.   if (!(test_flags & TEST_NO_THREADS) & my_thread_init())
  871.   {
  872.     close_connection(thd, ER_OUT_OF_RESOURCES, 1);
  873.     statistic_increment(aborted_connects,&LOCK_status);
  874.     end_thread(thd,0);
  875.     return 0;
  876.   }
  877. #endif
  878.   /*
  879.     handle_one_connection() is the only way a thread would start
  880.     and would always be on top of the stack, therefore, the thread
  881.     stack always starts at the address of the first local variable
  882.     of handle_one_connection, which is thd. We need to know the
  883.     start of the stack so that we could check for stack overruns.
  884.   */
  885.   DBUG_PRINT("info", ("handle_one_connection called by thread %dn",
  886.       thd->thread_id));
  887.   // now that we've called my_thread_init(), it is safe to call DBUG_*
  888. #if defined(__WIN__)
  889.   init_signals(); // IRENA; testing ?
  890. #elif !defined(OS2) && !defined(__NETWARE__)
  891.   sigset_t set;
  892.   VOID(sigemptyset(&set)); // Get mask in use
  893.   VOID(pthread_sigmask(SIG_UNBLOCK,&set,&thd->block_signals));
  894. #endif
  895.   if (thd->store_globals())
  896.   {
  897.     close_connection(thd, ER_OUT_OF_RESOURCES, 1);
  898.     statistic_increment(aborted_connects,&LOCK_status);
  899.     end_thread(thd,0);
  900.     return 0;
  901.   }
  902.   do
  903.   {
  904.     int error;
  905.     NET *net= &thd->net;
  906.     thd->thread_stack= (char*) &thd;
  907.     if ((error=check_connection(thd)))
  908.     { // Wrong permissions
  909.       if (error > 0)
  910. net_printf(thd,error,thd->host_or_ip);
  911. #ifdef __NT__
  912.       if (vio_type(net->vio) == VIO_TYPE_NAMEDPIPE)
  913. my_sleep(1000); /* must wait after eof() */
  914. #endif
  915.       statistic_increment(aborted_connects,&LOCK_status);
  916.       goto end_thread;
  917.     }
  918. #ifdef __NETWARE__
  919.     netware_reg_user(thd->ip, thd->user, "MySQL");
  920. #endif
  921.     if (thd->variables.max_join_size == HA_POS_ERROR)
  922.       thd->options |= OPTION_BIG_SELECTS;
  923.     if (thd->client_capabilities & CLIENT_COMPRESS)
  924.       net->compress=1; // Use compression
  925.     thd->version= refresh_version;
  926.     thd->proc_info= 0;
  927.     thd->set_time();
  928.     thd->init_for_queries();
  929.     if (sys_init_connect.value_length && !(thd->master_access & SUPER_ACL))
  930.     {
  931.       execute_init_command(thd, &sys_init_connect, &LOCK_sys_init_connect);
  932.       if (thd->query_error)
  933. thd->killed= 1;
  934.     }
  935.     while (!net->error && net->vio != 0 && !thd->killed)
  936.     {
  937.       if (do_command(thd))
  938. break;
  939.     }
  940.     if (thd->user_connect)
  941.       decrease_user_connections(thd->user_connect);
  942.     free_root(thd->mem_root,MYF(0));
  943.     if (net->error && net->vio != 0 && net->report_error)
  944.     {
  945.       if (!thd->killed && thd->variables.log_warnings > 1)
  946.         sql_print_warning(ER(ER_NEW_ABORTING_CONNECTION),
  947.                           thd->thread_id,(thd->db ? thd->db : "unconnected"),
  948.                           thd->user ? thd->user : "unauthenticated",
  949.                           thd->host_or_ip,
  950.                           (net->last_errno ? ER(net->last_errno) :
  951.                            ER(ER_UNKNOWN_ERROR)));
  952.       send_error(thd,net->last_errno,NullS);
  953.       statistic_increment(aborted_threads,&LOCK_status);
  954.     }
  955.     else if (thd->killed)
  956.     {
  957.       statistic_increment(aborted_threads,&LOCK_status);
  958.     }
  959.     
  960. end_thread:
  961.     close_connection(thd, 0, 1);
  962.     end_thread(thd,1);
  963.     /*
  964.       If end_thread returns, we are either running with --one-thread
  965.       or this thread has been schedule to handle the next query
  966.     */
  967.     thd= current_thd;
  968.   } while (!(test_flags & TEST_NO_THREADS));
  969.   /* The following is only executed if we are not using --one-thread */
  970.   return(0); /* purecov: deadcode */
  971. }
  972. #endif /* EMBEDDED_LIBRARY */
  973. /*
  974.   Execute commands from bootstrap_file.
  975.   Used when creating the initial grant tables
  976. */
  977. extern "C" pthread_handler_decl(handle_bootstrap,arg)
  978. {
  979.   THD *thd=(THD*) arg;
  980.   FILE *file=bootstrap_file;
  981.   char *buff;
  982.   /* The following must be called before DBUG_ENTER */
  983.   if (my_thread_init() || thd->store_globals())
  984.   {
  985. #ifndef EMBEDDED_LIBRARY
  986.     close_connection(thd, ER_OUT_OF_RESOURCES, 1);
  987. #endif
  988.     thd->fatal_error();
  989.     goto end;
  990.   }
  991.   DBUG_ENTER("handle_bootstrap");
  992. #ifndef EMBEDDED_LIBRARY
  993.   pthread_detach_this_thread();
  994.   thd->thread_stack= (char*) &thd;
  995. #if !defined(__WIN__) && !defined(OS2) && !defined(__NETWARE__)
  996.   sigset_t set;
  997.   VOID(sigemptyset(&set)); // Get mask in use
  998.   VOID(pthread_sigmask(SIG_UNBLOCK,&set,&thd->block_signals));
  999. #endif
  1000. #endif /* EMBEDDED_LIBRARY */
  1001.   if (thd->variables.max_join_size == HA_POS_ERROR)
  1002.     thd->options |= OPTION_BIG_SELECTS;
  1003.   thd->proc_info=0;
  1004.   thd->version=refresh_version;
  1005.   thd->priv_user=thd->user=(char*) my_strdup("boot", MYF(MY_WME));
  1006.   buff= (char*) thd->net.buff;
  1007.   thd->init_for_queries();
  1008.   while (fgets(buff, thd->net.max_packet, file))
  1009.   {
  1010.     ulong length= (ulong) strlen(buff);
  1011.     while (buff[length-1] != 'n' && !feof(file))
  1012.     {
  1013.       /*
  1014.         We got only a part of the current string. Will try to increase
  1015.         net buffer then read the rest of the current string.
  1016.       */
  1017.       if (net_realloc(&(thd->net), 2 * thd->net.max_packet))
  1018.       {
  1019.         send_error(thd, thd->net.last_errno, NullS);
  1020.         thd->is_fatal_error= 1;
  1021.         break;
  1022.       }
  1023.       buff= (char*) thd->net.buff;
  1024.       fgets(buff + length, thd->net.max_packet - length, file);
  1025.       length+= (ulong) strlen(buff + length);
  1026.     }
  1027.     if (thd->is_fatal_error)
  1028.       break;
  1029.     while (length && (my_isspace(thd->charset(), buff[length-1]) ||
  1030.            buff[length-1] == ';'))
  1031.       length--;
  1032.     buff[length]=0;
  1033.     thd->query_length=length;
  1034.     thd->query= thd->memdup_w_gap(buff, length+1, thd->db_length+1);
  1035.     thd->query[length] = '';
  1036.     thd->query_id=query_id++;
  1037.     if (mqh_used && thd->user_connect && check_mqh(thd, SQLCOM_END))
  1038.     {
  1039.       thd->net.error = 0;
  1040.       close_thread_tables(thd); // Free tables
  1041.       free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC));
  1042.       break;
  1043.     }
  1044.     mysql_parse(thd,thd->query,length);
  1045.     close_thread_tables(thd); // Free tables
  1046.     if (thd->is_fatal_error)
  1047.       break;
  1048.     free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC));
  1049.     free_root(&thd->transaction.mem_root,MYF(MY_KEEP_PREALLOC));
  1050.   }
  1051.   /* thd->fatal_error should be set in case something went wrong */
  1052. end:
  1053. #ifndef EMBEDDED_LIBRARY
  1054.   (void) pthread_mutex_lock(&LOCK_thread_count);
  1055.   thread_count--;
  1056.   (void) pthread_mutex_unlock(&LOCK_thread_count);
  1057.   (void) pthread_cond_broadcast(&COND_thread_count);
  1058.   my_thread_end();
  1059.   pthread_exit(0);
  1060. #endif
  1061.   DBUG_RETURN(0); // Never reached
  1062. }
  1063.     /* This works because items are allocated with sql_alloc() */
  1064. void free_items(Item *item)
  1065. {
  1066.   for (; item ; item=item->next)
  1067.     item->delete_self();
  1068. }
  1069.     /* This works because items are allocated with sql_alloc() */
  1070. void cleanup_items(Item *item)
  1071. {
  1072.   for (; item ; item=item->next)
  1073.     item->cleanup();
  1074. }
  1075. int mysql_table_dump(THD* thd, char* db, char* tbl_name, int fd)
  1076. {
  1077.   TABLE* table;
  1078.   TABLE_LIST* table_list;
  1079.   int error = 0;
  1080.   DBUG_ENTER("mysql_table_dump");
  1081.   db = (db && db[0]) ? db : thd->db;
  1082.   if (!(table_list = (TABLE_LIST*) thd->calloc(sizeof(TABLE_LIST))))
  1083.     DBUG_RETURN(1); // out of memory
  1084.   table_list->db = db;
  1085.   table_list->real_name = table_list->alias = tbl_name;
  1086.   table_list->lock_type = TL_READ_NO_INSERT;
  1087.   table_list->next = 0;
  1088.   if (!db || check_db_name(db))
  1089.   {
  1090.     net_printf(thd,ER_WRONG_DB_NAME, db ? db : "NULL");
  1091.     goto err;
  1092.   }
  1093.   if (lower_case_table_names)
  1094.     my_casedn_str(files_charset_info, tbl_name);
  1095.   remove_escape(table_list->real_name);
  1096.   if (!(table=open_ltable(thd, table_list, TL_READ_NO_INSERT)))
  1097.     DBUG_RETURN(1);
  1098.   if (check_one_table_access(thd, SELECT_ACL, table_list))
  1099.     goto err;
  1100.   thd->free_list = 0;
  1101.   thd->query_length=(uint) strlen(tbl_name);
  1102.   thd->query = tbl_name;
  1103.   if ((error = mysqld_dump_create_info(thd, table, -1)))
  1104.   {
  1105.     my_error(ER_GET_ERRNO, MYF(0), my_errno);
  1106.     goto err;
  1107.   }
  1108.   net_flush(&thd->net);
  1109.   if ((error= table->file->dump(thd,fd)))
  1110.     my_error(ER_GET_ERRNO, MYF(0), error);
  1111. err:
  1112.   close_thread_tables(thd);
  1113.   DBUG_RETURN(error);
  1114. }
  1115. #ifndef EMBEDDED_LIBRARY
  1116. /*
  1117.   Read one command from socket and execute it (query or simple command).
  1118.   This function is called in loop from thread function.
  1119.   SYNOPSIS
  1120.     do_command()
  1121.   RETURN VALUE
  1122.     0  success
  1123.     1  request of thread shutdown (see dispatch_command() description)
  1124. */
  1125. bool do_command(THD *thd)
  1126. {
  1127.   char *packet;
  1128.   uint old_timeout;
  1129.   ulong packet_length;
  1130.   NET *net;
  1131.   enum enum_server_command command;
  1132.   DBUG_ENTER("do_command");
  1133.   net= &thd->net;
  1134.   /*
  1135.     indicator of uninitialized lex => normal flow of errors handling
  1136.     (see my_message_sql)
  1137.   */
  1138.   thd->lex->current_select= 0;
  1139.   packet=0;
  1140.   old_timeout=net->read_timeout;
  1141.   // Wait max for 8 hours
  1142.   net->read_timeout=(uint) thd->variables.net_wait_timeout;
  1143.   thd->clear_error(); // Clear error message
  1144.   net_new_transaction(net);
  1145.   if ((packet_length=my_net_read(net)) == packet_error)
  1146.   {
  1147.     DBUG_PRINT("info",("Got error %d reading command from socket %s",
  1148.        net->error,
  1149.        vio_description(net->vio)));
  1150.     /* Check if we can continue without closing the connection */
  1151.     if (net->error != 3)
  1152.     {
  1153.       statistic_increment(aborted_threads,&LOCK_status);
  1154.       DBUG_RETURN(TRUE); // We have to close it.
  1155.     }
  1156.     send_error(thd,net->last_errno,NullS);
  1157.     net->error= 0;
  1158.     DBUG_RETURN(FALSE);
  1159.   }
  1160.   else
  1161.   {
  1162.     packet=(char*) net->read_pos;
  1163.     command = (enum enum_server_command) (uchar) packet[0];
  1164.     if (command >= COM_END)
  1165.       command= COM_END; // Wrong command
  1166.     DBUG_PRINT("info",("Command on %s = %d (%s)",
  1167.        vio_description(net->vio), command,
  1168.        command_name[command]));
  1169.   }
  1170.   net->read_timeout=old_timeout; // restore it
  1171.   /*
  1172.     packet_length contains length of data, as it was stored in packet
  1173.     header. In case of malformed header, packet_length can be zero.
  1174.     If packet_length is not zero, my_net_read ensures that this number
  1175.     of bytes was actually read from network. Additionally my_net_read
  1176.     sets packet[packet_length]= 0 (thus if packet_length == 0,
  1177.     command == packet[0] == COM_SLEEP).
  1178.     In dispatch_command packet[packet_length] points beyond the end of packet.
  1179.   */
  1180.   DBUG_RETURN(dispatch_command(command,thd, packet+1, (uint) packet_length));
  1181. }
  1182. #endif  /* EMBEDDED_LIBRARY */
  1183. /*
  1184.    Perform one connection-level (COM_XXXX) command.
  1185.   SYNOPSIS
  1186.     dispatch_command()
  1187.     thd             connection handle
  1188.     command         type of command to perform 
  1189.     packet          data for the command, packet is always null-terminated
  1190.     packet_length   length of packet + 1 (to show that data is
  1191.                     null-terminated) except for COM_SLEEP, where it
  1192.                     can be zero.
  1193.   RETURN VALUE
  1194.     0   ok
  1195.     1   request of thread shutdown, i. e. if command is
  1196.         COM_QUIT/COM_SHUTDOWN
  1197. */
  1198. bool dispatch_command(enum enum_server_command command, THD *thd,
  1199.       char* packet, uint packet_length)
  1200. {
  1201.   NET *net= &thd->net;
  1202.   bool error= 0;
  1203.   DBUG_ENTER("dispatch_command");
  1204.   thd->command=command;
  1205.   /*
  1206.     Commands which always take a long time are logged into
  1207.     the slow log only if opt_log_slow_admin_statements is set.
  1208.   */
  1209.   thd->enable_slow_log= TRUE;
  1210.   thd->set_time();
  1211.   VOID(pthread_mutex_lock(&LOCK_thread_count));
  1212.   thd->query_id=query_id;
  1213.   if (command != COM_STATISTICS && command != COM_PING)
  1214.     query_id++;
  1215.   thread_running++;
  1216.   /* TODO: set thd->lex->sql_command to SQLCOM_END here */
  1217.   VOID(pthread_mutex_unlock(&LOCK_thread_count));
  1218.   thd->server_status&=
  1219.            ~(SERVER_QUERY_NO_INDEX_USED | SERVER_QUERY_NO_GOOD_INDEX_USED);
  1220.   switch (command) {
  1221.   case COM_INIT_DB:
  1222.   {
  1223.     LEX_STRING tmp;
  1224.     statistic_increment(com_stat[SQLCOM_CHANGE_DB],&LOCK_status);
  1225.     thd->convert_string(&tmp, system_charset_info,
  1226. packet, strlen(packet), thd->charset());
  1227.     if (!mysql_change_db(thd, tmp.str))
  1228.       mysql_log.write(thd,command,"%s",thd->db);
  1229.     break;
  1230.   }
  1231. #ifdef HAVE_REPLICATION
  1232.   case COM_REGISTER_SLAVE:
  1233.   {
  1234.     if (!register_slave(thd, (uchar*)packet, packet_length))
  1235.       send_ok(thd);
  1236.     break;
  1237.   }
  1238. #endif
  1239.   case COM_TABLE_DUMP:
  1240.   {
  1241.     char *db, *tbl_name;
  1242.     uint db_len= *(uchar*) packet;
  1243.     uint tbl_len= *(uchar*) (packet + db_len + 1);
  1244.     statistic_increment(com_other, &LOCK_status);
  1245.     thd->enable_slow_log= opt_log_slow_admin_statements;
  1246.     db= thd->alloc(db_len + tbl_len + 2);
  1247.     tbl_name= strmake(db, packet + 1, db_len)+1;
  1248.     strmake(tbl_name, packet + db_len + 2, tbl_len);
  1249.     if (mysql_table_dump(thd, db, tbl_name, -1))
  1250.       send_error(thd); // dump to NET
  1251.     break;
  1252.   }
  1253.   case COM_CHANGE_USER:
  1254.   {
  1255.     thd->change_user();
  1256.     thd->clear_error();                         // if errors from rollback
  1257.     statistic_increment(com_other, &LOCK_status);
  1258.     char *user= (char*) packet;
  1259.     char *passwd= strend(user)+1;
  1260.     /* 
  1261.       Old clients send null-terminated string ('' for empty string) for
  1262.       password.  New clients send the size (1 byte) + string (not null
  1263.       terminated, so also '' for empty string).
  1264.     */
  1265.     char db_buff[NAME_LEN+1];                 // buffer to store db in utf8 
  1266.     char *db= passwd;
  1267.     uint passwd_len= thd->client_capabilities & CLIENT_SECURE_CONNECTION ? 
  1268.       *passwd++ : strlen(passwd);
  1269.     db+= passwd_len + 1;
  1270. #ifndef EMBEDDED_LIBRARY
  1271.     /* Small check for incomming packet */
  1272.     if ((uint) ((uchar*) db - net->read_pos) > packet_length)
  1273.     {
  1274.       send_error(thd, ER_UNKNOWN_COM_ERROR);
  1275.       break;
  1276.     }
  1277. #endif
  1278.     /* Convert database name to utf8 */
  1279.     uint dummy_errors;
  1280.     db_buff[copy_and_convert(db_buff, sizeof(db_buff)-1,
  1281.                              system_charset_info, db, strlen(db),
  1282.                              thd->charset(), &dummy_errors)]= 0;
  1283.     db= db_buff;
  1284.     /* Save user and privileges */
  1285.     uint save_master_access= thd->master_access;
  1286.     uint save_db_access= thd->db_access;
  1287.     uint save_db_length= thd->db_length;
  1288.     char *save_user= thd->user;
  1289.     char *save_priv_user= thd->priv_user;
  1290.     char *save_db= thd->db;
  1291.     USER_CONN *save_user_connect= thd->user_connect;
  1292.     
  1293.     if (!(thd->user= my_strdup(user, MYF(0))))
  1294.     {
  1295.       thd->user= save_user;
  1296.       send_error(thd, ER_OUT_OF_RESOURCES);
  1297.       break;
  1298.     }
  1299.     /* Clear variables that are allocated */
  1300.     thd->user_connect= 0;
  1301.     int res= check_user(thd, COM_CHANGE_USER, passwd, passwd_len, db, FALSE);
  1302.     if (res)
  1303.     {
  1304.       /* authentification failure, we shall restore old user */
  1305.       if (res > 0)
  1306.         send_error(thd, ER_UNKNOWN_COM_ERROR);
  1307.       x_free(thd->user);
  1308.       thd->user= save_user;
  1309.       thd->priv_user= save_priv_user;
  1310.       thd->user_connect= save_user_connect;
  1311.       thd->master_access= save_master_access;
  1312.       thd->db_access= save_db_access;
  1313.       thd->db= save_db;
  1314.       thd->db_length= save_db_length;
  1315.     }
  1316.     else
  1317.     {
  1318.       /* we've authenticated new user */
  1319.       if (save_user_connect)
  1320. decrease_user_connections(save_user_connect);
  1321.       x_free((gptr) save_db);
  1322.       x_free((gptr) save_user);
  1323.     }
  1324.     break;
  1325.   }
  1326.   case COM_EXECUTE:
  1327.   {
  1328.     mysql_stmt_execute(thd, packet, packet_length);
  1329.     break;
  1330.   }
  1331.   case COM_LONG_DATA:
  1332.   {
  1333.     mysql_stmt_get_longdata(thd, packet, packet_length);
  1334.     break;
  1335.   }
  1336.   case COM_PREPARE:
  1337.   {
  1338.     mysql_stmt_prepare(thd, packet, packet_length);
  1339.     break;
  1340.   }
  1341.   case COM_CLOSE_STMT:
  1342.   {
  1343.     mysql_stmt_free(thd, packet);
  1344.     break;
  1345.   }
  1346.   case COM_RESET_STMT:
  1347.   {
  1348.     mysql_stmt_reset(thd, packet);
  1349.     break;
  1350.   }
  1351.   case COM_QUERY:
  1352.   {
  1353.     if (alloc_query(thd, packet, packet_length))
  1354.       break; // fatal error is set
  1355.     char *packet_end= thd->query + thd->query_length;
  1356.     mysql_log.write(thd,command,"%s",thd->query);
  1357.     DBUG_PRINT("query",("%-.4096s",thd->query));
  1358.     mysql_parse(thd,thd->query, thd->query_length);
  1359.     while (!thd->killed && !thd->is_fatal_error && thd->lex->found_colon)
  1360.     {
  1361.       char *packet= thd->lex->found_colon;
  1362.       /*
  1363.         Multiple queries exits, execute them individually
  1364. in embedded server - just store them to be executed later 
  1365.       */
  1366. #ifndef EMBEDDED_LIBRARY
  1367.       if (thd->lock || thd->open_tables || thd->derived_tables)
  1368.         close_thread_tables(thd);
  1369. #endif
  1370.       ulong length= (ulong)(packet_end-packet);
  1371.       log_slow_statement(thd);
  1372.       /* Remove garbage at start of query */
  1373.       while (my_isspace(thd->charset(), *packet) && length > 0)
  1374.       {
  1375.         packet++;
  1376.         length--;
  1377.       }
  1378.       VOID(pthread_mutex_lock(&LOCK_thread_count));
  1379.       thd->query_length= length;
  1380.       thd->query= packet;
  1381.       thd->query_id= query_id++;
  1382.       thd->set_time(); /* Reset the query start time. */
  1383.       /* TODO: set thd->lex->sql_command to SQLCOM_END here */
  1384.       VOID(pthread_mutex_unlock(&LOCK_thread_count));
  1385. #ifndef EMBEDDED_LIBRARY
  1386.       mysql_parse(thd, packet, length);
  1387. #else
  1388.       /*
  1389. 'packet' can point inside the query_rest's buffer
  1390. so we have to do memmove here
  1391.        */
  1392.       if (thd->query_rest.length() > length)
  1393.       {
  1394. memmove(thd->query_rest.c_ptr(), packet, length);
  1395. thd->query_rest.length(length);
  1396.       }
  1397.       else
  1398. thd->query_rest.copy(packet, length, thd->query_rest.charset());
  1399.       thd->server_status&= ~ (SERVER_QUERY_NO_INDEX_USED |
  1400.                               SERVER_QUERY_NO_GOOD_INDEX_USED);
  1401.       break;
  1402. #endif /*EMBEDDED_LIBRARY*/
  1403.     }
  1404.     if (!(specialflag & SPECIAL_NO_PRIOR))
  1405.       my_pthread_setprio(pthread_self(),WAIT_PRIOR);
  1406.     DBUG_PRINT("info",("query ready"));
  1407.     break;
  1408.   }
  1409.   case COM_FIELD_LIST: // This isn't actually needed
  1410. #ifdef DONT_ALLOW_SHOW_COMMANDS
  1411.     send_error(thd,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */
  1412.     break;
  1413. #else
  1414.   {
  1415.     char *fields, *pend;
  1416.     TABLE_LIST table_list;
  1417.     LEX_STRING conv_name;
  1418.     statistic_increment(com_stat[SQLCOM_SHOW_FIELDS],&LOCK_status);
  1419.     bzero((char*) &table_list,sizeof(table_list));
  1420.     if (!(table_list.db=thd->db))
  1421.     {
  1422.       send_error(thd,ER_NO_DB_ERROR);
  1423.       break;
  1424.     }
  1425.     thd->free_list=0;
  1426.     pend= strend(packet);
  1427.     thd->convert_string(&conv_name, system_charset_info,
  1428. packet, (uint) (pend-packet), thd->charset());
  1429.     table_list.alias= table_list.real_name= conv_name.str;
  1430.     packet= pend+1;
  1431.     thd->query_length= strlen(packet);       // for simplicity: don't optimize
  1432.     if (!(thd->query=fields=thd->memdup(packet,thd->query_length+1)))
  1433.       break;
  1434.     mysql_log.write(thd,command,"%s %s",table_list.real_name,fields);
  1435.     if (lower_case_table_names)
  1436.       my_casedn_str(files_charset_info, table_list.real_name);
  1437.     remove_escape(table_list.real_name); // This can't have wildcards
  1438.     if (check_access(thd,SELECT_ACL,table_list.db,&table_list.grant.privilege,
  1439.      0, 0))
  1440.       break;
  1441.     if (grant_option &&
  1442. check_grant(thd, SELECT_ACL, &table_list, 2, UINT_MAX, 0))
  1443.       break;
  1444.     mysqld_list_fields(thd,&table_list,fields);
  1445.     free_items(thd->free_list);
  1446.     thd->free_list= 0;
  1447.     break;
  1448.   }
  1449. #endif
  1450.   case COM_QUIT:
  1451.     /* We don't calculate statistics for this command */
  1452.     mysql_log.write(thd,command,NullS);
  1453.     net->error=0; // Don't give 'abort' message
  1454.     error=TRUE; // End server
  1455.     break;
  1456.   case COM_CREATE_DB: // QQ: To be removed
  1457.     {
  1458.       char *db=thd->strdup(packet), *alias;
  1459.       HA_CREATE_INFO create_info;
  1460.       statistic_increment(com_stat[SQLCOM_CREATE_DB],&LOCK_status);
  1461.       // null test to handle EOM
  1462.       if (!db || !(alias= thd->strdup(db)) || check_db_name(db))
  1463.       {
  1464. net_printf(thd,ER_WRONG_DB_NAME, db ? db : "NULL");
  1465. break;
  1466.       }
  1467.       if (check_access(thd,CREATE_ACL,db,0,1,0))
  1468. break;
  1469.       mysql_log.write(thd,command,packet);
  1470.       bzero(&create_info, sizeof(create_info));
  1471.       if (mysql_create_db(thd, (lower_case_table_names == 2 ? alias : db),
  1472.                           &create_info, 0) < 0)
  1473.         send_error(thd, thd->killed ? ER_SERVER_SHUTDOWN : 0);
  1474.       break;
  1475.     }
  1476.   case COM_DROP_DB: // QQ: To be removed
  1477.     {
  1478.       statistic_increment(com_stat[SQLCOM_DROP_DB],&LOCK_status);
  1479.       char *db=thd->strdup(packet), *alias;
  1480.       // null test to handle EOM
  1481.       if (!db || !(alias= thd->strdup(db)) || check_db_name(db))
  1482.       {
  1483. net_printf(thd,ER_WRONG_DB_NAME, db ? db : "NULL");
  1484. break;
  1485.       }
  1486.       if (check_access(thd,DROP_ACL,db,0,1,0))
  1487. break;
  1488.       if (thd->locked_tables || thd->active_transaction())
  1489.       {
  1490. send_error(thd,ER_LOCK_OR_ACTIVE_TRANSACTION);
  1491. break;
  1492.       }
  1493.       mysql_log.write(thd,command,db);
  1494.       if (mysql_rm_db(thd, (lower_case_table_names == 2 ? alias : db),
  1495.                       0, 0) < 0)
  1496.         send_error(thd, thd->killed ? ER_SERVER_SHUTDOWN : 0);
  1497.       break;
  1498.     }
  1499. #ifndef EMBEDDED_LIBRARY
  1500.   case COM_BINLOG_DUMP:
  1501.     {
  1502.       ulong pos;
  1503.       ushort flags;
  1504.       uint32 slave_server_id;
  1505.       statistic_increment(com_other,&LOCK_status);
  1506.       thd->enable_slow_log= opt_log_slow_admin_statements;
  1507.       if (check_global_access(thd, REPL_SLAVE_ACL))
  1508. break;
  1509.       /* TODO: The following has to be changed to an 8 byte integer */
  1510.       pos = uint4korr(packet);
  1511.       flags = uint2korr(packet + 4);
  1512.       thd->server_id=0; /* avoid suicide */
  1513.       if ((slave_server_id= uint4korr(packet+6))) // mysqlbinlog.server_id==0
  1514. kill_zombie_dump_threads(slave_server_id);
  1515.       thd->server_id = slave_server_id;
  1516.       mysql_log.write(thd, command, "Log: '%s'  Pos: %ld", packet+10,
  1517.                       (long) pos);
  1518.       mysql_binlog_send(thd, thd->strdup(packet + 10), (my_off_t) pos, flags);
  1519.       unregister_slave(thd,1,1);
  1520.       // fake COM_QUIT -- if we get here, the thread needs to terminate
  1521.       error = TRUE;
  1522.       net->error = 0;
  1523.       break;
  1524.     }
  1525. #endif
  1526.   case COM_REFRESH:
  1527.     {
  1528.       statistic_increment(com_stat[SQLCOM_FLUSH],&LOCK_status);
  1529.       ulong options= (ulong) (uchar) packet[0];
  1530.       if (check_global_access(thd,RELOAD_ACL))
  1531. break;
  1532.       mysql_log.write(thd,command,NullS);
  1533.       if (reload_acl_and_cache(thd, options, (TABLE_LIST*) 0, NULL))
  1534.         send_error(thd, 0);
  1535.       else
  1536.         send_ok(thd);
  1537.       break;
  1538.     }
  1539. #ifndef EMBEDDED_LIBRARY
  1540.   case COM_SHUTDOWN:
  1541.   {
  1542.     statistic_increment(com_other,&LOCK_status);
  1543.     if (check_global_access(thd,SHUTDOWN_ACL))
  1544.       break; /* purecov: inspected */
  1545.     /*
  1546.       If the client is < 4.1.3, it is going to send us no argument; then
  1547.       packet_length is 1, packet[0] is the end 0 of the packet. Note that
  1548.       SHUTDOWN_DEFAULT is 0. If client is >= 4.1.3, the shutdown level is in
  1549.       packet[0].
  1550.     */
  1551.     enum mysql_enum_shutdown_level level=
  1552.       (enum mysql_enum_shutdown_level) (uchar) packet[0];
  1553.     DBUG_PRINT("quit",("Got shutdown command for level %u", level));
  1554.     if (level == SHUTDOWN_DEFAULT)
  1555.       level= SHUTDOWN_WAIT_ALL_BUFFERS; // soon default will be configurable
  1556.     else if (level != SHUTDOWN_WAIT_ALL_BUFFERS)
  1557.     {
  1558.       my_error(ER_NOT_SUPPORTED_YET, MYF(0), "this shutdown level");
  1559.       send_error(thd);
  1560.       break;
  1561.     }
  1562.     DBUG_PRINT("quit",("Got shutdown command for level %u", level));
  1563.     mysql_log.write(thd,command,NullS);
  1564.     send_eof(thd);
  1565. #ifdef __WIN__
  1566.     sleep(1); // must wait after eof()
  1567. #endif
  1568. #ifndef OS2
  1569.     send_eof(thd); // This is for 'quit request'
  1570. #endif
  1571.     close_connection(thd, 0, 1);
  1572.     close_thread_tables(thd); // Free before kill
  1573.     free_root(thd->mem_root,MYF(0));
  1574.     free_root(&thd->transaction.mem_root,MYF(0));
  1575.     kill_mysql();
  1576.     error=TRUE;
  1577.     break;
  1578.   }
  1579. #endif
  1580.   case COM_STATISTICS:
  1581.   {
  1582.     mysql_log.write(thd,command,NullS);
  1583.     statistic_increment(com_stat[SQLCOM_SHOW_STATUS],&LOCK_status);
  1584. #ifndef EMBEDDED_LIBRARY
  1585.     char buff[200];
  1586. #else
  1587.     char *buff= thd->net.last_error;
  1588. #endif
  1589.     ulong uptime = (ulong) (thd->start_time - start_time);
  1590.     sprintf((char*) buff,
  1591.     "Uptime: %ld  Threads: %d  Questions: %lu  Slow queries: %ld  Opens: %ld  Flush tables: %ld  Open tables: %u  Queries per second avg: %.3f",
  1592.     uptime,
  1593.     (int) thread_count,thd->query_id,long_query_count,
  1594.     opened_tables,refresh_version, cached_tables(),
  1595.     uptime ? (float)thd->query_id/(float)uptime : 0);
  1596. #ifdef SAFEMALLOC
  1597.     if (sf_malloc_cur_memory) // Using SAFEMALLOC
  1598.       sprintf(strend(buff), "  Memory in use: %ldK  Max memory used: %ldK",
  1599.       (sf_malloc_cur_memory+1023L)/1024L,
  1600.       (sf_malloc_max_memory+1023L)/1024L);
  1601. #endif
  1602. #ifndef EMBEDDED_LIBRARY
  1603.     VOID(my_net_write(net, buff,(uint) strlen(buff)));
  1604.     VOID(net_flush(net));
  1605. #endif
  1606.     break;
  1607.   }
  1608.   case COM_PING:
  1609.     statistic_increment(com_other,&LOCK_status);
  1610.     send_ok(thd); // Tell client we are alive
  1611.     break;
  1612.   case COM_PROCESS_INFO:
  1613.     statistic_increment(com_stat[SQLCOM_SHOW_PROCESSLIST],&LOCK_status);
  1614.     if (!thd->priv_user[0] && check_global_access(thd,PROCESS_ACL))
  1615.       break;
  1616.     mysql_log.write(thd,command,NullS);
  1617.     mysqld_list_processes(thd,
  1618.   thd->master_access & PROCESS_ACL ? 
  1619.   NullS : thd->priv_user, 0);
  1620.     break;
  1621.   case COM_PROCESS_KILL:
  1622.   {
  1623.     statistic_increment(com_stat[SQLCOM_KILL],&LOCK_status);
  1624.     ulong id=(ulong) uint4korr(packet);
  1625.     kill_one_thread(thd,id);
  1626.     break;
  1627.   }
  1628.   case COM_SET_OPTION:
  1629.   {
  1630.     statistic_increment(com_stat[SQLCOM_SET_OPTION], &LOCK_status);
  1631.     enum_mysql_set_option command= (enum_mysql_set_option) uint2korr(packet);
  1632.     switch (command) {
  1633.     case MYSQL_OPTION_MULTI_STATEMENTS_ON:
  1634.       thd->client_capabilities|= CLIENT_MULTI_STATEMENTS;
  1635.       send_eof(thd);
  1636.       break;
  1637.     case MYSQL_OPTION_MULTI_STATEMENTS_OFF:
  1638.       thd->client_capabilities&= ~CLIENT_MULTI_STATEMENTS;
  1639.       send_eof(thd);
  1640.       break;
  1641.     default:
  1642.       send_error(thd, ER_UNKNOWN_COM_ERROR);
  1643.       break;
  1644.     }
  1645.     break;
  1646.   }
  1647.   case COM_DEBUG:
  1648.     statistic_increment(com_other,&LOCK_status);
  1649.     if (check_global_access(thd, SUPER_ACL))
  1650.       break; /* purecov: inspected */
  1651.     mysql_print_status(thd);
  1652.     mysql_log.write(thd,command,NullS);
  1653.     send_eof(thd);
  1654.     break;
  1655.   case COM_SLEEP:
  1656.   case COM_CONNECT: // Impossible here
  1657.   case COM_TIME: // Impossible from client
  1658.   case COM_DELAYED_INSERT:
  1659.   case COM_END:
  1660.   default:
  1661.     send_error(thd, ER_UNKNOWN_COM_ERROR);
  1662.     break;
  1663.   }
  1664.   if (thd->lock || thd->open_tables || thd->derived_tables)
  1665.   {
  1666.     thd->proc_info="closing tables";
  1667.     close_thread_tables(thd); /* Free tables */
  1668.   }
  1669.   if (thd->is_fatal_error)
  1670.     send_error(thd,0); // End of memory ?
  1671.   log_slow_statement(thd);
  1672.   thd->proc_info="cleaning up";
  1673.   VOID(pthread_mutex_lock(&LOCK_thread_count)); // For process list
  1674.   thd->proc_info=0;
  1675.   thd->command=COM_SLEEP;
  1676.   thd->query=0;
  1677.   thd->query_length=0;
  1678.   thread_running--;
  1679.   VOID(pthread_mutex_unlock(&LOCK_thread_count));
  1680.   thd->packet.shrink(thd->variables.net_buffer_length); // Reclaim some memory
  1681.   free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC));
  1682.   DBUG_RETURN(error);
  1683. }
  1684. void log_slow_statement(THD *thd)
  1685. {
  1686.   time_t start_of_query=thd->start_time;
  1687.   thd->end_time(); // Set start time
  1688.   /*
  1689.     Do not log administrative statements unless the appropriate option is
  1690.     set; do not log into slow log if reading from backup.
  1691.   */
  1692.   if (thd->enable_slow_log && !thd->user_time)
  1693.   {
  1694.     thd->proc_info="logging slow query";
  1695.     if ((ulong) (thd->start_time - thd->time_after_lock) >
  1696. thd->variables.long_query_time ||
  1697. ((thd->server_status &
  1698.   (SERVER_QUERY_NO_INDEX_USED | SERVER_QUERY_NO_GOOD_INDEX_USED)) &&
  1699.  (specialflag & SPECIAL_LOG_QUERIES_NOT_USING_INDEXES)))
  1700.     {
  1701.       long_query_count++;
  1702.       mysql_slow_log.write(thd, thd->query, thd->query_length, start_of_query);
  1703.     }
  1704.   }
  1705. }
  1706. /*
  1707.   Read query from packet and store in thd->query
  1708.   Used in COM_QUERY and COM_PREPARE
  1709.   DESCRIPTION
  1710.     Sets the following THD variables:
  1711.       query
  1712.       query_length
  1713.   RETURN VALUES
  1714.     0 ok
  1715.     1 error;  In this case thd->fatal_error is set
  1716. */
  1717. bool alloc_query(THD *thd, char *packet, ulong packet_length)
  1718. {
  1719.   packet_length--; // Remove end null
  1720.   /* Remove garbage at start and end of query */
  1721.   while (my_isspace(thd->charset(),packet[0]) && packet_length > 0)
  1722.   {
  1723.     packet++;
  1724.     packet_length--;
  1725.   }
  1726.   char *pos=packet+packet_length; // Point at end null
  1727.   while (packet_length > 0 &&
  1728.  (pos[-1] == ';' || my_isspace(thd->charset() ,pos[-1])))
  1729.   {
  1730.     pos--;
  1731.     packet_length--;
  1732.   }
  1733.   /* We must allocate some extra memory for query cache */
  1734.   thd->query_length= 0;                        // Extra safety: Avoid races
  1735.   if (!(thd->query= (char*) thd->memdup_w_gap((gptr) (packet),
  1736.       packet_length,
  1737.       thd->db_length+ 1 +
  1738.       QUERY_CACHE_FLAGS_SIZE)))
  1739.     return 1;
  1740.   thd->query[packet_length]=0;
  1741.   thd->query_length= packet_length;
  1742.   /* Reclaim some memory */
  1743.   thd->packet.shrink(thd->variables.net_buffer_length);
  1744.   thd->convert_buffer.shrink(thd->variables.net_buffer_length);
  1745.   if (!(specialflag & SPECIAL_NO_PRIOR))
  1746.     my_pthread_setprio(pthread_self(),QUERY_PRIOR);
  1747.   return 0;
  1748. }
  1749. static void reset_one_shot_variables(THD *thd) 
  1750. {
  1751.   thd->variables.character_set_client=
  1752.     global_system_variables.character_set_client;
  1753.   thd->variables.collation_connection=
  1754.     global_system_variables.collation_connection;
  1755.   thd->variables.collation_database=
  1756.     global_system_variables.collation_database;
  1757.   thd->variables.collation_server=
  1758.     global_system_variables.collation_server;
  1759.   thd->update_charset();
  1760.   thd->variables.time_zone=
  1761.     global_system_variables.time_zone;
  1762.   thd->one_shot_set= 0;
  1763. }
  1764. /****************************************************************************
  1765. ** mysql_execute_command
  1766. ** Execute command saved in thd and current_lex->sql_command
  1767. ****************************************************************************/
  1768. void
  1769. mysql_execute_command(THD *thd)
  1770. {
  1771.   int res= 0;
  1772.   LEX *lex= thd->lex;
  1773.   SELECT_LEX *select_lex= &lex->select_lex;
  1774.   TABLE_LIST *tables= (TABLE_LIST*) select_lex->table_list.first;
  1775.   SELECT_LEX_UNIT *unit= &lex->unit;
  1776.   DBUG_ENTER("mysql_execute_command");
  1777.   /*
  1778.     Reset warning count for each query that uses tables
  1779.     A better approach would be to reset this for any commands
  1780.     that is not a SHOW command or a select that only access local
  1781.     variables, but for now this is probably good enough.
  1782.   */
  1783.   if (tables || &lex->select_lex != lex->all_selects_list ||
  1784.       lex->time_zone_tables_used)
  1785.     mysql_reset_errors(thd);
  1786.   /*
  1787.     When subselects or time_zone info is used in a query
  1788.     we create a new TABLE_LIST containing all referenced tables
  1789.     and set local variable 'tables' to point to this list.
  1790.   */
  1791.   if ((&lex->select_lex != lex->all_selects_list ||
  1792.        lex->time_zone_tables_used) &&
  1793.       lex->unit.create_total_list(thd, lex, &tables))
  1794.     DBUG_VOID_RETURN;
  1795. #ifdef HAVE_REPLICATION
  1796.   if (thd->slave_thread)
  1797.   {
  1798.     /*
  1799.       Check if statment should be skipped because of slave filtering
  1800.       rules
  1801.       Exceptions are:
  1802.       - UPDATE MULTI: For this statement, we want to check the filtering
  1803.         rules later in the code
  1804.       - SET: we always execute it (Not that many SET commands exists in
  1805.         the binary log anyway -- only 4.1 masters write SET statements,
  1806. in 5.0 there are no SET statements in the binary log)
  1807.       - DROP TEMPORARY TABLE IF EXISTS: we always execute it (otherwise we
  1808.         have stale files on slave caused by exclusion of one tmp table).
  1809.     */
  1810.     if (!(lex->sql_command == SQLCOM_UPDATE_MULTI) &&
  1811. !(lex->sql_command == SQLCOM_SET_OPTION) &&
  1812. !(lex->sql_command == SQLCOM_DROP_TABLE &&
  1813.           lex->drop_temporary && lex->drop_if_exists) &&
  1814.         all_tables_not_ok(thd,tables))
  1815.     {
  1816.       /* we warn the slave SQL thread */
  1817.       my_error(ER_SLAVE_IGNORED_TABLE, MYF(0));
  1818.       reset_one_shot_variables(thd);
  1819.       DBUG_VOID_RETURN;
  1820.     }
  1821. #ifndef TO_BE_DELETED
  1822.     /*
  1823.       This is a workaround to deal with the shortcoming in 3.23.44-3.23.46
  1824.       masters in RELEASE_LOCK() logging. We re-write SELECT RELEASE_LOCK()
  1825.       as DO RELEASE_LOCK()
  1826.     */
  1827.     if (lex->sql_command == SQLCOM_SELECT)
  1828.     {
  1829.       lex->sql_command = SQLCOM_DO;
  1830.       lex->insert_list = &select_lex->item_list;
  1831.     }
  1832. #endif
  1833.   }
  1834. #endif /* HAVE_REPLICATION */
  1835.   /*
  1836.     When option readonly is set deny operations which change tables.
  1837.     Except for the replication thread and the 'super' users.
  1838.   */
  1839.   if (opt_readonly &&
  1840.       !(thd->slave_thread || (thd->master_access & SUPER_ACL)) &&
  1841.       (uc_update_queries[lex->sql_command] > 0))
  1842.   {
  1843.     net_printf(thd, ER_OPTION_PREVENTS_STATEMENT, "--read-only");
  1844.     DBUG_VOID_RETURN;
  1845.   }
  1846.   statistic_increment(com_stat[lex->sql_command],&LOCK_status);
  1847.   switch (lex->sql_command) {
  1848.   case SQLCOM_SELECT:
  1849.   {
  1850.     /* assign global limit variable if limit is not given */
  1851.     {
  1852.       SELECT_LEX *param= lex->unit.global_parameters;
  1853.       if (!param->explicit_limit)
  1854. param->select_limit= thd->variables.select_limit;
  1855.     }
  1856.     select_result *result=lex->result;
  1857.     if (tables)
  1858.     {
  1859.       res=check_table_access(thd,
  1860.      lex->exchange ? SELECT_ACL | FILE_ACL :
  1861.      SELECT_ACL,
  1862.      tables,0);
  1863.     }
  1864.     else
  1865.       res=check_access(thd, lex->exchange ? SELECT_ACL | FILE_ACL : SELECT_ACL,
  1866.        any_db,0,0,0);
  1867.     if (res)
  1868.     {
  1869.       res=0;
  1870.       break; // Error message is given
  1871.     }
  1872.     /* 
  1873.        In case of single SELECT unit->global_parameters points on first SELECT
  1874.        TODO: move counters to SELECT_LEX
  1875.     */
  1876.     unit->offset_limit_cnt= (ha_rows) unit->global_parameters->offset_limit;
  1877.     unit->select_limit_cnt= (ha_rows) (unit->global_parameters->select_limit+
  1878.       unit->global_parameters->offset_limit);
  1879.     if (unit->select_limit_cnt <
  1880. (ha_rows) unit->global_parameters->select_limit)
  1881.       unit->select_limit_cnt= HA_POS_ERROR; // no limit
  1882.     if (unit->select_limit_cnt == HA_POS_ERROR && !select_lex->next_select())
  1883.       select_lex->options&= ~OPTION_FOUND_ROWS;
  1884.     if (!(res=open_and_lock_tables(thd,tables)))
  1885.     {
  1886.       if (lex->describe)
  1887.       {
  1888. if (!(result= new select_send()))
  1889. {
  1890.   send_error(thd, ER_OUT_OF_RESOURCES);
  1891.   DBUG_VOID_RETURN;
  1892. }
  1893. else
  1894.   thd->send_explain_fields(result);
  1895. res= mysql_explain_union(thd, &thd->lex->unit, result);
  1896. if (lex->describe & DESCRIBE_EXTENDED)
  1897. {
  1898.   char buff[1024];
  1899.   String str(buff,(uint32) sizeof(buff), system_charset_info);
  1900.   str.length(0);
  1901.   thd->lex->unit.print(&str);
  1902.   str.append('');
  1903.   push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
  1904.        ER_YES, str.ptr());
  1905. }
  1906. result->send_eof();
  1907.         delete result;
  1908.       }
  1909.       else
  1910.       {
  1911. if (!result && !(result= new select_send()))
  1912. {
  1913.   res= -1;
  1914.   break;
  1915. }
  1916. query_cache_store_query(thd, tables);
  1917. res= handle_select(thd, lex, result);
  1918.         if (result != lex->result)
  1919.           delete result;
  1920.       }
  1921.     }
  1922.     break;
  1923.   }
  1924.   case SQLCOM_PREPARE:
  1925.   {
  1926.     char *query_str;
  1927.     uint query_len;
  1928.     if (lex->prepared_stmt_code_is_varref)
  1929.     {
  1930.       /* This is PREPARE stmt FROM @var. */
  1931.       String str;
  1932.       CHARSET_INFO *to_cs= thd->variables.collation_connection;
  1933.       bool need_conversion;
  1934.       user_var_entry *entry;
  1935.       String *pstr= &str;
  1936.       uint32 unused;
  1937.       /*
  1938.         Convert @var contents to string in connection character set. Although
  1939.         it is known that int/real/NULL value cannot be a valid query we still
  1940.         convert it for error messages to uniform.
  1941.       */
  1942.       if ((entry=
  1943.              (user_var_entry*)hash_search(&thd->user_vars,
  1944.                                           (byte*)lex->prepared_stmt_code.str,
  1945.                                           lex->prepared_stmt_code.length))
  1946.           && entry->value)
  1947.       {
  1948.         my_bool is_var_null;
  1949.         pstr= entry->val_str(&is_var_null, &str, NOT_FIXED_DEC);
  1950.         /*
  1951.           NULL value of variable checked early as entry->value so here
  1952.           we can't get NULL in normal conditions
  1953.         */
  1954.         DBUG_ASSERT(!is_var_null);
  1955.         if (!pstr)
  1956.         {
  1957.           res= -1;
  1958.           break;      // EOM (error should be reported by allocator)
  1959.         }
  1960.       }
  1961.       else
  1962.       {
  1963.         /*
  1964.           variable absent or equal to NULL, so we need to set variable to
  1965.           something reasonable to get readable error message during parsing
  1966.         */
  1967.         str.set("NULL", 4, &my_charset_latin1);
  1968.       }
  1969.       need_conversion=
  1970.         String::needs_conversion(pstr->length(), pstr->charset(),
  1971.                                  to_cs, &unused);
  1972.       query_len= need_conversion? (pstr->length() * to_cs->mbmaxlen) :
  1973.                                   pstr->length();
  1974.       if (!(query_str= alloc_root(thd->mem_root, query_len+1)))
  1975.       {
  1976.         res= -1;
  1977.         break;        // EOM (error should be reported by allocator)
  1978.       }
  1979.       if (need_conversion)
  1980.       {
  1981.         uint dummy_errors;
  1982.         query_len= copy_and_convert(query_str, query_len, to_cs,
  1983.                                     pstr->ptr(), pstr->length(),
  1984.                                     pstr->charset(), &dummy_errors);
  1985.       }
  1986.       else
  1987.         memcpy(query_str, pstr->ptr(), pstr->length());
  1988.       query_str[query_len]= 0;
  1989.     }
  1990.     else
  1991.     {
  1992.       query_str= lex->prepared_stmt_code.str;
  1993.       query_len= lex->prepared_stmt_code.length;
  1994.       DBUG_PRINT("info", ("PREPARE: %.*s FROM '%.*s' n",
  1995.                           lex->prepared_stmt_name.length,
  1996.                           lex->prepared_stmt_name.str,
  1997.                           query_len, query_str));
  1998.     }
  1999.     thd->command= COM_PREPARE;
  2000.     if (!mysql_stmt_prepare(thd, query_str, query_len + 1,
  2001.                             &lex->prepared_stmt_name))
  2002.       send_ok(thd, 0L, 0L, "Statement prepared");
  2003.     break;
  2004.   }
  2005.   case SQLCOM_EXECUTE:
  2006.   {
  2007.     DBUG_PRINT("info", ("EXECUTE: %.*sn",
  2008.                         lex->prepared_stmt_name.length,
  2009.                         lex->prepared_stmt_name.str));
  2010.     mysql_sql_stmt_execute(thd, &lex->prepared_stmt_name);
  2011.     lex->prepared_stmt_params.empty();
  2012.     break;
  2013.   }
  2014.   case SQLCOM_DEALLOCATE_PREPARE:
  2015.   {
  2016.     Statement* stmt;
  2017.     DBUG_PRINT("info", ("DEALLOCATE PREPARE: %.*sn", 
  2018.                         lex->prepared_stmt_name.length,
  2019.                         lex->prepared_stmt_name.str));
  2020.     /* We account deallocate in the same manner as mysql_stmt_close */
  2021.     statistic_increment(com_stmt_close, &LOCK_status);
  2022.     if ((stmt= thd->stmt_map.find_by_name(&lex->prepared_stmt_name)))
  2023.     {
  2024.       thd->stmt_map.erase(stmt);
  2025.       send_ok(thd);
  2026.     }
  2027.     else
  2028.     {
  2029.       res= -1;
  2030.       my_error(ER_UNKNOWN_STMT_HANDLER, MYF(0),
  2031.                lex->prepared_stmt_name.length, lex->prepared_stmt_name.str,
  2032.                "DEALLOCATE PREPARE");
  2033.     }
  2034.     break;
  2035.   }
  2036.   case SQLCOM_DO:
  2037.     if (tables && ((res= check_table_access(thd, SELECT_ACL, tables,0)) ||
  2038.    (res= open_and_lock_tables(thd,tables))))
  2039. break;
  2040.     res= mysql_do(thd, *lex->insert_list);
  2041.     if (thd->net.report_error)
  2042.       res= -1;
  2043.     break;
  2044.   case SQLCOM_EMPTY_QUERY:
  2045.     send_ok(thd);
  2046.     break;
  2047.   case SQLCOM_HELP:
  2048.     res= mysqld_help(thd,lex->help_arg);
  2049.     break;
  2050. #ifndef EMBEDDED_LIBRARY
  2051.   case SQLCOM_PURGE:
  2052.   {
  2053.     if (check_global_access(thd, SUPER_ACL))
  2054.       goto error;
  2055.     // PURGE MASTER LOGS TO 'file'
  2056.     res = purge_master_logs(thd, lex->to_log);
  2057.     break;
  2058.   }
  2059.   case SQLCOM_PURGE_BEFORE:
  2060.   {
  2061.     if (check_global_access(thd, SUPER_ACL))
  2062.       goto error;
  2063.     // PURGE MASTER LOGS BEFORE 'data'
  2064.     res = purge_master_logs_before_date(thd, lex->purge_time);
  2065.     break;
  2066.   }
  2067. #endif
  2068.   case SQLCOM_SHOW_WARNS:
  2069.   {
  2070.     res= mysqld_show_warnings(thd, (ulong)
  2071.       ((1L << (uint) MYSQL_ERROR::WARN_LEVEL_NOTE) |
  2072.        (1L << (uint) MYSQL_ERROR::WARN_LEVEL_WARN) |
  2073.        (1L << (uint) MYSQL_ERROR::WARN_LEVEL_ERROR)
  2074.        ));
  2075.     break;
  2076.   }
  2077.   case SQLCOM_SHOW_ERRORS:
  2078.   {
  2079.     res= mysqld_show_warnings(thd, (ulong)
  2080.       (1L << (uint) MYSQL_ERROR::WARN_LEVEL_ERROR));
  2081.     break;
  2082.   }
  2083.   case SQLCOM_SHOW_NEW_MASTER:
  2084.   {
  2085.     if (check_global_access(thd, REPL_SLAVE_ACL))
  2086.       goto error;
  2087.     /* This query don't work now. See comment in repl_failsafe.cc */
  2088. #ifndef WORKING_NEW_MASTER
  2089.     net_printf(thd, ER_NOT_SUPPORTED_YET, "SHOW NEW MASTER");
  2090.     res= 1;
  2091. #else
  2092.     res = show_new_master(thd);
  2093. #endif
  2094.     break;
  2095.   }
  2096. #ifdef HAVE_REPLICATION
  2097.   case SQLCOM_SHOW_SLAVE_HOSTS:
  2098.   {
  2099.     if (check_global_access(thd, REPL_SLAVE_ACL))
  2100.       goto error;
  2101.     res = show_slave_hosts(thd);
  2102.     break;
  2103.   }
  2104.   case SQLCOM_SHOW_BINLOG_EVENTS:
  2105.   {
  2106.     if (check_global_access(thd, REPL_SLAVE_ACL))
  2107.       goto error;
  2108.     res = show_binlog_events(thd);
  2109.     break;
  2110.   }
  2111. #endif
  2112.   case SQLCOM_BACKUP_TABLE:
  2113.   {
  2114.     if (check_db_used(thd,tables) ||
  2115. check_table_access(thd,SELECT_ACL, tables,0) ||
  2116. check_global_access(thd, FILE_ACL))
  2117.       goto error; /* purecov: inspected */
  2118.     thd->enable_slow_log= opt_log_slow_admin_statements;
  2119.     res = mysql_backup_table(thd, tables);
  2120.     break;
  2121.   }
  2122.   case SQLCOM_RESTORE_TABLE:
  2123.   {
  2124.     if (check_db_used(thd,tables) ||
  2125. check_table_access(thd, INSERT_ACL, tables,0) ||
  2126. check_global_access(thd, FILE_ACL))
  2127.       goto error; /* purecov: inspected */
  2128.     thd->enable_slow_log= opt_log_slow_admin_statements;
  2129.     res = mysql_restore_table(thd, tables);
  2130.     break;
  2131.   }
  2132.   case SQLCOM_ASSIGN_TO_KEYCACHE:
  2133.   {
  2134.     if (check_db_used(thd, tables) ||
  2135.         check_access(thd, INDEX_ACL, tables->db,
  2136.                      &tables->grant.privilege, 0, 0))
  2137.       goto error;
  2138.     res= mysql_assign_to_keycache(thd, tables, &lex->name_and_length);
  2139.     break;
  2140.   }
  2141.   case SQLCOM_PRELOAD_KEYS:
  2142.   {
  2143.     if (check_db_used(thd, tables) ||
  2144. check_access(thd, INDEX_ACL, tables->db,
  2145.                      &tables->grant.privilege, 0, 0))
  2146.       goto error;
  2147.     res = mysql_preload_keys(thd, tables);
  2148.     break;
  2149.   }
  2150. #ifdef HAVE_REPLICATION
  2151.   case SQLCOM_CHANGE_MASTER:
  2152.   {
  2153.     if (check_global_access(thd, SUPER_ACL))
  2154.       goto error;
  2155.     pthread_mutex_lock(&LOCK_active_mi);
  2156.     res = change_master(thd,active_mi);
  2157.     pthread_mutex_unlock(&LOCK_active_mi);
  2158.     break;
  2159.   }
  2160.   case SQLCOM_SHOW_SLAVE_STAT:
  2161.   {
  2162.     /* Accept one of two privileges */
  2163.     if (check_global_access(thd, SUPER_ACL | REPL_CLIENT_ACL))
  2164.       goto error;
  2165.     pthread_mutex_lock(&LOCK_active_mi);
  2166.     res = show_master_info(thd,active_mi);
  2167.     pthread_mutex_unlock(&LOCK_active_mi);
  2168.     break;
  2169.   }
  2170.   case SQLCOM_SHOW_MASTER_STAT:
  2171.   {
  2172.     /* Accept one of two privileges */
  2173.     if (check_global_access(thd, SUPER_ACL | REPL_CLIENT_ACL))
  2174.       goto error;
  2175.     res = show_binlog_info(thd);
  2176.     break;
  2177.   }
  2178.   case SQLCOM_LOAD_MASTER_DATA: // sync with master
  2179.     if (check_global_access(thd, SUPER_ACL))
  2180.       goto error;
  2181.     if (end_active_trans(thd))
  2182.       res= -1;
  2183.     else
  2184.       res = load_master_data(thd);
  2185.     break;
  2186. #endif /* HAVE_REPLICATION */
  2187. #ifdef HAVE_NDBCLUSTER_DB
  2188.   case SQLCOM_SHOW_NDBCLUSTER_STATUS:
  2189.     {
  2190.       res = ndbcluster_show_status(thd);
  2191.       break;
  2192.     }
  2193. #endif
  2194. #ifdef HAVE_INNOBASE_DB
  2195.   case SQLCOM_SHOW_INNODB_STATUS:
  2196.     {
  2197.       if (check_global_access(thd, SUPER_ACL))
  2198. goto error;
  2199.       res = innodb_show_status(thd);
  2200.       break;
  2201.     }
  2202. #endif
  2203. #ifdef HAVE_REPLICATION
  2204.   case SQLCOM_LOAD_MASTER_TABLE:
  2205.   {
  2206.     if (!tables->db)
  2207.       tables->db=thd->db;
  2208.     if (check_access(thd,CREATE_ACL,tables->db,&tables->grant.privilege,0,0))
  2209.       goto error; /* purecov: inspected */
  2210.     if (grant_option)
  2211.     {
  2212.       /* Check that the first table has CREATE privilege */
  2213.       if (check_grant(thd, CREATE_ACL, tables, 0, 1, 0))
  2214. goto error;
  2215.     }
  2216.     if (strlen(tables->real_name) > NAME_LEN)
  2217.     {
  2218.       net_printf(thd,ER_WRONG_TABLE_NAME, tables->real_name);
  2219.       break;
  2220.     }
  2221.     pthread_mutex_lock(&LOCK_active_mi);
  2222.     /*
  2223.       fetch_master_table will send the error to the client on failure.
  2224.       Give error if the table already exists.
  2225.     */
  2226.     if (!fetch_master_table(thd, tables->db, tables->real_name,
  2227.     active_mi, 0, 0))
  2228.     {
  2229.       send_ok(thd);
  2230.     }
  2231.     pthread_mutex_unlock(&LOCK_active_mi);
  2232.     break;
  2233.   }
  2234. #endif /* HAVE_REPLICATION */
  2235.   case SQLCOM_CREATE_TABLE:
  2236.   {
  2237.     /* If CREATE TABLE of non-temporary table, do implicit commit */
  2238.     if (!(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE))
  2239.     {
  2240.       if (end_active_trans(thd))
  2241.       {
  2242. res= -1;
  2243. break;
  2244.       }
  2245.     }
  2246.     else 
  2247.     {
  2248.       /* So that CREATE TEMPORARY TABLE gets to binlog at commit/rollback */
  2249.       thd->options|= OPTION_STATUS_NO_TRANS_UPDATE;
  2250.     }
  2251.     /* Skip first table, which is the table we are creating */
  2252.     TABLE_LIST *create_table, *create_table_local;
  2253.     tables= lex->unlink_first_table(tables, &create_table,
  2254.     &create_table_local);
  2255.     if ((res= create_table_precheck(thd, tables, create_table)))
  2256.       goto unsent_create_error;
  2257. #ifndef HAVE_READLINK
  2258.     lex->create_info.data_file_name=lex->create_info.index_file_name=0;
  2259. #else
  2260.     /* Fix names if symlinked tables */
  2261.     if (append_file_to_dir(thd, &lex->create_info.data_file_name,
  2262.    create_table->real_name) ||
  2263. append_file_to_dir(thd,&lex->create_info.index_file_name,
  2264.    create_table->real_name))
  2265.     {
  2266.       res=-1;
  2267.       goto unsent_create_error;
  2268.     }
  2269. #endif
  2270.     /*
  2271.       If we are using SET CHARSET without DEFAULT, add an implicite
  2272.       DEFAULT to not confuse old users. (This may change).
  2273.     */
  2274.     if ((lex->create_info.used_fields & 
  2275.  (HA_CREATE_USED_DEFAULT_CHARSET | HA_CREATE_USED_CHARSET)) ==
  2276. HA_CREATE_USED_CHARSET)
  2277.     {
  2278.       lex->create_info.used_fields&= ~HA_CREATE_USED_CHARSET;
  2279.       lex->create_info.used_fields|= HA_CREATE_USED_DEFAULT_CHARSET;
  2280.       lex->create_info.default_table_charset= lex->create_info.table_charset;
  2281.       lex->create_info.table_charset= 0;
  2282.     }
  2283.     /*
  2284.       The create-select command will open and read-lock the select table
  2285.       and then create, open and write-lock the new table. If a global
  2286.       read lock steps in, we get a deadlock. The write lock waits for
  2287.       the global read lock, while the global read lock waits for the
  2288.       select table to be closed. So we wait until the global readlock is
  2289.       gone before starting both steps. Note that
  2290.       wait_if_global_read_lock() sets a protection against a new global
  2291.       read lock when it succeeds. This needs to be released by
  2292.       start_waiting_global_read_lock(). We protect the normal CREATE
  2293.       TABLE in the same way. That way we avoid that a new table is
  2294.       created during a gobal read lock.
  2295.     */
  2296.     if (wait_if_global_read_lock(thd, 0, 1))
  2297.     {
  2298.       res= -1;
  2299.       goto unsent_create_error;
  2300.     }
  2301.     if (select_lex->item_list.elements) // With select
  2302.     {
  2303.       select_result *result;
  2304.       select_lex->options|= SELECT_NO_UNLOCK;
  2305.       unit->offset_limit_cnt= select_lex->offset_limit;
  2306.       unit->select_limit_cnt= select_lex->select_limit+
  2307. select_lex->offset_limit;
  2308.       if (unit->select_limit_cnt < select_lex->select_limit)
  2309. unit->select_limit_cnt= HA_POS_ERROR; // No limit
  2310.       if (!(res=open_and_lock_tables(thd,tables)))
  2311.       {
  2312. res= -1; // If error
  2313.         if ((result=new select_create(create_table->db,
  2314.                                       create_table->real_name,
  2315.       &lex->create_info,
  2316.                                       lex->create_list,
  2317.                                       lex->key_list,
  2318.                                       select_lex->item_list, lex->duplicates,
  2319.                                       lex->ignore)))
  2320.         {
  2321.           /*
  2322.             CREATE from SELECT give its SELECT_LEX for SELECT,
  2323.             and item_list belong to SELECT
  2324.           */
  2325.           select_lex->resolve_mode= SELECT_LEX::SELECT_MODE;
  2326.           res=handle_select(thd, lex, result);
  2327.           select_lex->resolve_mode= SELECT_LEX::NOMATTER_MODE;
  2328.         }
  2329. //reset for PS
  2330. lex->create_list.empty();
  2331. lex->key_list.empty();
  2332.       }
  2333.     }
  2334.     else // regular create
  2335.     {
  2336.       if (lex->name)
  2337.         res= mysql_create_like_table(thd, create_table, &lex->create_info, 
  2338.                                      (Table_ident *)lex->name); 
  2339.       else
  2340.       {
  2341.         res= mysql_create_table(thd,create_table->db,
  2342.          create_table->real_name, &lex->create_info,
  2343.          lex->create_list,
  2344.          lex->key_list,0,0);
  2345.       }
  2346.       if (!res)
  2347. send_ok(thd);
  2348.     }
  2349.     /*
  2350.       Release the protection against the global read lock and wake
  2351.       everyone, who might want to set a global read lock.
  2352.     */
  2353.     start_waiting_global_read_lock(thd);
  2354. unsent_create_error:
  2355.     // put tables back for PS rexecuting
  2356.     tables= lex->link_first_table_back(tables, create_table,
  2357.        create_table_local);
  2358.     break;
  2359.   }
  2360.   case SQLCOM_CREATE_INDEX:
  2361.     if (check_one_table_access(thd, INDEX_ACL, tables))
  2362.       goto error; /* purecov: inspected */
  2363.     thd->enable_slow_log= opt_log_slow_admin_statements;
  2364.     if (end_active_trans(thd))
  2365.       res= -1;
  2366.     else
  2367.       res = mysql_create_index(thd, tables, lex->key_list);
  2368.     break;
  2369. #ifdef HAVE_REPLICATION
  2370.   case SQLCOM_SLAVE_START:
  2371.   {
  2372.     pthread_mutex_lock(&LOCK_active_mi);
  2373.     start_slave(thd,active_mi,1 /* net report*/);
  2374.     pthread_mutex_unlock(&LOCK_active_mi);
  2375.     break;
  2376.   }
  2377.   case SQLCOM_SLAVE_STOP:
  2378.   /*
  2379.     If the client thread has locked tables, a deadlock is possible.
  2380.     Assume that
  2381.     - the client thread does LOCK TABLE t READ.
  2382.     - then the master updates t.
  2383.     - then the SQL slave thread wants to update t,
  2384.       so it waits for the client thread because t is locked by it.
  2385.     - then the client thread does SLAVE STOP.
  2386.       SLAVE STOP waits for the SQL slave thread to terminate its
  2387.       update t, which waits for the client thread because t is locked by it.
  2388.     To prevent that, refuse SLAVE STOP if the
  2389.     client thread has locked tables
  2390.   */
  2391.   if (thd->locked_tables || thd->active_transaction() || thd->global_read_lock)
  2392.   {
  2393.     send_error(thd,ER_LOCK_OR_ACTIVE_TRANSACTION);
  2394.     break;
  2395.   }
  2396.   {
  2397.     pthread_mutex_lock(&LOCK_active_mi);
  2398.     stop_slave(thd,active_mi,1/* net report*/);
  2399.     pthread_mutex_unlock(&LOCK_active_mi);
  2400.     break;
  2401.   }
  2402. #endif /* HAVE_REPLICATION */
  2403.   case SQLCOM_ALTER_TABLE:
  2404. #if defined(DONT_ALLOW_SHOW_COMMANDS)
  2405.     send_error(thd,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */
  2406.     break;
  2407. #else
  2408.     {
  2409.       ulong priv=0;
  2410.       if (lex->name && (!lex->name[0] || strlen(lex->name) > NAME_LEN))
  2411.       {
  2412. net_printf(thd, ER_WRONG_TABLE_NAME, lex->name);
  2413. res= 1;
  2414. break;
  2415.       }
  2416.       if (!select_lex->db)
  2417.       {
  2418.         /*
  2419.           In the case of ALTER TABLE ... RENAME we should supply the
  2420.           default database if the new name is not explicitly qualified
  2421.           by a database. (Bug #11493)
  2422.         */
  2423.         if (lex->alter_info.flags & ALTER_RENAME)
  2424.         {
  2425.           if (! thd->db)
  2426.           {
  2427.             send_error(thd,ER_NO_DB_ERROR);
  2428.             goto error;
  2429.           }
  2430.           select_lex->db= thd->db;
  2431.         }
  2432.         else
  2433.           select_lex->db=tables->db;
  2434.       }
  2435.       if (check_access(thd,ALTER_ACL,tables->db,&tables->grant.privilege,0,0) ||
  2436.   check_access(thd,INSERT_ACL | CREATE_ACL,select_lex->db,&priv,0,0)||
  2437.   check_merge_table_access(thd, tables->db,
  2438.    (TABLE_LIST *)
  2439.    lex->create_info.merge_list.first))
  2440. goto error; /* purecov: inspected */
  2441.       if (grant_option)
  2442.       {
  2443. if (check_grant(thd, ALTER_ACL, tables, 0, UINT_MAX, 0))
  2444.   goto error;
  2445. if (lex->name && !test_all_bits(priv,INSERT_ACL | CREATE_ACL))
  2446. { // Rename of table
  2447.   TABLE_LIST tmp_table;
  2448.   bzero((char*) &tmp_table,sizeof(tmp_table));
  2449.   tmp_table.real_name=lex->name;
  2450.   tmp_table.db=select_lex->db;
  2451.   tmp_table.grant.privilege=priv;
  2452.   if (check_grant(thd, INSERT_ACL | CREATE_ACL, &tmp_table, 0,
  2453.   UINT_MAX, 0))
  2454.     goto error;
  2455. }
  2456.       }
  2457.       /* Don't yet allow changing of symlinks with ALTER TABLE */
  2458.       lex->create_info.data_file_name=lex->create_info.index_file_name=0;
  2459.       /* ALTER TABLE ends previous transaction */
  2460.       if (end_active_trans(thd))
  2461. res= -1;
  2462.       else
  2463.       {
  2464.         thd->enable_slow_log= opt_log_slow_admin_statements;
  2465. res= mysql_alter_table(thd, select_lex->db, lex->name,
  2466.        &lex->create_info,
  2467.        tables, lex->create_list,
  2468.        lex->key_list,
  2469.        select_lex->order_list.elements,
  2470.                                (ORDER *) select_lex->order_list.first,
  2471.        lex->duplicates, lex->ignore, &lex->alter_info);
  2472.       }
  2473.       break;
  2474.     }
  2475. #endif /*DONT_ALLOW_SHOW_COMMANDS*/
  2476.   case SQLCOM_RENAME_TABLE:
  2477.   {
  2478.     TABLE_LIST *table;
  2479.     if (check_db_used(thd,tables))
  2480.       goto error;
  2481.     for (table=tables ; table ; table=table->next->next)
  2482.     {
  2483.       if (check_access(thd, ALTER_ACL | DROP_ACL, table->db,
  2484.        &table->grant.privilege,0,0) ||
  2485.   check_access(thd, INSERT_ACL | CREATE_ACL, table->next->db,
  2486.        &table->next->grant.privilege,0,0))
  2487. goto error;
  2488.       if (grant_option)
  2489.       {
  2490. TABLE_LIST old_list,new_list;
  2491. /*
  2492.   we do not need initialize old_list and new_list because we will
  2493.   come table[0] and table->next[0] there
  2494. */
  2495. old_list=table[0];
  2496. new_list=table->next[0];
  2497. old_list.next=new_list.next=0;
  2498. if (check_grant(thd, ALTER_ACL, &old_list, 0, UINT_MAX, 0) ||
  2499.     (!test_all_bits(table->next->grant.privilege,
  2500.     INSERT_ACL | CREATE_ACL) &&
  2501.      check_grant(thd, INSERT_ACL | CREATE_ACL, &new_list, 0,
  2502.  UINT_MAX, 0)))
  2503.   goto error;
  2504.       }
  2505.     }
  2506.     query_cache_invalidate3(thd, tables, 0);
  2507.     if (end_active_trans(thd))
  2508.       res= -1;
  2509.     else if (mysql_rename_tables(thd,tables))
  2510.       res= -1;
  2511.     break;
  2512.   }
  2513. #ifndef EMBEDDED_LIBRARY
  2514.   case SQLCOM_SHOW_BINLOGS:
  2515. #ifdef DONT_ALLOW_SHOW_COMMANDS
  2516.     send_error(thd,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */
  2517.     DBUG_VOID_RETURN;
  2518. #else
  2519.     {
  2520.       if (check_global_access(thd, SUPER_ACL))
  2521. goto error;
  2522.       res = show_binlogs(thd);
  2523.       break;
  2524.     }
  2525. #endif
  2526. #endif /* EMBEDDED_LIBRARY */
  2527.   case SQLCOM_SHOW_CREATE:
  2528. #ifdef DONT_ALLOW_SHOW_COMMANDS
  2529.     send_error(thd,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */
  2530.     DBUG_VOID_RETURN;
  2531. #else
  2532.     {
  2533.       if (check_db_used(thd, tables) ||
  2534.   check_access(thd, SELECT_ACL | EXTRA_ACL, tables->db,
  2535.        &tables->grant.privilege,0,0))
  2536. goto error;
  2537.       if (grant_option && check_grant(thd, SELECT_ACL, tables, 2, UINT_MAX, 0))
  2538. goto error;
  2539.       res= mysqld_show_create(thd, tables);
  2540.       break;
  2541.     }
  2542. #endif
  2543.   case SQLCOM_CHECKSUM:
  2544.   {
  2545.     if (check_db_used(thd,tables) ||
  2546. check_table_access(thd, SELECT_ACL | EXTRA_ACL , tables,0))
  2547.       goto error; /* purecov: inspected */
  2548.     res = mysql_checksum_table(thd, tables, &lex->check_opt);
  2549.     break;
  2550.   }
  2551.   case SQLCOM_REPAIR:
  2552.   {
  2553.     if (check_db_used(thd,tables) ||
  2554. check_table_access(thd,SELECT_ACL | INSERT_ACL, tables,0))
  2555.       goto error; /* purecov: inspected */
  2556.     thd->enable_slow_log= opt_log_slow_admin_statements;
  2557.     res = mysql_repair_table(thd, tables, &lex->check_opt);
  2558.     /* ! we write after unlocking the table */
  2559.     if (!res && !lex->no_write_to_binlog)
  2560.     {
  2561.       mysql_update_log.write(thd, thd->query, thd->query_length);
  2562.       if (mysql_bin_log.is_open())
  2563.       {
  2564. thd->clear_error(); // No binlog error generated
  2565.         Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
  2566.         mysql_bin_log.write(&qinfo);
  2567.       }
  2568.     }
  2569.     break;
  2570.   }
  2571.   case SQLCOM_CHECK:
  2572.   {
  2573.     if (check_db_used(thd,tables) ||
  2574. check_table_access(thd, SELECT_ACL | EXTRA_ACL , tables,0))
  2575.       goto error; /* purecov: inspected */
  2576.     thd->enable_slow_log= opt_log_slow_admin_statements;
  2577.     res = mysql_check_table(thd, tables, &lex->check_opt);
  2578.     break;
  2579.   }
  2580.   case SQLCOM_ANALYZE:
  2581.   {
  2582.     if (check_db_used(thd,tables) ||
  2583. check_table_access(thd,SELECT_ACL | INSERT_ACL, tables,0))
  2584.       goto error; /* purecov: inspected */
  2585.     thd->enable_slow_log= opt_log_slow_admin_statements;
  2586.     res = mysql_analyze_table(thd, tables, &lex->check_opt);
  2587.     /* ! we write after unlocking the table */
  2588.     if (!res && !lex->no_write_to_binlog)
  2589.     {
  2590.       mysql_update_log.write(thd, thd->query, thd->query_length);
  2591.       if (mysql_bin_log.is_open())
  2592.       {
  2593. thd->clear_error(); // No binlog error generated
  2594.         Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
  2595.         mysql_bin_log.write(&qinfo);
  2596.       }
  2597.     }
  2598.     break;
  2599.   }
  2600.   case SQLCOM_OPTIMIZE:
  2601.   {
  2602.     if (check_db_used(thd,tables) ||
  2603. check_table_access(thd,SELECT_ACL | INSERT_ACL, tables,0))
  2604.       goto error; /* purecov: inspected */
  2605.     thd->enable_slow_log= opt_log_slow_admin_statements;
  2606.     res= (specialflag & (SPECIAL_SAFE_MODE | SPECIAL_NO_NEW_FUNC)) ?
  2607.       mysql_recreate_table(thd, tables, 1) :
  2608.       mysql_optimize_table(thd, tables, &lex->check_opt);
  2609.     /* ! we write after unlocking the table */
  2610.     if (!res && !lex->no_write_to_binlog)
  2611.     {
  2612.       mysql_update_log.write(thd, thd->query, thd->query_length);
  2613.       if (mysql_bin_log.is_open())
  2614.       {
  2615. thd->clear_error(); // No binlog error generated
  2616.         Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
  2617.         mysql_bin_log.write(&qinfo);
  2618.       }
  2619.     }
  2620.     break;
  2621.   }
  2622.   case SQLCOM_UPDATE:
  2623.     if (update_precheck(thd, tables))
  2624.       break;
  2625.     res= mysql_update(thd,tables,
  2626.                       select_lex->item_list,
  2627.                       lex->value_list,
  2628.                       select_lex->where,
  2629.       select_lex->order_list.elements,
  2630.                       (ORDER *) select_lex->order_list.first,
  2631.                       select_lex->select_limit,
  2632.                       lex->duplicates, lex->ignore);
  2633.     if (thd->net.report_error)
  2634.       res= -1;
  2635.     break;
  2636.   case SQLCOM_UPDATE_MULTI:
  2637.   {
  2638.     if ((res= multi_update_precheck(thd, tables)))
  2639.       break;
  2640.     if ((res= mysql_multi_update_lock(thd, tables, &select_lex->item_list,
  2641.       select_lex)))
  2642.       break;
  2643. #ifdef HAVE_REPLICATION
  2644.     /* Check slave filtering rules */
  2645.     if (thd->slave_thread)
  2646.       if (all_tables_not_ok(thd,tables))
  2647.       {
  2648. /* we warn the slave SQL thread */
  2649. my_error(ER_SLAVE_IGNORED_TABLE, MYF(0));
  2650. break;
  2651.       }
  2652. #endif /* HAVE_REPLICATION */
  2653.     res= mysql_multi_update(thd,tables,
  2654.     &select_lex->item_list,
  2655.     &lex->value_list,
  2656.     select_lex->where,
  2657.     select_lex->options,
  2658.     lex->duplicates, lex->ignore, unit, select_lex);
  2659.     break;
  2660.   }
  2661.   case SQLCOM_REPLACE:
  2662.   case SQLCOM_INSERT:
  2663.   {
  2664.     if ((res= insert_precheck(thd, tables)))
  2665.       break;
  2666.     res= mysql_insert(thd,tables,lex->field_list,lex->many_values,
  2667.                       lex->update_list, lex->value_list,
  2668.                       lex->duplicates, lex->ignore);
  2669.     if (thd->net.report_error)
  2670.       res= -1;
  2671.     break;
  2672.   }
  2673.   case SQLCOM_REPLACE_SELECT:
  2674.   case SQLCOM_INSERT_SELECT:
  2675.   {
  2676.     TABLE_LIST *first_local_table= (TABLE_LIST *) select_lex->table_list.first;
  2677.     TABLE_LIST dup_tables;
  2678.     TABLE *insert_table;
  2679.     if ((res= insert_precheck(thd, tables)))
  2680.       break;
  2681.     /* Fix lock for first table */
  2682.     if (tables->lock_type == TL_WRITE_DELAYED)
  2683.       tables->lock_type= TL_WRITE;
  2684.     /* Don't unlock tables until command is written to binary log */
  2685.     select_lex->options|= SELECT_NO_UNLOCK;
  2686.     select_result *result;
  2687.     unit->offset_limit_cnt= select_lex->offset_limit;
  2688.     unit->select_limit_cnt= select_lex->select_limit+select_lex->offset_limit;