sql_class.cc
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:16k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
  2.    
  3.    This program is free software; you can redistribute it and/or modify
  4.    it under the terms of the GNU General Public License as published by
  5.    the Free Software Foundation; either version 2 of the License, or
  6.    (at your option) any later version.
  7.    
  8.    This program is distributed in the hope that it will be useful,
  9.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11.    GNU General Public License for more details.
  12.    
  13.    You should have received a copy of the GNU General Public License
  14.    along with this program; if not, write to the Free Software
  15.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  16. /*****************************************************************************
  17. **
  18. ** This file implements classes defined in sql_class.h
  19. ** Especially the classes to handle a result from a select
  20. **
  21. *****************************************************************************/
  22. #ifdef __GNUC__
  23. #pragma implementation // gcc: Class implementation
  24. #endif
  25. #include "mysql_priv.h"
  26. #include "sql_acl.h"
  27. #include <m_ctype.h>
  28. #include <sys/stat.h>
  29. #include <thr_alarm.h>
  30. #ifdef __WIN__
  31. #include <io.h>
  32. #endif
  33. /*****************************************************************************
  34. ** Instansiate templates
  35. *****************************************************************************/
  36. #ifdef __GNUC__
  37. /* Used templates */
  38. template class List<Key>;
  39. template class List_iterator<Key>;
  40. template class List<key_part_spec>;
  41. template class List_iterator<key_part_spec>;
  42. template class List<Alter_drop>;
  43. template class List_iterator<Alter_drop>;
  44. template class List<Alter_column>;
  45. template class List_iterator<Alter_column>;
  46. #endif
  47. /****************************************************************************
  48. ** User variables
  49. ****************************************************************************/
  50. static byte* get_var_key(user_var_entry *entry, uint *length,
  51.  my_bool not_used __attribute__((unused)))
  52. {
  53.   *length=(uint) entry->name.length;
  54.   return (byte*) entry->name.str;
  55. }
  56. static void free_var(user_var_entry *entry)
  57. {
  58.   char *pos= (char*) entry+ALIGN_SIZE(sizeof(*entry));
  59.   if (entry->value && entry->value != pos)
  60.     my_free(entry->value, MYF(0));
  61.   my_free((char*) entry,MYF(0));
  62. }
  63. /****************************************************************************
  64. ** Thread specific functions
  65. ****************************************************************************/
  66. THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0),
  67.    insert_id_used(0),in_lock_tables(0),
  68.    global_read_lock(0),bootstrap(0)
  69. {
  70.   proc_info="login";
  71.   where="field list";
  72.   host=user=priv_user=db=query=ip=0;
  73.   locked=killed=count_cuted_fields=some_tables_deleted=no_errors=password=
  74.     query_start_used=0;
  75.   query_length=col_access=0;
  76.   query_error=0;
  77. #ifdef SIGNAL_WITH_VIO_CLOSE
  78.   active_vio = 0;
  79.   pthread_mutex_init(&active_vio_lock, NULL);
  80. #endif  
  81.   server_id = ::server_id;
  82.   server_status=SERVER_STATUS_AUTOCOMMIT;
  83.   next_insert_id=last_insert_id=0;
  84.   open_tables=temporary_tables=0;
  85.   tmp_table=0;
  86.   lock=locked_tables=0;
  87.   used_tables=0;
  88.   cuted_fields=sent_row_count=0L;
  89.   options=thd_startup_options;
  90.   update_lock_default= low_priority_updates ? TL_WRITE_LOW_PRIORITY : TL_WRITE;
  91.   start_time=(time_t) 0;
  92.   current_linfo =  0;
  93.   slave_thread = 0;
  94.   slave_proxy_id = 0;
  95.   last_nx_table = last_nx_db = 0;
  96.   inactive_timeout=net_wait_timeout;
  97.   open_options=ha_open_options;
  98.   cond_count=0;
  99.   command=COM_CONNECT;
  100.   set_query_id=1;
  101.   default_select_limit= HA_POS_ERROR;
  102.   max_join_size=  ((::max_join_size != ~ (ulong) 0L) ? ::max_join_size :
  103.    HA_POS_ERROR);
  104.   convert_set=0;
  105.   mysys_var=0;
  106.   db_access=NO_ACCESS;
  107.   hash_init(&user_vars, USER_VARS_HASH_SIZE, 0, 0,
  108.     (hash_get_key) get_var_key,
  109.     (void (*)(void*)) free_var,0);
  110.   net.vio=0;
  111.   ull=0;
  112.   system_thread=0;
  113.   bzero((char*) &mem_root,sizeof(mem_root));
  114. #ifdef USING_TRANSACTIONS
  115.   if (opt_using_transactions)
  116.   {
  117.     bzero((char*) &transaction,sizeof(transaction));
  118.     if (open_cached_file(&transaction.trans_log,
  119.  mysql_tmpdir, LOG_PREFIX, binlog_cache_size,
  120.  MYF(MY_WME)))
  121.       killed=1;
  122.     transaction.trans_log.end_of_file= max_binlog_cache_size;
  123.   }
  124. #endif
  125. #ifdef __WIN__
  126.   real_id = 0 ;
  127. #endif
  128. }
  129. THD::~THD()
  130. {
  131.   DBUG_ENTER("~THD()");
  132.   /* Close connection */
  133.   if (net.vio)
  134.   {
  135.     vio_delete(net.vio);
  136.     net_end(&net); 
  137.   }
  138.   ha_rollback(this);
  139.   if (locked_tables)
  140.   {
  141.     lock=locked_tables; locked_tables=0;
  142.     close_thread_tables(this);
  143.   }
  144.   close_temporary_tables(this);
  145. #ifdef USING_TRANSACTIONS
  146.   if (opt_using_transactions)
  147.   {
  148.     close_cached_file(&transaction.trans_log);
  149.     ha_close_connection(this);
  150.   }
  151. #endif
  152.   if (global_read_lock)
  153.   {
  154.     pthread_mutex_lock(&LOCK_open);
  155.     ::global_read_lock--;
  156.     pthread_cond_broadcast(&COND_refresh);
  157.     pthread_mutex_unlock(&LOCK_open);
  158.   }
  159.   if (ull)
  160.   {
  161.     pthread_mutex_lock(&LOCK_user_locks);
  162.     item_user_lock_release(ull);
  163.     pthread_mutex_unlock(&LOCK_user_locks);
  164.   }
  165.   hash_free(&user_vars);
  166.   DBUG_PRINT("info", ("freeing host"));
  167.   
  168.   if (host != localhost) // If not pointer to constant
  169.     safeFree(host);
  170.   if (user != delayed_user)
  171.     safeFree(user);
  172.   safeFree(db);
  173.   safeFree(ip);
  174.   free_root(&mem_root,MYF(0));
  175.   mysys_var=0; // Safety (shouldn't be needed)
  176. #ifdef SIGNAL_WITH_VIO_CLOSE
  177.   pthread_mutex_destroy(&active_vio_lock);
  178. #endif  
  179.   DBUG_VOID_RETURN;
  180. }
  181. void THD::prepare_to_die()
  182. {
  183.   thr_alarm_kill(real_id);
  184.   killed = 1;
  185. #ifdef SIGNAL_WITH_VIO_CLOSE
  186.   close_active_vio();
  187. #endif    
  188.   if (mysys_var)
  189.     {
  190.       pthread_mutex_lock(&mysys_var->mutex);
  191.       if (!system_thread) // Don't abort locks
  192. mysys_var->abort=1;
  193.       if (mysys_var->current_mutex)
  194. {
  195.   pthread_mutex_lock(mysys_var->current_mutex);
  196.   pthread_cond_broadcast(mysys_var->current_cond);
  197.   pthread_mutex_unlock(mysys_var->current_mutex);
  198. }
  199.       pthread_mutex_unlock(&mysys_var->mutex);
  200.     }
  201. }
  202. // remember the location of thread info, the structure needed for
  203. // sql_alloc() and the structure for the net buffer
  204. bool THD::store_globals()
  205. {
  206.   return (my_pthread_setspecific_ptr(THR_THD,  this) ||
  207.   my_pthread_setspecific_ptr(THR_MALLOC, &mem_root) ||
  208.   my_pthread_setspecific_ptr(THR_NET,  &net));
  209. }
  210. /*****************************************************************************
  211. ** Functions to provide a interface to select results
  212. *****************************************************************************/
  213. select_result::select_result()
  214. {
  215.   thd=current_thd;
  216. }
  217. static String default_line_term("n"),default_escaped("\"),
  218.       default_field_term("t");
  219. sql_exchange::sql_exchange(char *name,bool flag)
  220.   :file_name(name), opt_enclosed(0), dumpfile(flag), skip_lines(0)
  221. {
  222.   field_term= &default_field_term;
  223.   enclosed=   line_start= &empty_string;
  224.   line_term=  &default_line_term;
  225.   escaped=    &default_escaped;
  226. }
  227. bool select_send::send_fields(List<Item> &list,uint flag)
  228. {
  229.   return ::send_fields(thd,list,flag);
  230. }
  231. /* Send data to client. Returns 0 if ok */
  232. bool select_send::send_data(List<Item> &items)
  233. {
  234.   List_iterator<Item> li(items);
  235.   String *packet= &thd->packet;
  236.   DBUG_ENTER("send_data");
  237.   if (thd->offset_limit)
  238.   { // using limit offset,count
  239.     thd->offset_limit--;
  240.     DBUG_RETURN(0);
  241.   }
  242.   packet->length(0); // Reset packet
  243.   Item *item;
  244.   while ((item=li++))
  245.   {
  246.     if (item->send(packet))
  247.     {
  248.       packet->free(); // Free used
  249.       my_error(ER_OUT_OF_RESOURCES,MYF(0));
  250.       DBUG_RETURN(1);
  251.     }
  252.   }
  253.   thd->sent_row_count++;
  254.   bool error=my_net_write(&thd->net,(char*) packet->ptr(),packet->length());
  255.   DBUG_RETURN(error);
  256. }
  257. void select_send::send_error(uint errcode,const char *err)
  258. {
  259.   ::send_error(&thd->net,errcode,err);
  260. }
  261. bool select_send::send_eof()
  262. {
  263.   /* Unlock tables before sending packet to gain some speed */
  264.   if (thd->lock)
  265.   {
  266.     mysql_unlock_tables(thd, thd->lock); thd->lock=0;
  267.   }
  268.   ::send_eof(&thd->net);
  269.   return 0;
  270. }
  271. /***************************************************************************
  272. ** Export of select to textfile
  273. ***************************************************************************/
  274. select_export::~select_export()
  275. {
  276.   if (file >= 0)
  277.   { // This only happens in case of error
  278.     (void) end_io_cache(&cache);
  279.     (void) my_close(file,MYF(0));
  280.     file= -1;
  281.   }
  282.   thd->sent_row_count=row_count;
  283. }
  284. int
  285. select_export::prepare(List<Item> &list)
  286. {
  287.   char path[FN_REFLEN];
  288.   uint option=4;
  289.   bool blob_flag=0;
  290. #ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS
  291.   option|=1; // Force use of db directory
  292. #endif
  293.   if ((uint) strlen(exchange->file_name) + NAME_LEN >= FN_REFLEN)
  294.     strmake(path,exchange->file_name,FN_REFLEN-1);
  295.   (void) fn_format(path,exchange->file_name, thd->db ? thd->db : "", "",
  296.    option);
  297.   if (!access(path,F_OK))
  298.   {
  299.     my_error(ER_FILE_EXISTS_ERROR,MYF(0),exchange->file_name);
  300.     return 1;
  301.   }
  302.   /* Create the file world readable */
  303.   if ((file=my_create(path, 0666, O_WRONLY, MYF(MY_WME))) < 0)
  304.     return 1;
  305. #ifdef HAVE_FCHMOD
  306.   (void) fchmod(file,0666); // Because of umask()
  307. #else
  308.   (void) chmod(path,0666);
  309. #endif
  310.   if (init_io_cache(&cache,file,0L,WRITE_CACHE,0L,1,MYF(MY_WME)))
  311.   {
  312.     my_close(file,MYF(0));
  313.     file= -1;
  314.     return 1;
  315.   }
  316.   /* Check if there is any blobs in data */
  317.   {
  318.     List_iterator<Item> li(list);
  319.     Item *item;
  320.     while ((item=li++))
  321.     {
  322.       if (item->max_length >= MAX_BLOB_WIDTH)
  323.       {
  324. blob_flag=1;
  325. break;
  326.       }
  327.     }
  328.   }
  329.   field_term_length=exchange->field_term->length();
  330.   if (!exchange->line_term->length())
  331.     exchange->line_term=exchange->field_term; // Use this if it exists
  332.   field_sep_char= (exchange->enclosed->length() ? (*exchange->enclosed)[0] :
  333.    field_term_length ? (*exchange->field_term)[0] : INT_MAX);
  334.   escape_char= (exchange->escaped->length() ? (*exchange->escaped)[0] : -1);
  335.   line_sep_char= (exchange->line_term->length() ?
  336.   (*exchange->line_term)[0] : INT_MAX);
  337.   if (!field_term_length)
  338.     exchange->opt_enclosed=0;
  339.   if (!exchange->enclosed->length())
  340.     exchange->opt_enclosed=1; // A little quicker loop
  341.   fixed_row_size= (!field_term_length && !exchange->enclosed->length() &&
  342.    !blob_flag);
  343.   return 0;
  344. }
  345. bool select_export::send_data(List<Item> &items)
  346. {
  347.   DBUG_ENTER("send_data");
  348.   char buff[MAX_FIELD_WIDTH],null_buff[2],space[MAX_FIELD_WIDTH];
  349.   bool space_inited=0;
  350.   String tmp(buff,sizeof(buff)),*res;
  351.   tmp.length(0);
  352.   if (thd->offset_limit)
  353.   { // using limit offset,count
  354.     thd->offset_limit--;
  355.     DBUG_RETURN(0);
  356.   }
  357.   row_count++;
  358.   Item *item;
  359.   char *buff_ptr=buff;
  360.   uint used_length=0,items_left=items.elements;
  361.   List_iterator<Item> li(items);
  362.   if (my_b_write(&cache,(byte*) exchange->line_start->ptr(),
  363.  exchange->line_start->length()))
  364.     goto err;
  365.   while ((item=li++))
  366.   {
  367.     Item_result result_type=item->result_type();
  368.     res=item->str_result(&tmp);
  369.     if (res && (!exchange->opt_enclosed || result_type == STRING_RESULT))
  370.     {
  371.       if (my_b_write(&cache,(byte*) exchange->enclosed->ptr(),
  372.      exchange->enclosed->length()))
  373. goto err;
  374.     }
  375.     if (!res)
  376.     { // NULL
  377.       if (!fixed_row_size)
  378.       {
  379. if (escape_char != -1) // Use N syntax
  380. {
  381.   null_buff[0]=escape_char;
  382.   null_buff[1]='N';
  383.   if (my_b_write(&cache,(byte*) null_buff,2))
  384.     goto err;
  385. }
  386. else if (my_b_write(&cache,(byte*) "NULL",4))
  387.   goto err;
  388.       }
  389.       else
  390.       {
  391. used_length=0; // Fill with space
  392.       }
  393.     }
  394.     else
  395.     {
  396.       if (fixed_row_size)
  397. used_length=min(res->length(),item->max_length);
  398.       else
  399. used_length=res->length();
  400.       if (result_type == STRING_RESULT && escape_char != -1)
  401.       {
  402. char *pos,*start,*end;
  403. for (start=pos=(char*) res->ptr(),end=pos+used_length ;
  404.      pos != end ;
  405.      pos++)
  406. {
  407. #ifdef USE_MB
  408.   if (use_mb(default_charset_info))
  409.   {
  410.     int l;
  411.     if ((l=my_ismbchar(default_charset_info, pos, end)))
  412.     {
  413.       pos += l-1;
  414.       continue;
  415.     }
  416.   }
  417. #endif
  418.   if ((int) *pos == escape_char || (int) *pos == field_sep_char ||
  419.       (int) *pos == line_sep_char || !*pos)
  420.   {
  421.     char tmp_buff[2];
  422.     tmp_buff[0]= escape_char;
  423.     tmp_buff[1]= *pos ? *pos : '0';
  424.     if (my_b_write(&cache,(byte*) start,(uint) (pos-start)) ||
  425. my_b_write(&cache,(byte*) tmp_buff,2))
  426.       goto err;
  427.     start=pos+1;
  428.   }
  429. }
  430. if (my_b_write(&cache,(byte*) start,(uint) (pos-start)))
  431.   goto err;
  432.       }
  433.       else if (my_b_write(&cache,(byte*) res->ptr(),used_length))
  434. goto err;
  435.     }
  436.     if (fixed_row_size)
  437.     { // Fill with space
  438.       if (item->max_length > used_length)
  439.       {
  440. /* QQ:  Fix by adding a my_b_fill() function */
  441. if (!space_inited)
  442. {
  443.   space_inited=1;
  444.   bfill(space,sizeof(space),' ');
  445. }
  446. uint length=item->max_length-used_length;
  447. for ( ; length > sizeof(space) ; length-=sizeof(space))
  448. {
  449.   if (my_b_write(&cache,(byte*) space,sizeof(space)))
  450.     goto err;
  451. }
  452. if (my_b_write(&cache,(byte*) space,length))
  453.   goto err;
  454.       }
  455.     }
  456.     buff_ptr=buff; // Place separators here
  457.     if (res && (!exchange->opt_enclosed || result_type == STRING_RESULT))
  458.     {
  459.       memcpy(buff_ptr,exchange->enclosed->ptr(),exchange->enclosed->length());
  460.       buff_ptr+=exchange->enclosed->length();
  461.     }
  462.     if (--items_left)
  463.     {
  464.       memcpy(buff_ptr,exchange->field_term->ptr(),field_term_length);
  465.       buff_ptr+=field_term_length;
  466.     }
  467.     if (my_b_write(&cache,(byte*) buff,(uint) (buff_ptr-buff)))
  468.       goto err;
  469.   }
  470.   if (my_b_write(&cache,(byte*) exchange->line_term->ptr(),
  471.  exchange->line_term->length()))
  472.     goto err;
  473.   DBUG_RETURN(0);
  474. err:
  475.   DBUG_RETURN(1);
  476. }
  477. void select_export::send_error(uint errcode,const char *err)
  478. {
  479.   ::send_error(&thd->net,errcode,err);
  480.   (void) end_io_cache(&cache);
  481.   (void) my_close(file,MYF(0));
  482.   file= -1;
  483. }
  484. bool select_export::send_eof()
  485. {
  486.   int error=test(end_io_cache(&cache));
  487.   if (my_close(file,MYF(MY_WME)))
  488.     error=1;
  489.   if (error)
  490.     ::send_error(&thd->net);
  491.   else
  492.     ::send_ok(&thd->net,row_count);
  493.   file= -1;
  494.   return error;
  495. }
  496. /***************************************************************************
  497. ** Dump  of select to a binary file
  498. ***************************************************************************/
  499. select_dump::~select_dump()
  500. {
  501.   if (file >= 0)
  502.   { // This only happens in case of error
  503.     (void) end_io_cache(&cache);
  504.     (void) my_close(file,MYF(0));
  505.     file= -1;
  506.   }
  507. }
  508. int
  509. select_dump::prepare(List<Item> &list __attribute__((unused)))
  510. {
  511.   uint option=4;
  512. #ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS
  513.   option|=1; // Force use of db directory
  514. #endif
  515.   (void) fn_format(path,exchange->file_name, thd->db ? thd->db : "", "",
  516.    option);
  517.   if (!access(path,F_OK))
  518.   {
  519.     my_error(ER_FILE_EXISTS_ERROR,MYF(0),exchange->file_name);
  520.     return 1;
  521.   }
  522.   /* Create the file world readable */
  523.   if ((file=my_create(path, 0666, O_WRONLY, MYF(MY_WME))) < 0)
  524.     return 1;
  525. #ifdef HAVE_FCHMOD
  526.   (void) fchmod(file,0666); // Because of umask()
  527. #else
  528.   (void) chmod(path,0666);
  529. #endif
  530.   if (init_io_cache(&cache,file,0L,WRITE_CACHE,0L,1,MYF(MY_WME)))
  531.   {
  532.     my_close(file,MYF(0));
  533.     my_delete(path,MYF(0));
  534.     file= -1;
  535.     return 1;
  536.   }
  537.   return 0;
  538. }
  539. bool select_dump::send_data(List<Item> &items)
  540. {
  541.   List_iterator<Item> li(items);
  542.   char buff[MAX_FIELD_WIDTH];
  543.   String tmp(buff,sizeof(buff)),*res;
  544.   tmp.length(0);
  545.   Item *item;
  546.   DBUG_ENTER("send_data");
  547.   if (thd->offset_limit)
  548.   { // using limit offset,count
  549.     thd->offset_limit--;
  550.     DBUG_RETURN(0);
  551.   }
  552.   if (row_count++ > 1) 
  553.   {
  554.     my_error(ER_TOO_MANY_ROWS,MYF(0));
  555.     goto err;
  556.   }
  557.   while ((item=li++))
  558.   {
  559.     res=item->str_result(&tmp);
  560.     if (!res) // If NULL
  561.     {
  562.       if (my_b_write(&cache,(byte*) "",1))
  563. goto err;
  564.     }
  565.     else if (my_b_write(&cache,(byte*) res->ptr(),res->length()))
  566.     {
  567.       my_error(ER_ERROR_ON_WRITE,MYF(0), path, my_errno);
  568.       goto err;
  569.     }
  570.   }
  571.   DBUG_RETURN(0);
  572. err:
  573.   DBUG_RETURN(1);
  574. }
  575. void select_dump::send_error(uint errcode,const char *err)
  576. {
  577.   ::send_error(&thd->net,errcode,err);
  578.   (void) end_io_cache(&cache);
  579.   (void) my_close(file,MYF(0));
  580.   (void) my_delete(path,MYF(0)); // Delete file on error
  581.   file= -1;
  582. }
  583. bool select_dump::send_eof()
  584. {
  585.   int error=test(end_io_cache(&cache));
  586.   if (my_close(file,MYF(MY_WME)))
  587.     error=1;
  588.   if (error)
  589.     ::send_error(&thd->net);
  590.   else
  591.     ::send_ok(&thd->net,row_count);
  592.   file= -1;
  593.   return error;
  594. }