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

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