log_event.cc 17.8 KB
Newer Older
unknown's avatar
unknown committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
   
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.
   
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
   
   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */


#ifndef MYSQL_CLIENT
#ifdef __GNUC__
#pragma implementation				// gcc: Class implementation
#endif
#include  "mysql_priv.h"
#endif /* MYSQL_CLIENT */


static void pretty_print_char(FILE* file, int c)
{
  fputc('\'', file);
29 30 31 32 33 34 35 36 37 38 39 40
  switch(c) {
  case '\n': fprintf(file, "\\n"); break;
  case '\r': fprintf(file, "\\r"); break;
  case '\\': fprintf(file, "\\\\"); break;
  case '\b': fprintf(file, "\\b"); break;
  case '\'': fprintf(file, "\\'"); break;
  case 0   : fprintf(file, "\\0"); break;
  default:
    fputc(c, file);
    break;
  }
  fputc('\'', file);
unknown's avatar
unknown committed
41 42
}

43
int Query_log_event::write(IO_CACHE* file)
unknown's avatar
unknown committed
44 45 46 47
{
  return query ? Log_event::write(file) : -1; 
}

48
int Log_event::write(IO_CACHE* file)
unknown's avatar
unknown committed
49
{
50
  return (write_header(file) || write_data(file)) ? -1 : 0;
unknown's avatar
unknown committed
51 52
}

53
int Log_event::write_header(IO_CACHE* file)
unknown's avatar
unknown committed
54 55
{
  // make sure to change this when the header gets bigger
56
  char buf[LOG_EVENT_HEADER_LEN];
unknown's avatar
unknown committed
57 58 59 60
  char* pos = buf;
  int4store(pos, when); // timestamp
  pos += 4;
  *pos++ = get_type_code(); // event type code
61 62
  int4store(pos, server_id);
  pos += 4;
63 64
  long tmp=get_data_size() + LOG_EVENT_HEADER_LEN;
  int4store(pos, tmp);
unknown's avatar
unknown committed
65
  pos += 4;
66
  return (my_b_write(file, (byte*) buf, (uint) (pos - buf)));
unknown's avatar
unknown committed
67 68 69 70
}

#ifndef MYSQL_CLIENT

71
int Log_event::read_log_event(IO_CACHE* file, String* packet,
72
			      pthread_mutex_t* log_lock)
unknown's avatar
unknown committed
73 74 75
{
  ulong data_len;
  char buf[LOG_EVENT_HEADER_LEN];
76
  if (log_lock)
77
    pthread_mutex_lock(log_lock);
78 79 80
  if (my_b_read(file, (byte*) buf, sizeof(buf)))
  {
    if (log_lock) pthread_mutex_unlock(log_lock);
unknown's avatar
unknown committed
81 82 83
    // if the read hits eof, we must report it as eof
    // so the caller will know it can go into cond_wait to be woken up
    // on the next update to the log
unknown's avatar
unknown committed
84 85
    if(!file->error) return LOG_READ_EOF;
    return file->error > 0 ? LOG_READ_TRUNC: LOG_READ_IO;
86
  }
unknown's avatar
unknown committed
87
  data_len = uint4korr(buf + EVENT_LEN_OFFSET);
unknown's avatar
unknown committed
88
  if (data_len < LOG_EVENT_HEADER_LEN || data_len > max_allowed_packet)
89 90
  {
    if (log_lock) pthread_mutex_unlock(log_lock);
unknown's avatar
unknown committed
91 92
    return (data_len < LOG_EVENT_HEADER_LEN) ? LOG_READ_BOGUS :
      LOG_READ_TOO_LARGE;
93
  }
unknown's avatar
unknown committed
94 95
  packet->append(buf, sizeof(buf));
  data_len -= LOG_EVENT_HEADER_LEN;
96 97 98
  if (data_len)
  {
    if (packet->append(file, data_len))
99 100 101
    {
      if(log_lock)
	pthread_mutex_unlock(log_lock);
unknown's avatar
unknown committed
102 103 104
      // here we should never hit eof in a non-error condtion
      // eof means we are reading the event partially, which should
      // never happen
105
      return file->error >= 0 ? LOG_READ_TRUNC: LOG_READ_IO;
106
    }
107 108
  }
  if (log_lock) pthread_mutex_unlock(log_lock);
unknown's avatar
unknown committed
109 110 111 112 113 114 115
  return 0;
}

#endif // MYSQL_CLIENT

// allocates memory - the caller is responsible for clean-up

116
Log_event* Log_event::read_log_event(IO_CACHE* file, pthread_mutex_t* log_lock)
unknown's avatar
unknown committed
117 118
{
  time_t timestamp;
119 120 121
  uint32 server_id;
  
  char buf[LOG_EVENT_HEADER_LEN-4];
122
  if(log_lock) pthread_mutex_lock(log_lock);
123 124 125 126 127
  if (my_b_read(file, (byte *) buf, sizeof(buf)))
  {
    if (log_lock) pthread_mutex_unlock(log_lock);
    return NULL;
  }
unknown's avatar
unknown committed
128
  timestamp = uint4korr(buf);
129 130
  server_id = uint4korr(buf + 5);
  
unknown's avatar
unknown committed
131 132 133 134
  switch(buf[EVENT_TYPE_OFFSET])
  {
  case QUERY_EVENT:
  {
135
    Query_log_event* q = new Query_log_event(file, timestamp, server_id);
136
    if(log_lock) pthread_mutex_unlock(log_lock);
unknown's avatar
unknown committed
137 138 139
    if (!q->query)
    {
      delete q;
140
      q=NULL;
unknown's avatar
unknown committed
141 142 143 144 145 146
    }
    return q;
  }
  
  case LOAD_EVENT:
  {
147
    Load_log_event* l = new Load_log_event(file, timestamp, server_id);
148
    if(log_lock) pthread_mutex_unlock(log_lock);
unknown's avatar
unknown committed
149 150 151
    if (!l->table_name)
    {
      delete l;
152
      l=NULL;
unknown's avatar
unknown committed
153 154 155 156 157 158 159
    }
    return l;
  }


  case ROTATE_EVENT:
  {
160
    Rotate_log_event* r = new Rotate_log_event(file, timestamp, server_id);
161 162
    if(log_lock) pthread_mutex_unlock(log_lock);
    
unknown's avatar
unknown committed
163 164 165
    if (!r->new_log_ident)
    {
      delete r;
166
      r=NULL;
unknown's avatar
unknown committed
167 168 169 170 171 172
    }
    return r;
  }

  case INTVAR_EVENT:
  {
173
    Intvar_log_event* e = new Intvar_log_event(file, timestamp, server_id);
174 175
    if(log_lock) pthread_mutex_unlock(log_lock);
    
unknown's avatar
unknown committed
176 177 178
    if (e->type == INVALID_INT_EVENT)
    {
      delete e;
179
      e=NULL;
unknown's avatar
unknown committed
180 181 182 183
    }
    return e;
  }
  
184 185 186 187 188 189 190 191 192 193 194 195 196
  case START_EVENT:
    {
      Start_log_event* e = new Start_log_event(file, timestamp, server_id);
      if(log_lock) pthread_mutex_unlock(log_lock);
      return e;
    }	  
  case STOP_EVENT:
    {
      Stop_log_event* e = new Stop_log_event(file, timestamp, server_id);
      if(log_lock) pthread_mutex_unlock(log_lock);
      return e;
    }
  default:
197
    break;
unknown's avatar
unknown committed
198 199
  }

200 201
  // default
  if (log_lock) pthread_mutex_unlock(log_lock);
unknown's avatar
unknown committed
202 203 204
  return NULL;
}

205
Log_event* Log_event::read_log_event(const char* buf, int event_len)
unknown's avatar
unknown committed
206
{
207 208 209 210
  if(event_len < EVENT_LEN_OFFSET ||
     (uint)event_len != uint4korr(buf+EVENT_LEN_OFFSET))
    return NULL; // general sanity check - will fail on a partial read
  
unknown's avatar
unknown committed
211 212 213 214
  switch(buf[EVENT_TYPE_OFFSET])
  {
  case QUERY_EVENT:
  {
215
    Query_log_event* q = new Query_log_event(buf, event_len);
unknown's avatar
unknown committed
216 217 218 219 220 221 222 223 224 225 226
    if (!q->query)
    {
      delete q;
      return NULL;
    }

    return q;
  }

  case LOAD_EVENT:
  {
227
    Load_log_event* l = new Load_log_event(buf, event_len);
unknown's avatar
unknown committed
228 229 230 231 232 233 234 235 236 237 238
    if (!l->table_name)
    {
      delete l;
      return NULL;
    }

    return l;
  }

  case ROTATE_EVENT:
  {
239
    Rotate_log_event* r = new Rotate_log_event(buf, event_len);
unknown's avatar
unknown committed
240 241 242 243 244 245 246 247
    if (!r->new_log_ident)
    {
      delete r;
      return NULL;
    }

    return r;
  }
248 249 250
  case START_EVENT:  return  new Start_log_event(buf);
  case STOP_EVENT:  return  new Stop_log_event(buf);
  case INTVAR_EVENT:  return  new Intvar_log_event(buf);
251 252
  default:
    break;
unknown's avatar
unknown committed
253
  }
254
  return NULL;  // default value
unknown's avatar
unknown committed
255 256
}

257 258 259 260
void Log_event::print_header(FILE* file)
{
  fputc('#', file);
  print_timestamp(file);
261
  fprintf(file, " server id  %d ", server_id); 
262 263
}

264
void Log_event::print_timestamp(FILE* file, time_t* ts)
unknown's avatar
unknown committed
265
{
266 267 268 269 270 271 272 273 274 275 276 277 278 279
  struct tm tm_tmp;
  if (!ts)
  {
    ts = &when;
  }
  localtime_r(ts,&tm_tmp);

  fprintf(file,"%02d%02d%02d %2d:%02d:%02d",
	  tm_tmp.tm_year % 100,
	  tm_tmp.tm_mon+1,
	  tm_tmp.tm_mday,
	  tm_tmp.tm_hour,
	  tm_tmp.tm_min,
	  tm_tmp.tm_sec);
unknown's avatar
unknown committed
280 281 282
}


283
void Start_log_event::print(FILE* file, bool short_form, char* last_db)
unknown's avatar
unknown committed
284 285 286 287
{
  if (short_form)
    return;

288 289 290 291 292
  print_header(file);
  fprintf(file, "\tStart: binlog v %d, server v %s created ", binlog_version,
	  server_version);
  print_timestamp(file, (time_t*)&created);
  fputc('\n', file);
unknown's avatar
unknown committed
293 294 295
  fflush(file);
}

296
void Stop_log_event::print(FILE* file, bool short_form, char* last_db)
unknown's avatar
unknown committed
297 298 299 300
{
  if (short_form)
    return;

301
  print_header(file);
unknown's avatar
unknown committed
302 303 304 305
  fprintf(file, "\tStop\n");
  fflush(file);
}

306
void Rotate_log_event::print(FILE* file, bool short_form, char* last_db)
unknown's avatar
unknown committed
307 308 309 310
{
  if (short_form)
    return;

311
  print_header(file);
unknown's avatar
unknown committed
312 313 314 315 316 317 318 319
  fprintf(file, "\tRotate to ");
  if (new_log_ident)
    my_fwrite(file, (byte*) new_log_ident, (uint)ident_len, 
	      MYF(MY_NABP | MY_WME));
  fprintf(file, "\n");
  fflush(file);
}

320
Rotate_log_event::Rotate_log_event(IO_CACHE* file, time_t when_arg,
321 322
				   uint32 server_id):
  Log_event(when_arg, 0, 0, server_id),new_log_ident(NULL),alloced(0)
unknown's avatar
unknown committed
323 324 325 326
{
  char *tmp_ident;
  char buf[4];

327
  if (my_b_read(file, (byte*) buf, sizeof(buf)))
unknown's avatar
unknown committed
328 329 330
    return;
  ulong event_len;
  event_len = uint4korr(buf);
331
  if (event_len < ROTATE_EVENT_OVERHEAD)
unknown's avatar
unknown committed
332 333 334 335 336
    return;

  ident_len = (uchar)(event_len - ROTATE_EVENT_OVERHEAD);
  if (!(tmp_ident = (char*) my_malloc((uint)ident_len, MYF(MY_WME))))
    return;
337
  if (my_b_read( file, (byte*) tmp_ident, (uint) ident_len))
unknown's avatar
unknown committed
338 339 340 341 342 343 344 345 346
  {
    my_free((gptr) tmp_ident, MYF(0));
    return;
  }

  new_log_ident = tmp_ident;
  alloced = 1;
}

347 348 349 350 351 352 353 354
Start_log_event::Start_log_event(const char* buf) :Log_event(buf)
{
  buf += EVENT_LEN_OFFSET + 4; // skip even length
  binlog_version = uint2korr(buf);
  memcpy(server_version, buf + 2, sizeof(server_version));
  created = uint4korr(buf + 2 + sizeof(server_version));
}

355 356 357 358 359 360 361 362 363
int Start_log_event::write_data(IO_CACHE* file)
{
  char buff[sizeof(server_version)+2+4];
  int2store(buff,binlog_version);
  memcpy(buff+2,server_version,sizeof(server_version));
  int4store(buff+2+sizeof(server_version),created);
  return (my_b_write(file, (byte*) buff, sizeof(buff)) ? -1 : 0);
}

364
Rotate_log_event::Rotate_log_event(const char* buf, int event_len):
unknown's avatar
unknown committed
365 366
  Log_event(buf),new_log_ident(NULL),alloced(0)
{
367 368 369
  // the caller will ensure that event_len is what we have at
  // EVENT_LEN_OFFSET
  if(event_len < ROTATE_EVENT_OVERHEAD)
unknown's avatar
unknown committed
370 371 372 373 374 375 376 377 378 379
    return;

  ident_len = (uchar)(event_len - ROTATE_EVENT_OVERHEAD);
  if (!(new_log_ident = (char*) my_memdup((byte*) buf + LOG_EVENT_HEADER_LEN,
					  (uint) ident_len, MYF(MY_WME))))
    return;

  alloced = 1;
}

380
int Rotate_log_event::write_data(IO_CACHE* file)
unknown's avatar
unknown committed
381
{
382
  return my_b_write(file, (byte*) new_log_ident, (uint) ident_len) ? -1 :0;
unknown's avatar
unknown committed
383 384
}

385
Query_log_event::Query_log_event(IO_CACHE* file, time_t when_arg,
386 387
				 uint32 server_id):
  Log_event(when_arg,0,0,server_id),data_buf(0),query(NULL),db(NULL)
unknown's avatar
unknown committed
388 389 390
{
  char buf[QUERY_HEADER_LEN + 4];
  ulong data_len;
391
  if (my_b_read(file, (byte*) buf, sizeof(buf)))
unknown's avatar
unknown committed
392 393 394 395 396 397 398 399 400
    return;				// query == NULL will tell the
					// caller there was a problem
  data_len = uint4korr(buf);
  if (data_len < QUERY_EVENT_OVERHEAD)
    return;				// tear-drop attack protection :)

  data_len -= QUERY_EVENT_OVERHEAD;
  exec_time = uint4korr(buf + 8);
  db_len = (uint)buf[12];
401
  error_code = uint2korr(buf + 13);
unknown's avatar
unknown committed
402
  
403
  /* Allocate one byte extra for end \0 */
unknown's avatar
unknown committed
404 405
  if (!(data_buf = (char*) my_malloc(data_len+1, MYF(MY_WME))))
    return;
406
  if (my_b_read( file, (byte*) data_buf, data_len))
unknown's avatar
unknown committed
407 408 409 410 411 412 413 414 415 416
  {
    my_free((gptr) data_buf, MYF(0));
    data_buf = 0;
    return;
  }

  thread_id = uint4korr(buf + 4);
  db = data_buf;
  query=data_buf + db_len + 1;
  q_len = data_len - 1 - db_len;
417
  *((char*) query + q_len) = 0;			// Safety
unknown's avatar
unknown committed
418 419
}

420
Query_log_event::Query_log_event(const char* buf, int event_len):
unknown's avatar
unknown committed
421 422
  Log_event(buf),data_buf(0), query(NULL), db(NULL)
{
423
  if ((uint)event_len < QUERY_EVENT_OVERHEAD)
424
    return;				
unknown's avatar
unknown committed
425 426
  ulong data_len;
  buf += EVENT_LEN_OFFSET;
427
  data_len = event_len - QUERY_EVENT_OVERHEAD;
unknown's avatar
unknown committed
428 429

  exec_time = uint4korr(buf + 8);
430
  error_code = uint2korr(buf + 13);
unknown's avatar
unknown committed
431

432
  if (!(data_buf = (char*) my_malloc(data_len + 1, MYF(MY_WME))))
unknown's avatar
unknown committed
433 434
    return;

435
  memcpy(data_buf, buf + QUERY_HEADER_LEN + 4, data_len);
unknown's avatar
unknown committed
436 437 438 439 440 441 442 443
  thread_id = uint4korr(buf + 4);
  db = data_buf;
  db_len = (uint)buf[12];
  query=data_buf + db_len + 1;
  q_len = data_len - 1 - db_len;
  *((char*)query+q_len) = 0;
}

444
void Query_log_event::print(FILE* file, bool short_form, char* last_db)
unknown's avatar
unknown committed
445
{
446
  char buff[40],*end;				// Enough for SET TIMESTAMP
unknown's avatar
unknown committed
447 448
  if (!short_form)
  {
449
    print_header(file);
450 451
    fprintf(file, "\tQuery\tthread_id=%lu\texec_time=%lu\terror_code=%d\n",
	    (ulong) thread_id, (ulong) exec_time, error_code);
unknown's avatar
unknown committed
452 453
  }

454 455 456 457
  bool same_db = 0;

  if(db && last_db)
    {
unknown's avatar
unknown committed
458
      if(!(same_db = !memcmp(last_db, db, db_len + 1)))
459 460 461 462
        memcpy(last_db, db, db_len + 1);
    }
  
  if (db && db[0] && !same_db)
unknown's avatar
unknown committed
463
    fprintf(file, "use %s;\n", db);
464 465 466 467
  end=int10_to_str((long) when, strmov(buff,"SET TIMESTAMP="),10);
  *end++=';';
  *end++='\n';
  my_fwrite(file, (byte*) buff, (uint) (end-buff),MYF(MY_NABP | MY_WME));
unknown's avatar
unknown committed
468 469 470 471
  my_fwrite(file, (byte*) query, q_len, MYF(MY_NABP | MY_WME));
  fprintf(file, ";\n");
}

472
int Query_log_event::write_data(IO_CACHE* file)
unknown's avatar
unknown committed
473
{
474
  if (!query) return -1;
unknown's avatar
unknown committed
475 476 477 478 479 480 481 482
  
  char buf[QUERY_HEADER_LEN]; 
  char* pos = buf;
  int4store(pos, thread_id);
  pos += 4;
  int4store(pos, exec_time);
  pos += 4;
  *pos++ = (char)db_len;
483 484
  int2store(pos, error_code);
  pos += 2;
unknown's avatar
unknown committed
485

486 487 488
  return (my_b_write(file, (byte*) buf, (uint)(pos - buf)) ||
	  my_b_write(file, (db) ? (byte*) db : (byte*)"", db_len + 1) ||
	  my_b_write(file, (byte*) query, q_len)) ? -1 : 0;
unknown's avatar
unknown committed
489 490
}

491
Intvar_log_event:: Intvar_log_event(IO_CACHE* file, time_t when_arg,
492 493
				    uint32 server_id)
  :Log_event(when_arg,0,0,server_id), type(INVALID_INT_EVENT)
unknown's avatar
unknown committed
494
{
495 496 497 498 499 500
  char buf[9+4];
  if (!my_b_read(file, (byte*) buf, sizeof(buf)))
  {
    type = buf[4];
    val = uint8korr(buf+1+4);
  }
unknown's avatar
unknown committed
501 502 503 504 505 506 507 508 509
}

Intvar_log_event::Intvar_log_event(const char* buf):Log_event(buf)
{
  buf += LOG_EVENT_HEADER_LEN;
  type = buf[0];
  val = uint8korr(buf+1);
}

510
int Intvar_log_event::write_data(IO_CACHE* file)
unknown's avatar
unknown committed
511 512 513 514
{
  char buf[9];
  buf[0] = type;
  int8store(buf + 1, val);
515
  return my_b_write(file, (byte*) buf, sizeof(buf));
unknown's avatar
unknown committed
516 517
}

518
void Intvar_log_event::print(FILE* file, bool short_form, char* last_db)
unknown's avatar
unknown committed
519 520 521 522
{
  char llbuff[22];
  if(!short_form)
  {
523
    print_header(file);
unknown's avatar
unknown committed
524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541
    fprintf(file, "\tIntvar\n");
  }

  fprintf(file, "SET ");
  switch(type)
  {
  case LAST_INSERT_ID_EVENT:
    fprintf(file, "LAST_INSERT_ID = ");
    break;
  case INSERT_ID_EVENT:
    fprintf(file, "INSERT_ID = ");
    break;
  }
  fprintf(file, "%s;\n", llstr(val,llbuff));
  fflush(file);
  
}

542
int Load_log_event::write_data(IO_CACHE* file)
unknown's avatar
unknown committed
543 544 545 546 547 548 549 550 551
{
  char buf[LOAD_HEADER_LEN];
  int4store(buf, thread_id);
  int4store(buf + 4, exec_time);
  int4store(buf + 8, skip_lines);
  buf[12] = (char)table_name_len;
  buf[13] = (char)db_len;
  int4store(buf + 14, num_fields);
  
552 553
  if(my_b_write(file, (byte*)buf, sizeof(buf)) ||
     my_b_write(file, (byte*)&sql_ex, sizeof(sql_ex)))
unknown's avatar
unknown committed
554 555
    return 1;

556 557 558 559 560 561 562 563 564
  if (num_fields && fields && field_lens)
  {
    if(my_b_write(file, (byte*)field_lens, num_fields) ||
       my_b_write(file, (byte*)fields, field_block_len))
      return 1;
  }
  if(my_b_write(file, (byte*)table_name, table_name_len + 1) ||
     my_b_write(file, (byte*)db, db_len + 1) ||
     my_b_write(file, (byte*)fname, fname_len))
unknown's avatar
unknown committed
565 566 567 568
    return 1;
  return 0;
}

569
Load_log_event::Load_log_event(IO_CACHE* file, time_t when, uint32 server_id):
570 571
  Log_event(when,0,0,server_id),data_buf(0),num_fields(0),
  fields(0),field_lens(0),field_block_len(0),
unknown's avatar
unknown committed
572 573 574 575
  table_name(0),db(0),fname(0)
{
  char buf[LOAD_HEADER_LEN + 4];
  ulong data_len;
576 577
  if (my_b_read(file, (byte*)buf, sizeof(buf)) ||
      my_b_read(file, (byte*)&sql_ex, sizeof(sql_ex)))
unknown's avatar
unknown committed
578 579
    return;

580 581
  data_len = uint4korr(buf) - LOAD_EVENT_OVERHEAD;
  if (!(data_buf = (char*)my_malloc(data_len + 1, MYF(MY_WME))))
unknown's avatar
unknown committed
582
    return;
583
  if (my_b_read(file, (byte*)data_buf, data_len))
unknown's avatar
unknown committed
584
    return;
585
  copy_log_event(buf,data_len);
unknown's avatar
unknown committed
586 587
}

588
Load_log_event::Load_log_event(const char* buf, int event_len):
589
  Log_event(buf),data_buf(0),num_fields(0),fields(0),
590
  field_lens(0),field_block_len(0),
unknown's avatar
unknown committed
591 592 593 594
  table_name(0),db(0),fname(0)
{
  ulong data_len;

595
  if((uint)event_len < (LOAD_EVENT_OVERHEAD + LOG_EVENT_HEADER_LEN))
unknown's avatar
unknown committed
596 597
    return;
  buf += EVENT_LEN_OFFSET;
598
  memcpy(&sql_ex, buf + LOAD_HEADER_LEN + 4, sizeof(sql_ex));
599
  data_len = event_len;
unknown's avatar
unknown committed
600
  
601 602 603 604 605 606 607 608
  if(!(data_buf = (char*)my_malloc(data_len + 1, MYF(MY_WME))))
    return;
  memcpy(data_buf, buf + 22 + sizeof(sql_ex), data_len);
  copy_log_event(buf, data_len);
}

void Load_log_event::copy_log_event(const char *buf, ulong data_len)
{
unknown's avatar
unknown committed
609 610 611 612 613 614 615
  thread_id = uint4korr(buf+4);
  exec_time = uint4korr(buf+8);
  skip_lines = uint4korr(buf + 12);
  table_name_len = (uint)buf[16];
  db_len = (uint)buf[17];
  num_fields = uint4korr(buf + 18);
	  
616
  if (num_fields > data_len) // simple sanity check against corruption
unknown's avatar
unknown committed
617 618
    return;

619
  field_lens = (uchar*) data_buf;
unknown's avatar
unknown committed
620
  uint i;
621 622 623 624
  for (i = 0; i < num_fields; i++)
  {
    field_block_len += (uint)field_lens[i] + 1;
  }
unknown's avatar
unknown committed
625 626 627 628 629 630
  fields = (char*)field_lens + num_fields;
  
  *((char*)data_buf+data_len) = 0;
  table_name  = fields + field_block_len;
  db = table_name + table_name_len + 1;
  fname = db + db_len + 1;
631 632
  fname_len = data_len - 2 - db_len - table_name_len - num_fields -
    field_block_len;
unknown's avatar
unknown committed
633 634 635
}


636
void Load_log_event::print(FILE* file, bool short_form, char* last_db)
unknown's avatar
unknown committed
637 638 639
{
  if (!short_form)
  {
640
    print_header(file);
641
    fprintf(file, "\tQuery\tthread_id=%ld\texec_time=%ld\n",
unknown's avatar
unknown committed
642 643 644
	    thread_id, exec_time);
  }

645 646 647 648
  bool same_db = 0;

  if(db && last_db)
    {
unknown's avatar
unknown committed
649
      if(!(same_db = !memcmp(last_db, db, db_len + 1)))
650 651 652 653
        memcpy(last_db, db, db_len + 1);
    }
  
  if(db && db[0] && !same_db)
unknown's avatar
unknown committed
654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696
    fprintf(file, "use %s;\n", db);

  fprintf(file, "LOAD DATA INFILE '%s' ", fname);

  if(sql_ex.opt_flags && REPLACE_FLAG )
    fprintf(file," REPLACE ");
  else if(sql_ex.opt_flags && IGNORE_FLAG )
    fprintf(file," IGNORE ");
  
  fprintf(file, "INTO TABLE %s ", table_name);
  if(!(sql_ex.empty_flags & FIELD_TERM_EMPTY))
  {
    fprintf(file, " FIELDS TERMINATED BY ");
    pretty_print_char(file, sql_ex.field_term);
  }

  if(!(sql_ex.empty_flags & ENCLOSED_EMPTY))
  {
    if(sql_ex.opt_flags && OPT_ENCLOSED_FLAG )
      fprintf(file," OPTIONALLY ");
    fprintf(file, " ENCLOSED BY ");
    pretty_print_char(file, sql_ex.enclosed);
  }
     
  if(!(sql_ex.empty_flags & ESCAPED_EMPTY))
  {
    fprintf(file, " ESCAPED BY ");
    pretty_print_char(file, sql_ex.escaped);
  }
     
  if(!(sql_ex.empty_flags & LINE_TERM_EMPTY))
  {
    fprintf(file," LINES TERMINATED BY ");
    pretty_print_char(file, sql_ex.line_term);
  }

  if(!(sql_ex.empty_flags & LINE_START_EMPTY))
  {
    fprintf(file," LINES STARTING BY ");
    pretty_print_char(file, sql_ex.line_start);
  }
     
  if((int)skip_lines > 0)
unknown's avatar
unknown committed
697
    fprintf(file, " IGNORE %ld LINES ", (long) skip_lines);
unknown's avatar
unknown committed
698

699 700 701 702 703 704
  if (num_fields)
  {
    uint i;
    const char* field = fields;
    fprintf( file, " (");
    for(i = 0; i < num_fields; i++)
unknown's avatar
unknown committed
705
    {
706 707 708
      if(i)
	fputc(',', file);
      fprintf(file, field);
unknown's avatar
unknown committed
709
	  
710
      field += field_lens[i]  + 1;
unknown's avatar
unknown committed
711
    }
712 713
    fputc(')', file);
  }
unknown's avatar
unknown committed
714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732

  fprintf(file, ";\n");
}

#ifndef MYSQL_CLIENT

void Load_log_event::set_fields(List<Item> &fields)
{
  uint i;
  const char* field = this->fields;
  for(i = 0; i < num_fields; i++)
    {
      fields.push_back(new Item_field(db, table_name, field));	  
      field += field_lens[i]  + 1;
    }
  
}

#endif