home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 January / Chip_2001-01_cd1.bin / tema / mysql / mysql-3.23.28g-win-source.exe / sql / log_event.cpp < prev    next >
C/C++ Source or Header  |  2000-11-22  |  18KB  |  711 lines

  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. #ifndef MYSQL_CLIENT
  19. #ifdef __GNUC__
  20. #pragma implementation                // gcc: Class implementation
  21. #endif
  22. #include  "mysql_priv.h"
  23. #endif /* MYSQL_CLIENT */
  24.  
  25.  
  26. static void pretty_print_char(FILE* file, int c)
  27. {
  28.   fputc('\'', file);
  29.   switch(c) {
  30.   case '\n': fprintf(file, "\\n"); break;
  31.   case '\r': fprintf(file, "\\r"); break;
  32.   case '\\': fprintf(file, "\\\\"); break;
  33.   case '\b': fprintf(file, "\\b"); break;
  34.   case '\'': fprintf(file, "\\'"); break;
  35.   case 0   : fprintf(file, "\\0"); break;
  36.   default:
  37.     fputc(c, file);
  38.     break;
  39.   }
  40.   fputc('\'', file);
  41. }
  42.  
  43. int Query_log_event::write(IO_CACHE* file)
  44. {
  45.   return query ? Log_event::write(file) : -1; 
  46. }
  47.  
  48. int Log_event::write(IO_CACHE* file)
  49. {
  50.   return (write_header(file) || write_data(file)) ? -1 : 0;
  51. }
  52.  
  53. int Log_event::write_header(IO_CACHE* file)
  54. {
  55.   // make sure to change this when the header gets bigger
  56.   char buf[LOG_EVENT_HEADER_LEN];
  57.   char* pos = buf;
  58.   int4store(pos, when); // timestamp
  59.   pos += 4;
  60.   *pos++ = get_type_code(); // event type code
  61.   int4store(pos, server_id);
  62.   pos += 4;
  63.   long tmp=get_data_size() + LOG_EVENT_HEADER_LEN;
  64.   int4store(pos, tmp);
  65.   pos += 4;
  66.   return (my_b_write(file, (byte*) buf, (uint) (pos - buf)));
  67. }
  68.  
  69. #ifndef MYSQL_CLIENT
  70.  
  71. int Log_event::read_log_event(IO_CACHE* file, String* packet,
  72.                   pthread_mutex_t* log_lock)
  73. {
  74.   ulong data_len;
  75.   char buf[LOG_EVENT_HEADER_LEN];
  76.   if (log_lock)
  77.     pthread_mutex_lock(log_lock);
  78.   if (my_b_read(file, (byte*) buf, sizeof(buf)))
  79.   {
  80.     if (log_lock) pthread_mutex_unlock(log_lock);
  81.     // if the read hits eof, we must report it as eof
  82.     // so the caller will know it can go into cond_wait to be woken up
  83.     // on the next update to the log
  84.     if(!file->error) return LOG_READ_EOF;
  85.     return file->error > 0 ? LOG_READ_TRUNC: LOG_READ_IO;
  86.   }
  87.   data_len = uint4korr(buf + EVENT_LEN_OFFSET);
  88.   if (data_len < LOG_EVENT_HEADER_LEN || data_len > MAX_EVENT_LEN)
  89.   {
  90.     if (log_lock) pthread_mutex_unlock(log_lock);
  91.     return LOG_READ_BOGUS;
  92.   }
  93.   packet->append(buf, sizeof(buf));
  94.   data_len -= LOG_EVENT_HEADER_LEN;
  95.   if (data_len)
  96.   {
  97.     if (packet->append(file, data_len))
  98.     {
  99.       if(log_lock)
  100.     pthread_mutex_unlock(log_lock);
  101.       // here we should never hit eof in a non-error condtion
  102.       // eof means we are reading the event partially, which should
  103.       // never happen
  104.       return file->error >= 0 ? LOG_READ_TRUNC: LOG_READ_IO;
  105.     }
  106.   }
  107.   if (log_lock) pthread_mutex_unlock(log_lock);
  108.   return 0;
  109. }
  110.  
  111. #endif // MYSQL_CLIENT
  112.  
  113. // allocates memory - the caller is responsible for clean-up
  114.  
  115. Log_event* Log_event::read_log_event(IO_CACHE* file, pthread_mutex_t* log_lock)
  116. {
  117.   time_t timestamp;
  118.   uint32 server_id;
  119.   
  120.   char buf[LOG_EVENT_HEADER_LEN-4];
  121.   if(log_lock) pthread_mutex_lock(log_lock);
  122.   if (my_b_read(file, (byte *) buf, sizeof(buf)))
  123.   {
  124.     if (log_lock) pthread_mutex_unlock(log_lock);
  125.     return NULL;
  126.   }
  127.   timestamp = uint4korr(buf);
  128.   server_id = uint4korr(buf + 5);
  129.   
  130.   switch(buf[EVENT_TYPE_OFFSET])
  131.   {
  132.   case QUERY_EVENT:
  133.   {
  134.     Query_log_event* q = new Query_log_event(file, timestamp, server_id);
  135.     if(log_lock) pthread_mutex_unlock(log_lock);
  136.     if (!q->query)
  137.     {
  138.       delete q;
  139.       q=NULL;
  140.     }
  141.     return q;
  142.   }
  143.   
  144.   case LOAD_EVENT:
  145.   {
  146.     Load_log_event* l = new Load_log_event(file, timestamp, server_id);
  147.     if(log_lock) pthread_mutex_unlock(log_lock);
  148.     if (!l->table_name)
  149.     {
  150.       delete l;
  151.       l=NULL;
  152.     }
  153.     return l;
  154.   }
  155.  
  156.  
  157.   case ROTATE_EVENT:
  158.   {
  159.     Rotate_log_event* r = new Rotate_log_event(file, timestamp, server_id);
  160.     if(log_lock) pthread_mutex_unlock(log_lock);
  161.     
  162.     if (!r->new_log_ident)
  163.     {
  164.       delete r;
  165.       r=NULL;
  166.     }
  167.     return r;
  168.   }
  169.  
  170.   case INTVAR_EVENT:
  171.   {
  172.     Intvar_log_event* e = new Intvar_log_event(file, timestamp, server_id);
  173.     if(log_lock) pthread_mutex_unlock(log_lock);
  174.     
  175.     if (e->type == INVALID_INT_EVENT)
  176.     {
  177.       delete e;
  178.       e=NULL;
  179.     }
  180.     return e;
  181.   }
  182.   
  183.   case START_EVENT:
  184.     {
  185.       Start_log_event* e = new Start_log_event(file, timestamp, server_id);
  186.       if(log_lock) pthread_mutex_unlock(log_lock);
  187.       return e;
  188.     }      
  189.   case STOP_EVENT:
  190.     {
  191.       Stop_log_event* e = new Stop_log_event(file, timestamp, server_id);
  192.       if(log_lock) pthread_mutex_unlock(log_lock);
  193.       return e;
  194.     }
  195.   default:
  196.     break;
  197.   }
  198.  
  199.   // default
  200.   if (log_lock) pthread_mutex_unlock(log_lock);
  201.   return NULL;
  202. }
  203.  
  204. Log_event* Log_event::read_log_event(const char* buf, int event_len)
  205. {
  206.   if(event_len < EVENT_LEN_OFFSET ||
  207.      (uint)event_len != uint4korr(buf+EVENT_LEN_OFFSET))
  208.     return NULL; // general sanity check - will fail on a partial read
  209.   
  210.   switch(buf[EVENT_TYPE_OFFSET])
  211.   {
  212.   case QUERY_EVENT:
  213.   {
  214.     Query_log_event* q = new Query_log_event(buf, event_len);
  215.     if (!q->query)
  216.     {
  217.       delete q;
  218.       return NULL;
  219.     }
  220.  
  221.     return q;
  222.   }
  223.  
  224.   case LOAD_EVENT:
  225.   {
  226.     Load_log_event* l = new Load_log_event(buf, event_len);
  227.     if (!l->table_name)
  228.     {
  229.       delete l;
  230.       return NULL;
  231.     }
  232.  
  233.     return l;
  234.   }
  235.  
  236.   case ROTATE_EVENT:
  237.   {
  238.     Rotate_log_event* r = new Rotate_log_event(buf, event_len);
  239.     if (!r->new_log_ident)
  240.     {
  241.       delete r;
  242.       return NULL;
  243.     }
  244.  
  245.     return r;
  246.   }
  247.   case START_EVENT:  return  new Start_log_event(buf);
  248.   case STOP_EVENT:  return  new Stop_log_event(buf);
  249.   case INTVAR_EVENT:  return  new Intvar_log_event(buf);
  250.   default:
  251.     break;
  252.   }
  253.   return NULL;  // default value
  254. }
  255.  
  256. void Log_event::print_header(FILE* file)
  257. {
  258.   fputc('#', file);
  259.   print_timestamp(file);
  260.   fprintf(file, " server id  %d ", server_id); 
  261. }
  262.  
  263. void Log_event::print_timestamp(FILE* file, time_t* ts)
  264. {
  265.   struct tm tm_tmp;
  266.   if (!ts)
  267.   {
  268.     ts = &when;
  269.   }
  270.   localtime_r(ts,&tm_tmp);
  271.  
  272.   fprintf(file,"%02d%02d%02d %2d:%02d:%02d",
  273.       tm_tmp.tm_year % 100,
  274.       tm_tmp.tm_mon+1,
  275.       tm_tmp.tm_mday,
  276.       tm_tmp.tm_hour,
  277.       tm_tmp.tm_min,
  278.       tm_tmp.tm_sec);
  279. }
  280.  
  281.  
  282. void Start_log_event::print(FILE* file, bool short_form)
  283. {
  284.   if (short_form)
  285.     return;
  286.  
  287.   print_header(file);
  288.   fprintf(file, "\tStart: binlog v %d, server v %s created ", binlog_version,
  289.       server_version);
  290.   print_timestamp(file, (time_t*)&created);
  291.   fputc('\n', file);
  292.   fflush(file);
  293. }
  294.  
  295. void Stop_log_event::print(FILE* file, bool short_form)
  296. {
  297.   if (short_form)
  298.     return;
  299.  
  300.   print_header(file);
  301.   fprintf(file, "\tStop\n");
  302.   fflush(file);
  303. }
  304.  
  305. void Rotate_log_event::print(FILE* file, bool short_form)
  306. {
  307.   if (short_form)
  308.     return;
  309.  
  310.   print_header(file);
  311.   fprintf(file, "\tRotate to ");
  312.   if (new_log_ident)
  313.     my_fwrite(file, (byte*) new_log_ident, (uint)ident_len, 
  314.           MYF(MY_NABP | MY_WME));
  315.   fprintf(file, "\n");
  316.   fflush(file);
  317. }
  318.  
  319. Rotate_log_event::Rotate_log_event(IO_CACHE* file, time_t when_arg,
  320.                    uint32 server_id):
  321.   Log_event(when_arg, 0, 0, server_id),new_log_ident(NULL),alloced(0)
  322. {
  323.   char *tmp_ident;
  324.   char buf[4];
  325.  
  326.   if (my_b_read(file, (byte*) buf, sizeof(buf)))
  327.     return;
  328.   ulong event_len;
  329.   event_len = uint4korr(buf);
  330.   if (event_len < ROTATE_EVENT_OVERHEAD)
  331.     return;
  332.  
  333.   ident_len = (uchar)(event_len - ROTATE_EVENT_OVERHEAD);
  334.   if (!(tmp_ident = (char*) my_malloc((uint)ident_len, MYF(MY_WME))))
  335.     return;
  336.   if (my_b_read( file, (byte*) tmp_ident, (uint) ident_len))
  337.   {
  338.     my_free((gptr) tmp_ident, MYF(0));
  339.     return;
  340.   }
  341.  
  342.   new_log_ident = tmp_ident;
  343.   alloced = 1;
  344. }
  345.  
  346. Start_log_event::Start_log_event(const char* buf) :Log_event(buf)
  347. {
  348.   buf += EVENT_LEN_OFFSET + 4; // skip even length
  349.   binlog_version = uint2korr(buf);
  350.   memcpy(server_version, buf + 2, sizeof(server_version));
  351.   created = uint4korr(buf + 2 + sizeof(server_version));
  352. }
  353.  
  354. int Start_log_event::write_data(IO_CACHE* file)
  355. {
  356.   char buff[sizeof(server_version)+2+4];
  357.   int2store(buff,binlog_version);
  358.   memcpy(buff+2,server_version,sizeof(server_version));
  359.   int4store(buff+2+sizeof(server_version),created);
  360.   return (my_b_write(file, (byte*) buff, sizeof(buff)) ? -1 : 0);
  361. }
  362.  
  363. Rotate_log_event::Rotate_log_event(const char* buf, int event_len):
  364.   Log_event(buf),new_log_ident(NULL),alloced(0)
  365. {
  366.   // the caller will ensure that event_len is what we have at
  367.   // EVENT_LEN_OFFSET
  368.   if(event_len < ROTATE_EVENT_OVERHEAD)
  369.     return;
  370.  
  371.   ident_len = (uchar)(event_len - ROTATE_EVENT_OVERHEAD);
  372.   if (!(new_log_ident = (char*) my_memdup((byte*) buf + LOG_EVENT_HEADER_LEN,
  373.                       (uint) ident_len, MYF(MY_WME))))
  374.     return;
  375.  
  376.   alloced = 1;
  377. }
  378.  
  379. int Rotate_log_event::write_data(IO_CACHE* file)
  380. {
  381.   return my_b_write(file, (byte*) new_log_ident, (uint) ident_len) ? -1 :0;
  382. }
  383.  
  384. Query_log_event::Query_log_event(IO_CACHE* file, time_t when_arg,
  385.                  uint32 server_id):
  386.   Log_event(when_arg,0,0,server_id),data_buf(0),query(NULL),db(NULL)
  387. {
  388.   char buf[QUERY_HEADER_LEN + 4];
  389.   ulong data_len;
  390.   if (my_b_read(file, (byte*) buf, sizeof(buf)))
  391.     return;                // query == NULL will tell the
  392.                     // caller there was a problem
  393.   data_len = uint4korr(buf);
  394.   if (data_len < QUERY_EVENT_OVERHEAD)
  395.     return;                // tear-drop attack protection :)
  396.  
  397.   data_len -= QUERY_EVENT_OVERHEAD;
  398.   exec_time = uint4korr(buf + 8);
  399.   db_len = (uint)buf[12];
  400.   error_code = uint2korr(buf + 13);
  401.   
  402.   /* Allocate one byte extra for end \0 */
  403.   if (!(data_buf = (char*) my_malloc(data_len+1, MYF(MY_WME))))
  404.     return;
  405.   if (my_b_read( file, (byte*) data_buf, data_len))
  406.   {
  407.     my_free((gptr) data_buf, MYF(0));
  408.     data_buf = 0;
  409.     return;
  410.   }
  411.  
  412.   thread_id = uint4korr(buf + 4);
  413.   db = data_buf;
  414.   query=data_buf + db_len + 1;
  415.   q_len = data_len - 1 - db_len;
  416.   *((char*) query + q_len) = 0;            // Safety
  417. }
  418.  
  419. Query_log_event::Query_log_event(const char* buf, int event_len):
  420.   Log_event(buf),data_buf(0), query(NULL), db(NULL)
  421. {
  422.   if ((uint)event_len < QUERY_EVENT_OVERHEAD)
  423.     return;                
  424.   ulong data_len;
  425.   buf += EVENT_LEN_OFFSET;
  426.   data_len = event_len - QUERY_EVENT_OVERHEAD;
  427.  
  428.   exec_time = uint4korr(buf + 8);
  429.   error_code = uint2korr(buf + 13);
  430.  
  431.   if (!(data_buf = (char*) my_malloc(data_len + 1, MYF(MY_WME))))
  432.     return;
  433.  
  434.   memcpy(data_buf, buf + QUERY_HEADER_LEN + 4, data_len);
  435.   thread_id = uint4korr(buf + 4);
  436.   db = data_buf;
  437.   db_len = (uint)buf[12];
  438.   query=data_buf + db_len + 1;
  439.   q_len = data_len - 1 - db_len;
  440.   *((char*)query+q_len) = 0;
  441. }
  442.  
  443. void Query_log_event::print(FILE* file, bool short_form)
  444. {
  445.   if (!short_form)
  446.   {
  447.     print_header(file);
  448.     fprintf(file, "\tQuery\tthread_id=%lu\texec_time=%lu\terror_code=%d\n",
  449.         (ulong) thread_id, (ulong) exec_time, error_code);
  450.   }
  451.  
  452.   if(db && db[0])
  453.     fprintf(file, "use %s;\n", db);
  454.   my_fwrite(file, (byte*) query, q_len, MYF(MY_NABP | MY_WME));
  455.   fprintf(file, ";\n");
  456. }
  457.  
  458. int Query_log_event::write_data(IO_CACHE* file)
  459. {
  460.   if (!query) return -1;
  461.   
  462.   char buf[QUERY_HEADER_LEN]; 
  463.   char* pos = buf;
  464.   int4store(pos, thread_id);
  465.   pos += 4;
  466.   int4store(pos, exec_time);
  467.   pos += 4;
  468.   *pos++ = (char)db_len;
  469.   int2store(pos, error_code);
  470.   pos += 2;
  471.  
  472.   return (my_b_write(file, (byte*) buf, (uint)(pos - buf)) ||
  473.       my_b_write(file, (db) ? (byte*) db : (byte*)"", db_len + 1) ||
  474.       my_b_write(file, (byte*) query, q_len)) ? -1 : 0;
  475. }
  476.  
  477. Intvar_log_event:: Intvar_log_event(IO_CACHE* file, time_t when_arg,
  478.                     uint32 server_id)
  479.   :Log_event(when_arg,0,0,server_id), type(INVALID_INT_EVENT)
  480. {
  481.   char buf[9+4];
  482.   if (!my_b_read(file, (byte*) buf, sizeof(buf)))
  483.   {
  484.     type = buf[4];
  485.     val = uint8korr(buf+1+4);
  486.   }
  487. }
  488.  
  489. Intvar_log_event::Intvar_log_event(const char* buf):Log_event(buf)
  490. {
  491.   buf += LOG_EVENT_HEADER_LEN;
  492.   type = buf[0];
  493.   val = uint8korr(buf+1);
  494. }
  495.  
  496. int Intvar_log_event::write_data(IO_CACHE* file)
  497. {
  498.   char buf[9];
  499.   buf[0] = type;
  500.   int8store(buf + 1, val);
  501.   return my_b_write(file, (byte*) buf, sizeof(buf));
  502. }
  503.  
  504. void Intvar_log_event::print(FILE* file, bool short_form)
  505. {
  506.   char llbuff[22];
  507.   if(!short_form)
  508.   {
  509.     print_header(file);
  510.     fprintf(file, "\tIntvar\n");
  511.   }
  512.  
  513.   fprintf(file, "SET ");
  514.   switch(type)
  515.   {
  516.   case LAST_INSERT_ID_EVENT:
  517.     fprintf(file, "LAST_INSERT_ID = ");
  518.     break;
  519.   case INSERT_ID_EVENT:
  520.     fprintf(file, "INSERT_ID = ");
  521.     break;
  522.   }
  523.   fprintf(file, "%s;\n", llstr(val,llbuff));
  524.   fflush(file);
  525.   
  526. }
  527.  
  528. int Load_log_event::write_data(IO_CACHE* file)
  529. {
  530.   char buf[LOAD_HEADER_LEN];
  531.   int4store(buf, thread_id);
  532.   int4store(buf + 4, exec_time);
  533.   int4store(buf + 8, skip_lines);
  534.   buf[12] = (char)table_name_len;
  535.   buf[13] = (char)db_len;
  536.   int4store(buf + 14, num_fields);
  537.   
  538.   if(my_b_write(file, (byte*)buf, sizeof(buf)) ||
  539.      my_b_write(file, (byte*)&sql_ex, sizeof(sql_ex)))
  540.     return 1;
  541.  
  542.   if (num_fields && fields && field_lens)
  543.   {
  544.     if(my_b_write(file, (byte*)field_lens, num_fields) ||
  545.        my_b_write(file, (byte*)fields, field_block_len))
  546.       return 1;
  547.   }
  548.   if(my_b_write(file, (byte*)table_name, table_name_len + 1) ||
  549.      my_b_write(file, (byte*)db, db_len + 1) ||
  550.      my_b_write(file, (byte*)fname, fname_len))
  551.     return 1;
  552.   return 0;
  553. }
  554.  
  555. Load_log_event::Load_log_event(IO_CACHE* file, time_t when, uint32 server_id):
  556.   Log_event(when,0,0,server_id),data_buf(0),num_fields(0),
  557.   fields(0),field_lens(0),field_block_len(0),
  558.   table_name(0),db(0),fname(0)
  559. {
  560.   char buf[LOAD_HEADER_LEN + 4];
  561.   ulong data_len;
  562.   if (my_b_read(file, (byte*)buf, sizeof(buf)) ||
  563.       my_b_read(file, (byte*)&sql_ex, sizeof(sql_ex)))
  564.     return;
  565.  
  566.   data_len = uint4korr(buf) - LOAD_EVENT_OVERHEAD;
  567.   if (!(data_buf = (char*)my_malloc(data_len + 1, MYF(MY_WME))))
  568.     return;
  569.   if (my_b_read(file, (byte*)data_buf, data_len))
  570.     return;
  571.   copy_log_event(buf,data_len);
  572. }
  573.  
  574. Load_log_event::Load_log_event(const char* buf, int event_len):
  575.   Log_event(when,0,0,server_id),data_buf(0),num_fields(0),fields(0),
  576.   field_lens(0),field_block_len(0),
  577.   table_name(0),db(0),fname(0)
  578. {
  579.   ulong data_len;
  580.  
  581.   if((uint)event_len < (LOAD_EVENT_OVERHEAD + LOG_EVENT_HEADER_LEN))
  582.     return;
  583.   buf += EVENT_LEN_OFFSET;
  584.   memcpy(&sql_ex, buf + LOAD_HEADER_LEN + 4, sizeof(sql_ex));
  585.   data_len = event_len;
  586.   
  587.   if(!(data_buf = (char*)my_malloc(data_len + 1, MYF(MY_WME))))
  588.     return;
  589.   memcpy(data_buf, buf + 22 + sizeof(sql_ex), data_len);
  590.   copy_log_event(buf, data_len);
  591. }
  592.  
  593. void Load_log_event::copy_log_event(const char *buf, ulong data_len)
  594. {
  595.   thread_id = uint4korr(buf+4);
  596.   exec_time = uint4korr(buf+8);
  597.   skip_lines = uint4korr(buf + 12);
  598.   table_name_len = (uint)buf[16];
  599.   db_len = (uint)buf[17];
  600.   num_fields = uint4korr(buf + 18);
  601.       
  602.   if (num_fields > data_len) // simple sanity check against corruption
  603.     return;
  604.  
  605.   field_lens = (uchar*) data_buf;
  606.   uint i;
  607.   for (i = 0; i < num_fields; i++)
  608.   {
  609.     field_block_len += (uint)field_lens[i] + 1;
  610.   }
  611.   fields = (char*)field_lens + num_fields;
  612.   
  613.   *((char*)data_buf+data_len) = 0;
  614.   table_name  = fields + field_block_len;
  615.   db = table_name + table_name_len + 1;
  616.   fname = db + db_len + 1;
  617.   fname_len = data_len - 2 - db_len - table_name_len - num_fields -
  618.     field_block_len;
  619. }
  620.  
  621.  
  622. void Load_log_event::print(FILE* file, bool short_form)
  623. {
  624.   if (!short_form)
  625.   {
  626.     print_header(file);
  627.     fprintf(file, "\tQuery\tthread_id=%d\texec_time=%ld\n",
  628.         thread_id, exec_time);
  629.   }
  630.  
  631.   if(db && db[0])
  632.     fprintf(file, "use %s;\n", db);
  633.  
  634.   fprintf(file, "LOAD DATA INFILE '%s' ", fname);
  635.  
  636.   if(sql_ex.opt_flags && REPLACE_FLAG )
  637.     fprintf(file," REPLACE ");
  638.   else if(sql_ex.opt_flags && IGNORE_FLAG )
  639.     fprintf(file," IGNORE ");
  640.   
  641.   fprintf(file, "INTO TABLE %s ", table_name);
  642.   if(!(sql_ex.empty_flags & FIELD_TERM_EMPTY))
  643.   {
  644.     fprintf(file, " FIELDS TERMINATED BY ");
  645.     pretty_print_char(file, sql_ex.field_term);
  646.   }
  647.  
  648.   if(!(sql_ex.empty_flags & ENCLOSED_EMPTY))
  649.   {
  650.     if(sql_ex.opt_flags && OPT_ENCLOSED_FLAG )
  651.       fprintf(file," OPTIONALLY ");
  652.     fprintf(file, " ENCLOSED BY ");
  653.     pretty_print_char(file, sql_ex.enclosed);
  654.   }
  655.      
  656.   if(!(sql_ex.empty_flags & ESCAPED_EMPTY))
  657.   {
  658.     fprintf(file, " ESCAPED BY ");
  659.     pretty_print_char(file, sql_ex.escaped);
  660.   }
  661.      
  662.   if(!(sql_ex.empty_flags & LINE_TERM_EMPTY))
  663.   {
  664.     fprintf(file," LINES TERMINATED BY ");
  665.     pretty_print_char(file, sql_ex.line_term);
  666.   }
  667.  
  668.   if(!(sql_ex.empty_flags & LINE_START_EMPTY))
  669.   {
  670.     fprintf(file," LINES STARTING BY ");
  671.     pretty_print_char(file, sql_ex.line_start);
  672.   }
  673.      
  674.   if((int)skip_lines > 0)
  675.     fprintf(file, " IGNORE %d LINES ", skip_lines);
  676.  
  677.   if (num_fields)
  678.   {
  679.     uint i;
  680.     const char* field = fields;
  681.     fprintf( file, " (");
  682.     for(i = 0; i < num_fields; i++)
  683.     {
  684.       if(i)
  685.     fputc(',', file);
  686.       fprintf(file, field);
  687.       
  688.       field += field_lens[i]  + 1;
  689.     }
  690.     fputc(')', file);
  691.   }
  692.  
  693.   fprintf(file, ";\n");
  694. }
  695.  
  696. #ifndef MYSQL_CLIENT
  697.  
  698. void Load_log_event::set_fields(List<Item> &fields)
  699. {
  700.   uint i;
  701.   const char* field = this->fields;
  702.   for(i = 0; i < num_fields; i++)
  703.     {
  704.       fields.push_back(new Item_field(db, table_name, field));      
  705.       field += field_lens[i]  + 1;
  706.     }
  707.   
  708. }
  709.  
  710. #endif
  711.