~linuxjedi/drizzle/trunk-bug-667053

« back to all changes in this revision

Viewing changes to sql/sql_class.cc

  • Committer: brian
  • Date: 2008-06-25 05:29:13 UTC
  • Revision ID: brian@localhost.localdomain-20080625052913-6upwo0jsrl4lnapl
clean slate

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 2000-2006 MySQL 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; version 2 of the License.
 
6
 
 
7
   This program is distributed in the hope that it will be useful,
 
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
10
   GNU General Public License for more details.
 
11
 
 
12
   You should have received a copy of the GNU General Public License
 
13
   along with this program; if not, write to the Free Software
 
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
15
 
 
16
 
 
17
/*****************************************************************************
 
18
**
 
19
** This file implements classes defined in sql_class.h
 
20
** Especially the classes to handle a result from a select
 
21
**
 
22
*****************************************************************************/
 
23
 
 
24
#ifdef USE_PRAGMA_IMPLEMENTATION
 
25
#pragma implementation                          // gcc: Class implementation
 
26
#endif
 
27
 
 
28
#include "mysql_priv.h"
 
29
#include "rpl_rli.h"
 
30
#include "rpl_record.h"
 
31
#include "slave.h"
 
32
#include <my_bitmap.h>
 
33
#include "log_event.h"
 
34
#include <m_ctype.h>
 
35
#include <sys/stat.h>
 
36
#include <thr_alarm.h>
 
37
#include <mysys_err.h>
 
38
 
 
39
/*
 
40
  The following is used to initialise Table_ident with a internal
 
41
  table name
 
42
*/
 
43
char internal_table_name[2]= "*";
 
44
char empty_c_string[1]= {0};    /* used for not defined db */
 
45
 
 
46
const char * const THD::DEFAULT_WHERE= "field list";
 
47
 
 
48
 
 
49
/*****************************************************************************
 
50
** Instansiate templates
 
51
*****************************************************************************/
 
52
 
 
53
#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
 
54
/* Used templates */
 
55
template class List<Key>;
 
56
template class List_iterator<Key>;
 
57
template class List<Key_part_spec>;
 
58
template class List_iterator<Key_part_spec>;
 
59
template class List<Alter_drop>;
 
60
template class List_iterator<Alter_drop>;
 
61
template class List<Alter_column>;
 
62
template class List_iterator<Alter_column>;
 
63
#endif
 
64
 
 
65
/****************************************************************************
 
66
** User variables
 
67
****************************************************************************/
 
68
 
 
69
extern "C" uchar *get_var_key(user_var_entry *entry, size_t *length,
 
70
                              my_bool not_used __attribute__((unused)))
 
71
{
 
72
  *length= entry->name.length;
 
73
  return (uchar*) entry->name.str;
 
74
}
 
75
 
 
76
extern "C" void free_user_var(user_var_entry *entry)
 
77
{
 
78
  char *pos= (char*) entry+ALIGN_SIZE(sizeof(*entry));
 
79
  if (entry->value && entry->value != pos)
 
80
    my_free(entry->value, MYF(0));
 
81
  my_free((char*) entry,MYF(0));
 
82
}
 
83
 
 
84
bool Key_part_spec::operator==(const Key_part_spec& other) const
 
85
{
 
86
  return length == other.length &&
 
87
         field_name.length == other.field_name.length &&
 
88
         !strcmp(field_name.str, other.field_name.str);
 
89
}
 
90
 
 
91
/**
 
92
  Construct an (almost) deep copy of this key. Only those
 
93
  elements that are known to never change are not copied.
 
94
  If out of memory, a partial copy is returned and an error is set
 
95
  in THD.
 
96
*/
 
97
 
 
98
Key::Key(const Key &rhs, MEM_ROOT *mem_root)
 
99
  :type(rhs.type),
 
100
  key_create_info(rhs.key_create_info),
 
101
  columns(rhs.columns, mem_root),
 
102
  name(rhs.name),
 
103
  generated(rhs.generated)
 
104
{
 
105
  list_copy_and_replace_each_value(columns, mem_root);
 
106
}
 
107
 
 
108
/**
 
109
  Construct an (almost) deep copy of this foreign key. Only those
 
110
  elements that are known to never change are not copied.
 
111
  If out of memory, a partial copy is returned and an error is set
 
112
  in THD.
 
113
*/
 
114
 
 
115
Foreign_key::Foreign_key(const Foreign_key &rhs, MEM_ROOT *mem_root)
 
116
  :Key(rhs),
 
117
  ref_table(rhs.ref_table),
 
118
  ref_columns(rhs.ref_columns),
 
119
  delete_opt(rhs.delete_opt),
 
120
  update_opt(rhs.update_opt),
 
121
  match_opt(rhs.match_opt)
 
122
{
 
123
  list_copy_and_replace_each_value(ref_columns, mem_root);
 
124
}
 
125
 
 
126
/*
 
127
  Test if a foreign key (= generated key) is a prefix of the given key
 
128
  (ignoring key name, key type and order of columns)
 
129
 
 
130
  NOTES:
 
131
    This is only used to test if an index for a FOREIGN KEY exists
 
132
 
 
133
  IMPLEMENTATION
 
134
    We only compare field names
 
135
 
 
136
  RETURN
 
137
    0   Generated key is a prefix of other key
 
138
    1   Not equal
 
139
*/
 
140
 
 
141
bool foreign_key_prefix(Key *a, Key *b)
 
142
{
 
143
  /* Ensure that 'a' is the generated key */
 
144
  if (a->generated)
 
145
  {
 
146
    if (b->generated && a->columns.elements > b->columns.elements)
 
147
      swap_variables(Key*, a, b);               // Put shorter key in 'a'
 
148
  }
 
149
  else
 
150
  {
 
151
    if (!b->generated)
 
152
      return TRUE;                              // No foreign key
 
153
    swap_variables(Key*, a, b);                 // Put generated key in 'a'
 
154
  }
 
155
 
 
156
  /* Test if 'a' is a prefix of 'b' */
 
157
  if (a->columns.elements > b->columns.elements)
 
158
    return TRUE;                                // Can't be prefix
 
159
 
 
160
  List_iterator<Key_part_spec> col_it1(a->columns);
 
161
  List_iterator<Key_part_spec> col_it2(b->columns);
 
162
  const Key_part_spec *col1, *col2;
 
163
 
 
164
#ifdef ENABLE_WHEN_INNODB_CAN_HANDLE_SWAPED_FOREIGN_KEY_COLUMNS
 
165
  while ((col1= col_it1++))
 
166
  {
 
167
    bool found= 0;
 
168
    col_it2.rewind();
 
169
    while ((col2= col_it2++))
 
170
    {
 
171
      if (*col1 == *col2)
 
172
      {
 
173
        found= TRUE;
 
174
        break;
 
175
      }
 
176
    }
 
177
    if (!found)
 
178
      return TRUE;                              // Error
 
179
  }
 
180
  return FALSE;                                 // Is prefix
 
181
#else
 
182
  while ((col1= col_it1++))
 
183
  {
 
184
    col2= col_it2++;
 
185
    if (!(*col1 == *col2))
 
186
      return TRUE;
 
187
  }
 
188
  return FALSE;                                 // Is prefix
 
189
#endif
 
190
}
 
191
 
 
192
 
 
193
/****************************************************************************
 
194
** Thread specific functions
 
195
****************************************************************************/
 
196
 
 
197
Open_tables_state::Open_tables_state(ulong version_arg)
 
198
  :version(version_arg), state_flags(0U)
 
199
{
 
200
  reset_open_tables_state();
 
201
}
 
202
 
 
203
/*
 
204
  The following functions form part of the C plugin API
 
205
*/
 
206
 
 
207
extern "C" int mysql_tmpfile(const char *prefix)
 
208
{
 
209
  char filename[FN_REFLEN];
 
210
  File fd = create_temp_file(filename, mysql_tmpdir, prefix,
 
211
                             O_CREAT | O_EXCL | O_RDWR | O_TEMPORARY,
 
212
                             MYF(MY_WME));
 
213
  if (fd >= 0) {
 
214
    /*
 
215
      This can be removed once the following bug is fixed:
 
216
      Bug #28903  create_temp_file() doesn't honor O_TEMPORARY option
 
217
                  (file not removed) (Unix)
 
218
    */
 
219
    unlink(filename);
 
220
  }
 
221
 
 
222
  return fd;
 
223
}
 
224
 
 
225
 
 
226
extern "C"
 
227
int thd_in_lock_tables(const THD *thd)
 
228
{
 
229
  return test(thd->in_lock_tables);
 
230
}
 
231
 
 
232
 
 
233
extern "C"
 
234
int thd_tablespace_op(const THD *thd)
 
235
{
 
236
  return test(thd->tablespace_op);
 
237
}
 
238
 
 
239
 
 
240
extern "C"
 
241
const char *set_thd_proc_info(THD *thd, const char *info, 
 
242
                              const char *calling_function, 
 
243
                              const char *calling_file, 
 
244
                              const unsigned int calling_line)
 
245
{
 
246
  const char *old_info= thd->proc_info;
 
247
  DBUG_PRINT("proc_info", ("%s:%d  %s", calling_file, calling_line, 
 
248
                           (info != NULL) ? info : "(null)"));
 
249
  thd->proc_info= info;
 
250
  return old_info;
 
251
}
 
252
 
 
253
extern "C"
 
254
void **thd_ha_data(const THD *thd, const struct handlerton *hton)
 
255
{
 
256
  return (void **) &thd->ha_data[hton->slot].ha_ptr;
 
257
}
 
258
 
 
259
extern "C"
 
260
long long thd_test_options(const THD *thd, long long test_options)
 
261
{
 
262
  return thd->options & test_options;
 
263
}
 
264
 
 
265
extern "C"
 
266
int thd_sql_command(const THD *thd)
 
267
{
 
268
  return (int) thd->lex->sql_command;
 
269
}
 
270
 
 
271
extern "C"
 
272
int thd_tx_isolation(const THD *thd)
 
273
{
 
274
  return (int) thd->variables.tx_isolation;
 
275
}
 
276
 
 
277
extern "C"
 
278
void thd_inc_row_count(THD *thd)
 
279
{
 
280
  thd->row_count++;
 
281
}
 
282
 
 
283
/*
 
284
  Dumps a text description of a thread, its security context
 
285
  (user, host) and the current query.
 
286
 
 
287
  SYNOPSIS
 
288
    thd_security_context()
 
289
    thd                 current thread context
 
290
    buffer              pointer to preferred result buffer
 
291
    length              length of buffer
 
292
    max_query_len       how many chars of query to copy (0 for all)
 
293
 
 
294
  RETURN VALUES
 
295
    pointer to string
 
296
*/
 
297
extern "C"
 
298
char *thd_security_context(THD *thd, char *buffer, unsigned int length,
 
299
                           unsigned int max_query_len)
 
300
{
 
301
  String str(buffer, length, &my_charset_latin1);
 
302
  const Security_context *sctx= &thd->main_security_ctx;
 
303
  char header[64];
 
304
  int len;
 
305
 
 
306
  len= my_snprintf(header, sizeof(header),
 
307
                   "MySQL thread id %lu, query id %lu",
 
308
                   thd->thread_id, (ulong) thd->query_id);
 
309
  str.length(0);
 
310
  str.append(header, len);
 
311
 
 
312
  if (sctx->host)
 
313
  {
 
314
    str.append(' ');
 
315
    str.append(sctx->host);
 
316
  }
 
317
 
 
318
  if (sctx->ip)
 
319
  {
 
320
    str.append(' ');
 
321
    str.append(sctx->ip);
 
322
  }
 
323
 
 
324
  if (sctx->user)
 
325
  {
 
326
    str.append(' ');
 
327
    str.append(sctx->user);
 
328
  }
 
329
 
 
330
  if (thd->proc_info)
 
331
  {
 
332
    str.append(' ');
 
333
    str.append(thd->proc_info);
 
334
  }
 
335
 
 
336
  if (thd->query)
 
337
  {
 
338
    if (max_query_len < 1)
 
339
      len= thd->query_length;
 
340
    else
 
341
      len= min(thd->query_length, max_query_len);
 
342
    str.append('\n');
 
343
    str.append(thd->query, len);
 
344
  }
 
345
  if (str.c_ptr_safe() == buffer)
 
346
    return buffer;
 
347
  return thd->strmake(str.ptr(), str.length());
 
348
}
 
349
 
 
350
/**
 
351
  Clear this diagnostics area. 
 
352
 
 
353
  Normally called at the end of a statement.
 
354
*/
 
355
 
 
356
void
 
357
Diagnostics_area::reset_diagnostics_area()
 
358
{
 
359
#ifdef DBUG_OFF
 
360
  can_overwrite_status= FALSE;
 
361
  /** Don't take chances in production */
 
362
  m_message[0]= '\0';
 
363
  m_sql_errno= 0;
 
364
  m_server_status= 0;
 
365
  m_affected_rows= 0;
 
366
  m_last_insert_id= 0;
 
367
  m_total_warn_count= 0;
 
368
#endif
 
369
  is_sent= FALSE;
 
370
  /** Tiny reset in debug mode to see garbage right away */
 
371
  m_status= DA_EMPTY;
 
372
}
 
373
 
 
374
 
 
375
/**
 
376
  Set OK status -- ends commands that do not return a
 
377
  result set, e.g. INSERT/UPDATE/DELETE.
 
378
*/
 
379
 
 
380
void
 
381
Diagnostics_area::set_ok_status(THD *thd, ha_rows affected_rows_arg,
 
382
                                ulonglong last_insert_id_arg,
 
383
                                const char *message_arg)
 
384
{
 
385
  DBUG_ASSERT(! is_set());
 
386
#ifdef DBUG_OFF
 
387
  /*
 
388
    In production, refuse to overwrite an error or a custom response
 
389
    with an OK packet.
 
390
  */
 
391
  if (is_error() || is_disabled())
 
392
    return;
 
393
#endif
 
394
  /** Only allowed to report success if has not yet reported an error */
 
395
 
 
396
  m_server_status= thd->server_status;
 
397
  m_total_warn_count= thd->total_warn_count;
 
398
  m_affected_rows= affected_rows_arg;
 
399
  m_last_insert_id= last_insert_id_arg;
 
400
  if (message_arg)
 
401
    strmake(m_message, message_arg, sizeof(m_message) - 1);
 
402
  else
 
403
    m_message[0]= '\0';
 
404
  m_status= DA_OK;
 
405
}
 
406
 
 
407
 
 
408
/**
 
409
  Set EOF status.
 
410
*/
 
411
 
 
412
void
 
413
Diagnostics_area::set_eof_status(THD *thd)
 
414
{
 
415
  /** Only allowed to report eof if has not yet reported an error */
 
416
 
 
417
  DBUG_ASSERT(! is_set());
 
418
#ifdef DBUG_OFF
 
419
  /*
 
420
    In production, refuse to overwrite an error or a custom response
 
421
    with an EOF packet.
 
422
  */
 
423
  if (is_error() || is_disabled())
 
424
    return;
 
425
#endif
 
426
 
 
427
  m_server_status= thd->server_status;
 
428
  /*
 
429
    If inside a stored procedure, do not return the total
 
430
    number of warnings, since they are not available to the client
 
431
    anyway.
 
432
  */
 
433
  m_total_warn_count= thd->total_warn_count;
 
434
 
 
435
  m_status= DA_EOF;
 
436
}
 
437
 
 
438
/**
 
439
  Set ERROR status.
 
440
*/
 
441
 
 
442
void
 
443
Diagnostics_area::set_error_status(THD *thd, uint sql_errno_arg,
 
444
                                   const char *message_arg)
 
445
{
 
446
  /*
 
447
    Only allowed to report error if has not yet reported a success
 
448
    The only exception is when we flush the message to the client,
 
449
    an error can happen during the flush.
 
450
  */
 
451
  DBUG_ASSERT(! is_set() || can_overwrite_status);
 
452
#ifdef DBUG_OFF
 
453
  /*
 
454
    In production, refuse to overwrite a custom response with an
 
455
    ERROR packet.
 
456
  */
 
457
  if (is_disabled())
 
458
    return;
 
459
#endif
 
460
 
 
461
  m_sql_errno= sql_errno_arg;
 
462
  strmake(m_message, message_arg, sizeof(m_message) - 1);
 
463
 
 
464
  m_status= DA_ERROR;
 
465
}
 
466
 
 
467
 
 
468
/**
 
469
  Mark the diagnostics area as 'DISABLED'.
 
470
 
 
471
  This is used in rare cases when the COM_ command at hand sends a response
 
472
  in a custom format. One example is the query cache, another is
 
473
  COM_STMT_PREPARE.
 
474
*/
 
475
 
 
476
void
 
477
Diagnostics_area::disable_status()
 
478
{
 
479
  DBUG_ASSERT(! is_set());
 
480
  m_status= DA_DISABLED;
 
481
}
 
482
 
 
483
 
 
484
THD::THD()
 
485
   :Statement(&main_lex, &main_mem_root, CONVENTIONAL_EXECUTION,
 
486
              /* statement id */ 0),
 
487
   Open_tables_state(refresh_version), rli_fake(0),
 
488
   lock_id(&main_lock_id),
 
489
   user_time(0), in_sub_stmt(0),
 
490
   binlog_table_maps(0), binlog_flags(0UL),
 
491
   arg_of_last_insert_id_function(FALSE),
 
492
   first_successful_insert_id_in_prev_stmt(0),
 
493
   first_successful_insert_id_in_prev_stmt_for_binlog(0),
 
494
   first_successful_insert_id_in_cur_stmt(0),
 
495
   stmt_depends_on_first_successful_insert_id_in_prev_stmt(FALSE),
 
496
   global_read_lock(0),
 
497
   is_fatal_error(0),
 
498
   transaction_rollback_request(0),
 
499
   is_fatal_sub_stmt_error(0),
 
500
   rand_used(0),
 
501
   time_zone_used(0),
 
502
   in_lock_tables(0),
 
503
   bootstrap(0),
 
504
   derived_tables_processing(FALSE),
 
505
   m_lip(NULL),
 
506
  /*
 
507
    @todo The following is a work around for online backup and the DDL blocker.
 
508
          It should be removed when the generalized solution is in place.
 
509
          This is needed to ensure the restore (which uses DDL) is not blocked
 
510
          when the DDL blocker is engaged.
 
511
  */
 
512
   DDL_exception(FALSE)
 
513
{
 
514
  ulong tmp;
 
515
 
 
516
  /*
 
517
    Pass nominal parameters to init_alloc_root only to ensure that
 
518
    the destructor works OK in case of an error. The main_mem_root
 
519
    will be re-initialized in init_for_queries().
 
520
  */
 
521
  init_sql_alloc(&main_mem_root, ALLOC_ROOT_MIN_BLOCK_SIZE, 0);
 
522
  stmt_arena= this;
 
523
  thread_stack= 0;
 
524
  catalog= (char*)"std"; // the only catalog we have for now
 
525
  main_security_ctx.init();
 
526
  security_ctx= &main_security_ctx;
 
527
  some_tables_deleted=no_errors=password= 0;
 
528
  query_start_used= 0;
 
529
  count_cuted_fields= CHECK_FIELD_IGNORE;
 
530
  killed= NOT_KILLED;
 
531
  col_access=0;
 
532
  is_slave_error= thread_specific_used= FALSE;
 
533
  hash_clear(&handler_tables_hash);
 
534
  tmp_table=0;
 
535
  used_tables=0;
 
536
  cuted_fields= sent_row_count= row_count= 0L;
 
537
  limit_found_rows= 0;
 
538
  row_count_func= -1;
 
539
  statement_id_counter= 0UL;
 
540
  // Must be reset to handle error with THD's created for init of mysqld
 
541
  lex->current_select= 0;
 
542
  start_time=(time_t) 0;
 
543
  start_utime= 0L;
 
544
  utime_after_lock= 0L;
 
545
  current_linfo =  0;
 
546
  slave_thread = 0;
 
547
  bzero(&variables, sizeof(variables));
 
548
  thread_id= 0;
 
549
  one_shot_set= 0;
 
550
  file_id = 0;
 
551
  query_id= 0;
 
552
  warn_id= 0;
 
553
  db_charset= global_system_variables.collation_database;
 
554
  bzero(ha_data, sizeof(ha_data));
 
555
  mysys_var=0;
 
556
  binlog_evt_union.do_union= FALSE;
 
557
  enable_slow_log= 0;
 
558
#ifndef DBUG_OFF
 
559
  dbug_sentry=THD_SENTRY_MAGIC;
 
560
#endif
 
561
  net.vio=0;
 
562
  client_capabilities= 0;                       // minimalistic client
 
563
  system_thread= NON_SYSTEM_THREAD;
 
564
  cleanup_done= abort_on_warning= no_warnings_for_error= 0;
 
565
  peer_port= 0;                                 // For SHOW PROCESSLIST
 
566
  transaction.m_pending_rows_event= 0;
 
567
  transaction.on= 1;
 
568
#ifdef SIGNAL_WITH_VIO_CLOSE
 
569
  active_vio = 0;
 
570
#endif
 
571
  pthread_mutex_init(&LOCK_delete, MY_MUTEX_INIT_FAST);
 
572
 
 
573
  /* Variables with default values */
 
574
  proc_info="login";
 
575
  where= THD::DEFAULT_WHERE;
 
576
  server_id = ::server_id;
 
577
  slave_net = 0;
 
578
  command=COM_CONNECT;
 
579
  *scramble= '\0';
 
580
 
 
581
  init();
 
582
  /* Initialize sub structures */
 
583
  init_sql_alloc(&warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE);
 
584
  user_connect=(USER_CONN *)0;
 
585
  hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0,
 
586
            (hash_get_key) get_var_key,
 
587
            (hash_free_key) free_user_var, 0);
 
588
 
 
589
  /* For user vars replication*/
 
590
  if (opt_bin_log)
 
591
    my_init_dynamic_array(&user_var_events,
 
592
                          sizeof(BINLOG_USER_VAR_EVENT *), 16, 16);
 
593
  else
 
594
    bzero((char*) &user_var_events, sizeof(user_var_events));
 
595
 
 
596
  /* Protocol */
 
597
  protocol= &protocol_text;                     // Default protocol
 
598
  protocol_text.init(this);
 
599
 
 
600
  tablespace_op=FALSE;
 
601
  tmp= sql_rnd_with_mutex();
 
602
  randominit(&rand, tmp + (ulong) &rand, tmp + (ulong) ::global_query_id);
 
603
  substitute_null_with_insert_id = FALSE;
 
604
  thr_lock_info_init(&lock_info); /* safety: will be reset after start */
 
605
  thr_lock_owner_init(&main_lock_id, &lock_info);
 
606
 
 
607
  m_internal_handler= NULL;
 
608
}
 
609
 
 
610
 
 
611
void THD::push_internal_handler(Internal_error_handler *handler)
 
612
{
 
613
  /*
 
614
    TODO: The current implementation is limited to 1 handler at a time only.
 
615
    THD and sp_rcontext need to be modified to use a common handler stack.
 
616
  */
 
617
  DBUG_ASSERT(m_internal_handler == NULL);
 
618
  m_internal_handler= handler;
 
619
}
 
620
 
 
621
 
 
622
bool THD::handle_error(uint sql_errno, const char *message,
 
623
                       MYSQL_ERROR::enum_warning_level level)
 
624
{
 
625
  if (m_internal_handler)
 
626
  {
 
627
    return m_internal_handler->handle_error(sql_errno, message, level, this);
 
628
  }
 
629
 
 
630
  return FALSE;                                 // 'FALSE', as per coding style
 
631
}
 
632
 
 
633
 
 
634
void THD::pop_internal_handler()
 
635
{
 
636
  DBUG_ASSERT(m_internal_handler != NULL);
 
637
  m_internal_handler= NULL;
 
638
}
 
639
 
 
640
extern "C"
 
641
void *thd_alloc(MYSQL_THD thd, unsigned int size)
 
642
{
 
643
  return thd->alloc(size);
 
644
}
 
645
 
 
646
extern "C"
 
647
void *thd_calloc(MYSQL_THD thd, unsigned int size)
 
648
{
 
649
  return thd->calloc(size);
 
650
}
 
651
 
 
652
extern "C"
 
653
char *thd_strdup(MYSQL_THD thd, const char *str)
 
654
{
 
655
  return thd->strdup(str);
 
656
}
 
657
 
 
658
extern "C"
 
659
char *thd_strmake(MYSQL_THD thd, const char *str, unsigned int size)
 
660
{
 
661
  return thd->strmake(str, size);
 
662
}
 
663
 
 
664
extern "C"
 
665
LEX_STRING *thd_make_lex_string(THD *thd, LEX_STRING *lex_str,
 
666
                                const char *str, unsigned int size,
 
667
                                int allocate_lex_string)
 
668
{
 
669
  return thd->make_lex_string(lex_str, str, size,
 
670
                              (bool) allocate_lex_string);
 
671
}
 
672
 
 
673
extern "C"
 
674
void *thd_memdup(MYSQL_THD thd, const void* str, unsigned int size)
 
675
{
 
676
  return thd->memdup(str, size);
 
677
}
 
678
 
 
679
extern "C"
 
680
void thd_get_xid(const MYSQL_THD thd, MYSQL_XID *xid)
 
681
{
 
682
  *xid = *(MYSQL_XID *) &thd->transaction.xid_state.xid;
 
683
}
 
684
 
 
685
/*
 
686
  Init common variables that has to be reset on start and on change_user
 
687
*/
 
688
 
 
689
void THD::init(void)
 
690
{
 
691
  pthread_mutex_lock(&LOCK_global_system_variables);
 
692
  plugin_thdvar_init(this);
 
693
  variables.time_format= date_time_format_copy((THD*) 0,
 
694
                                               variables.time_format);
 
695
  variables.date_format= date_time_format_copy((THD*) 0,
 
696
                                               variables.date_format);
 
697
  variables.datetime_format= date_time_format_copy((THD*) 0,
 
698
                                                   variables.datetime_format);
 
699
  /*
 
700
    variables= global_system_variables above has reset
 
701
    variables.pseudo_thread_id to 0. We need to correct it here to
 
702
    avoid temporary tables replication failure.
 
703
  */
 
704
  variables.pseudo_thread_id= thread_id;
 
705
  pthread_mutex_unlock(&LOCK_global_system_variables);
 
706
  server_status= SERVER_STATUS_AUTOCOMMIT;
 
707
  options= thd_startup_options;
 
708
 
 
709
  if (variables.max_join_size == HA_POS_ERROR)
 
710
    options |= OPTION_BIG_SELECTS;
 
711
  else
 
712
    options &= ~OPTION_BIG_SELECTS;
 
713
 
 
714
  transaction.all.modified_non_trans_table= transaction.stmt.modified_non_trans_table= FALSE;
 
715
  open_options=ha_open_options;
 
716
  update_lock_default= (variables.low_priority_updates ?
 
717
                        TL_WRITE_LOW_PRIORITY :
 
718
                        TL_WRITE);
 
719
  session_tx_isolation= (enum_tx_isolation) variables.tx_isolation;
 
720
  warn_list.empty();
 
721
  bzero((char*) warn_count, sizeof(warn_count));
 
722
  total_warn_count= 0;
 
723
  update_charset();
 
724
  reset_current_stmt_binlog_row_based();
 
725
  bzero((char *) &status_var, sizeof(status_var));
 
726
}
 
727
 
 
728
 
 
729
/*
 
730
  Init THD for query processing.
 
731
  This has to be called once before we call mysql_parse.
 
732
  See also comments in sql_class.h.
 
733
*/
 
734
 
 
735
void THD::init_for_queries()
 
736
{
 
737
  set_time(); 
 
738
  ha_enable_transaction(this,TRUE);
 
739
 
 
740
  reset_root_defaults(mem_root, variables.query_alloc_block_size,
 
741
                      variables.query_prealloc_size);
 
742
  reset_root_defaults(&transaction.mem_root,
 
743
                      variables.trans_alloc_block_size,
 
744
                      variables.trans_prealloc_size);
 
745
  transaction.xid_state.xid.null();
 
746
  transaction.xid_state.in_thd=1;
 
747
}
 
748
 
 
749
 
 
750
/* Do operations that may take a long time */
 
751
 
 
752
void THD::cleanup(void)
 
753
{
 
754
  DBUG_ENTER("THD::cleanup");
 
755
  DBUG_ASSERT(cleanup_done == 0);
 
756
 
 
757
  killed= KILL_CONNECTION;
 
758
#ifdef ENABLE_WHEN_BINLOG_WILL_BE_ABLE_TO_PREPARE
 
759
  if (transaction.xid_state.xa_state == XA_PREPARED)
 
760
  {
 
761
#error xid_state in the cache should be replaced by the allocated value
 
762
  }
 
763
#endif
 
764
  {
 
765
    ha_rollback(this);
 
766
    xid_cache_delete(&transaction.xid_state);
 
767
  }
 
768
  if (locked_tables)
 
769
  {
 
770
    lock=locked_tables; locked_tables=0;
 
771
    close_thread_tables(this);
 
772
  }
 
773
  mysql_ha_cleanup(this);
 
774
  delete_dynamic(&user_var_events);
 
775
  hash_free(&user_vars);
 
776
  close_temporary_tables(this);
 
777
  my_free((char*) variables.time_format, MYF(MY_ALLOW_ZERO_PTR));
 
778
  my_free((char*) variables.date_format, MYF(MY_ALLOW_ZERO_PTR));
 
779
  my_free((char*) variables.datetime_format, MYF(MY_ALLOW_ZERO_PTR));
 
780
  
 
781
  if (global_read_lock)
 
782
    unlock_global_read_lock(this);
 
783
 
 
784
  cleanup_done=1;
 
785
  DBUG_VOID_RETURN;
 
786
}
 
787
 
 
788
 
 
789
/*
 
790
   Set the proc_info field.
 
791
   Do not use this method directly, use THD_SET_PROC_INFO instead.
 
792
 */
 
793
#ifndef DBUG_OFF
 
794
void THD::set_proc_info(const char* file, int line, const char* info)
 
795
{
 
796
  /*
 
797
     Implementation note:
 
798
     file and line correspond to the __FILE__ and __LINE__ where
 
799
     THD_SET_PROC_INFO was called.
 
800
     These two parameters are provided to help instrumenting the code.
 
801
   */
 
802
 
 
803
  DBUG_PRINT("info", ("THD::set_proc_info(%s, %d, %s)",
 
804
                      file, line, (info ? info : NullS)));
 
805
 
 
806
  proc_info= info;
 
807
}
 
808
#endif
 
809
 
 
810
 
 
811
THD::~THD()
 
812
{
 
813
  THD_CHECK_SENTRY(this);
 
814
  DBUG_ENTER("~THD()");
 
815
  /* Ensure that no one is using THD */
 
816
  pthread_mutex_lock(&LOCK_delete);
 
817
  pthread_mutex_unlock(&LOCK_delete);
 
818
  add_to_status(&global_status_var, &status_var);
 
819
 
 
820
  /* Close connection */
 
821
  if (net.vio)
 
822
  {
 
823
    vio_delete(net.vio);
 
824
    net_end(&net);
 
825
  }
 
826
  if (!cleanup_done)
 
827
    cleanup();
 
828
 
 
829
  ha_close_connection(this);
 
830
  plugin_thdvar_cleanup(this);
 
831
 
 
832
  DBUG_PRINT("info", ("freeing security context"));
 
833
  main_security_ctx.destroy();
 
834
  safeFree(db);
 
835
  free_root(&warn_root,MYF(0));
 
836
  free_root(&transaction.mem_root,MYF(0));
 
837
  mysys_var=0;                                  // Safety (shouldn't be needed)
 
838
  pthread_mutex_destroy(&LOCK_delete);
 
839
#ifndef DBUG_OFF
 
840
  dbug_sentry= THD_SENTRY_GONE;
 
841
#endif  
 
842
  if (rli_fake)
 
843
  {
 
844
    delete rli_fake;
 
845
    rli_fake= NULL;
 
846
  }
 
847
  
 
848
  free_root(&main_mem_root, MYF(0));
 
849
  DBUG_VOID_RETURN;
 
850
}
 
851
 
 
852
 
 
853
/*
 
854
  Add all status variables to another status variable array
 
855
 
 
856
  SYNOPSIS
 
857
   add_to_status()
 
858
   to_var       add to this array
 
859
   from_var     from this array
 
860
 
 
861
  NOTES
 
862
    This function assumes that all variables are long/ulong.
 
863
    If this assumption will change, then we have to explictely add
 
864
    the other variables after the while loop
 
865
*/
 
866
 
 
867
void add_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var)
 
868
{
 
869
  ulong *end= (ulong*) ((uchar*) to_var +
 
870
                        offsetof(STATUS_VAR, last_system_status_var) +
 
871
                        sizeof(ulong));
 
872
  ulong *to= (ulong*) to_var, *from= (ulong*) from_var;
 
873
 
 
874
  while (to != end)
 
875
    *(to++)+= *(from++);
 
876
}
 
877
 
 
878
/*
 
879
  Add the difference between two status variable arrays to another one.
 
880
 
 
881
  SYNOPSIS
 
882
    add_diff_to_status
 
883
    to_var       add to this array
 
884
    from_var     from this array
 
885
    dec_var      minus this array
 
886
  
 
887
  NOTE
 
888
    This function assumes that all variables are long/ulong.
 
889
*/
 
890
 
 
891
void add_diff_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var,
 
892
                        STATUS_VAR *dec_var)
 
893
{
 
894
  ulong *end= (ulong*) ((uchar*) to_var + offsetof(STATUS_VAR,
 
895
                                                  last_system_status_var) +
 
896
                        sizeof(ulong));
 
897
  ulong *to= (ulong*) to_var, *from= (ulong*) from_var, *dec= (ulong*) dec_var;
 
898
 
 
899
  while (to != end)
 
900
    *(to++)+= *(from++) - *(dec++);
 
901
}
 
902
 
 
903
 
 
904
void THD::awake(THD::killed_state state_to_set)
 
905
{
 
906
  DBUG_ENTER("THD::awake");
 
907
  DBUG_PRINT("enter", ("this: 0x%lx", (long) this));
 
908
  THD_CHECK_SENTRY(this);
 
909
  safe_mutex_assert_owner(&LOCK_delete); 
 
910
 
 
911
  killed= state_to_set;
 
912
  if (state_to_set != THD::KILL_QUERY)
 
913
  {
 
914
    thr_alarm_kill(thread_id);
 
915
    if (!slave_thread)
 
916
      thread_scheduler.post_kill_notification(this);
 
917
#ifdef SIGNAL_WITH_VIO_CLOSE
 
918
    if (this != current_thd)
 
919
    {
 
920
      /*
 
921
        In addition to a signal, let's close the socket of the thread that
 
922
        is being killed. This is to make sure it does not block if the
 
923
        signal is lost. This needs to be done only on platforms where
 
924
        signals are not a reliable interruption mechanism.
 
925
 
 
926
        If we're killing ourselves, we know that we're not blocked, so this
 
927
        hack is not used.
 
928
      */
 
929
 
 
930
      close_active_vio();
 
931
    }
 
932
#endif    
 
933
  }
 
934
  if (mysys_var)
 
935
  {
 
936
    pthread_mutex_lock(&mysys_var->mutex);
 
937
    if (!system_thread)         // Don't abort locks
 
938
      mysys_var->abort=1;
 
939
    /*
 
940
      This broadcast could be up in the air if the victim thread
 
941
      exits the cond in the time between read and broadcast, but that is
 
942
      ok since all we want to do is to make the victim thread get out
 
943
      of waiting on current_cond.
 
944
      If we see a non-zero current_cond: it cannot be an old value (because
 
945
      then exit_cond() should have run and it can't because we have mutex); so
 
946
      it is the true value but maybe current_mutex is not yet non-zero (we're
 
947
      in the middle of enter_cond() and there is a "memory order
 
948
      inversion"). So we test the mutex too to not lock 0.
 
949
 
 
950
      Note that there is a small chance we fail to kill. If victim has locked
 
951
      current_mutex, but hasn't yet entered enter_cond() (which means that
 
952
      current_cond and current_mutex are 0), then the victim will not get
 
953
      a signal and it may wait "forever" on the cond (until
 
954
      we issue a second KILL or the status it's waiting for happens).
 
955
      It's true that we have set its thd->killed but it may not
 
956
      see it immediately and so may have time to reach the cond_wait().
 
957
    */
 
958
    if (mysys_var->current_cond && mysys_var->current_mutex)
 
959
    {
 
960
      pthread_mutex_lock(mysys_var->current_mutex);
 
961
      pthread_cond_broadcast(mysys_var->current_cond);
 
962
      pthread_mutex_unlock(mysys_var->current_mutex);
 
963
    }
 
964
    pthread_mutex_unlock(&mysys_var->mutex);
 
965
  }
 
966
  DBUG_VOID_RETURN;
 
967
}
 
968
 
 
969
/*
 
970
  Remember the location of thread info, the structure needed for
 
971
  sql_alloc() and the structure for the net buffer
 
972
*/
 
973
 
 
974
bool THD::store_globals()
 
975
{
 
976
  /*
 
977
    Assert that thread_stack is initialized: it's necessary to be able
 
978
    to track stack overrun.
 
979
  */
 
980
  DBUG_ASSERT(thread_stack);
 
981
 
 
982
  if (my_pthread_setspecific_ptr(THR_THD,  this) ||
 
983
      my_pthread_setspecific_ptr(THR_MALLOC, &mem_root))
 
984
    return 1;
 
985
  mysys_var=my_thread_var;
 
986
  /*
 
987
    Let mysqld define the thread id (not mysys)
 
988
    This allows us to move THD to different threads if needed.
 
989
  */
 
990
  mysys_var->id= thread_id;
 
991
  real_id= pthread_self();                      // For debugging
 
992
 
 
993
  /*
 
994
    We have to call thr_lock_info_init() again here as THD may have been
 
995
    created in another thread
 
996
  */
 
997
  thr_lock_info_init(&lock_info);
 
998
  return 0;
 
999
}
 
1000
 
 
1001
 
 
1002
/*
 
1003
  Cleanup after query.
 
1004
 
 
1005
  SYNOPSIS
 
1006
    THD::cleanup_after_query()
 
1007
 
 
1008
  DESCRIPTION
 
1009
    This function is used to reset thread data to its default state.
 
1010
 
 
1011
  NOTE
 
1012
    This function is not suitable for setting thread data to some
 
1013
    non-default values, as there is only one replication thread, so
 
1014
    different master threads may overwrite data of each other on
 
1015
    slave.
 
1016
*/
 
1017
 
 
1018
void THD::cleanup_after_query()
 
1019
{
 
1020
  /*
 
1021
    Reset rand_used so that detection of calls to rand() will save random 
 
1022
    seeds if needed by the slave.
 
1023
 
 
1024
    Do not reset rand_used if inside a stored function or trigger because 
 
1025
    only the call to these operations is logged. Thus only the calling 
 
1026
    statement needs to detect rand() calls made by its substatements. These
 
1027
    substatements must not set rand_used to 0 because it would remove the
 
1028
    detection of rand() by the calling statement. 
 
1029
  */
 
1030
  if (!in_sub_stmt) /* stored functions and triggers are a special case */
 
1031
  {
 
1032
    /* Forget those values, for next binlogger: */
 
1033
    stmt_depends_on_first_successful_insert_id_in_prev_stmt= 0;
 
1034
    auto_inc_intervals_in_cur_stmt_for_binlog.empty();
 
1035
    rand_used= 0;
 
1036
  }
 
1037
  if (first_successful_insert_id_in_cur_stmt > 0)
 
1038
  {
 
1039
    /* set what LAST_INSERT_ID() will return */
 
1040
    first_successful_insert_id_in_prev_stmt= 
 
1041
      first_successful_insert_id_in_cur_stmt;
 
1042
    first_successful_insert_id_in_cur_stmt= 0;
 
1043
    substitute_null_with_insert_id= TRUE;
 
1044
  }
 
1045
  arg_of_last_insert_id_function= 0;
 
1046
  /* Free Items that were created during this execution */
 
1047
  free_items();
 
1048
  /* Reset where. */
 
1049
  where= THD::DEFAULT_WHERE;
 
1050
}
 
1051
 
 
1052
 
 
1053
/**
 
1054
  Create a LEX_STRING in this connection.
 
1055
 
 
1056
  @param lex_str  pointer to LEX_STRING object to be initialized
 
1057
  @param str      initializer to be copied into lex_str
 
1058
  @param length   length of str, in bytes
 
1059
  @param allocate_lex_string  if TRUE, allocate new LEX_STRING object,
 
1060
                              instead of using lex_str value
 
1061
  @return  NULL on failure, or pointer to the LEX_STRING object
 
1062
*/
 
1063
LEX_STRING *THD::make_lex_string(LEX_STRING *lex_str,
 
1064
                                 const char* str, uint length,
 
1065
                                 bool allocate_lex_string)
 
1066
{
 
1067
  if (allocate_lex_string)
 
1068
    if (!(lex_str= (LEX_STRING *)alloc(sizeof(LEX_STRING))))
 
1069
      return 0;
 
1070
  if (!(lex_str->str= strmake_root(mem_root, str, length)))
 
1071
    return 0;
 
1072
  lex_str->length= length;
 
1073
  return lex_str;
 
1074
}
 
1075
 
 
1076
 
 
1077
/*
 
1078
  Convert a string to another character set
 
1079
 
 
1080
  SYNOPSIS
 
1081
    convert_string()
 
1082
    to                          Store new allocated string here
 
1083
    to_cs                       New character set for allocated string
 
1084
    from                        String to convert
 
1085
    from_length                 Length of string to convert
 
1086
    from_cs                     Original character set
 
1087
 
 
1088
  NOTES
 
1089
    to will be 0-terminated to make it easy to pass to system funcs
 
1090
 
 
1091
  RETURN
 
1092
    0   ok
 
1093
    1   End of memory.
 
1094
        In this case to->str will point to 0 and to->length will be 0.
 
1095
*/
 
1096
 
 
1097
bool THD::convert_string(LEX_STRING *to, CHARSET_INFO *to_cs,
 
1098
                         const char *from, uint from_length,
 
1099
                         CHARSET_INFO *from_cs)
 
1100
{
 
1101
  DBUG_ENTER("convert_string");
 
1102
  size_t new_length= to_cs->mbmaxlen * from_length;
 
1103
  uint dummy_errors;
 
1104
  if (!(to->str= (char*) alloc(new_length+1)))
 
1105
  {
 
1106
    to->length= 0;                              // Safety fix
 
1107
    DBUG_RETURN(1);                             // EOM
 
1108
  }
 
1109
  to->length= copy_and_convert((char*) to->str, new_length, to_cs,
 
1110
                               from, from_length, from_cs, &dummy_errors);
 
1111
  to->str[to->length]=0;                        // Safety
 
1112
  DBUG_RETURN(0);
 
1113
}
 
1114
 
 
1115
 
 
1116
/*
 
1117
  Convert string from source character set to target character set inplace.
 
1118
 
 
1119
  SYNOPSIS
 
1120
    THD::convert_string
 
1121
 
 
1122
  DESCRIPTION
 
1123
    Convert string using convert_buffer - buffer for character set 
 
1124
    conversion shared between all protocols.
 
1125
 
 
1126
  RETURN
 
1127
    0   ok
 
1128
   !0   out of memory
 
1129
*/
 
1130
 
 
1131
bool THD::convert_string(String *s, CHARSET_INFO *from_cs, CHARSET_INFO *to_cs)
 
1132
{
 
1133
  uint dummy_errors;
 
1134
  if (convert_buffer.copy(s->ptr(), s->length(), from_cs, to_cs, &dummy_errors))
 
1135
    return TRUE;
 
1136
  /* If convert_buffer >> s copying is more efficient long term */
 
1137
  if (convert_buffer.alloced_length() >= convert_buffer.length() * 2 ||
 
1138
      !s->is_alloced())
 
1139
  {
 
1140
    return s->copy(convert_buffer);
 
1141
  }
 
1142
  s->swap(convert_buffer);
 
1143
  return FALSE;
 
1144
}
 
1145
 
 
1146
 
 
1147
/*
 
1148
  Update some cache variables when character set changes
 
1149
*/
 
1150
 
 
1151
void THD::update_charset()
 
1152
{
 
1153
  uint32 not_used;
 
1154
  charset_is_system_charset= !String::needs_conversion(0,charset(),
 
1155
                                                       system_charset_info,
 
1156
                                                       &not_used);
 
1157
  charset_is_collation_connection= 
 
1158
    !String::needs_conversion(0,charset(),variables.collation_connection,
 
1159
                              &not_used);
 
1160
  charset_is_character_set_filesystem= 
 
1161
    !String::needs_conversion(0, charset(),
 
1162
                              variables.character_set_filesystem, &not_used);
 
1163
}
 
1164
 
 
1165
 
 
1166
/* routings to adding tables to list of changed in transaction tables */
 
1167
 
 
1168
inline static void list_include(CHANGED_TABLE_LIST** prev,
 
1169
                                CHANGED_TABLE_LIST* curr,
 
1170
                                CHANGED_TABLE_LIST* new_table)
 
1171
{
 
1172
  if (new_table)
 
1173
  {
 
1174
    *prev = new_table;
 
1175
    (*prev)->next = curr;
 
1176
  }
 
1177
}
 
1178
 
 
1179
/* add table to list of changed in transaction tables */
 
1180
 
 
1181
void THD::add_changed_table(TABLE *table)
 
1182
{
 
1183
  DBUG_ENTER("THD::add_changed_table(table)");
 
1184
 
 
1185
  DBUG_ASSERT((options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) &&
 
1186
              table->file->has_transactions());
 
1187
  add_changed_table(table->s->table_cache_key.str,
 
1188
                    (long) table->s->table_cache_key.length);
 
1189
  DBUG_VOID_RETURN;
 
1190
}
 
1191
 
 
1192
 
 
1193
void THD::add_changed_table(const char *key, long key_length)
 
1194
{
 
1195
  DBUG_ENTER("THD::add_changed_table(key)");
 
1196
  CHANGED_TABLE_LIST **prev_changed = &transaction.changed_tables;
 
1197
  CHANGED_TABLE_LIST *curr = transaction.changed_tables;
 
1198
 
 
1199
  for (; curr; prev_changed = &(curr->next), curr = curr->next)
 
1200
  {
 
1201
    int cmp =  (long)curr->key_length - (long)key_length;
 
1202
    if (cmp < 0)
 
1203
    {
 
1204
      list_include(prev_changed, curr, changed_table_dup(key, key_length));
 
1205
      DBUG_PRINT("info", 
 
1206
                 ("key_length: %ld  %u", key_length,
 
1207
                  (*prev_changed)->key_length));
 
1208
      DBUG_VOID_RETURN;
 
1209
    }
 
1210
    else if (cmp == 0)
 
1211
    {
 
1212
      cmp = memcmp(curr->key, key, curr->key_length);
 
1213
      if (cmp < 0)
 
1214
      {
 
1215
        list_include(prev_changed, curr, changed_table_dup(key, key_length));
 
1216
        DBUG_PRINT("info", 
 
1217
                   ("key_length:  %ld  %u", key_length,
 
1218
                    (*prev_changed)->key_length));
 
1219
        DBUG_VOID_RETURN;
 
1220
      }
 
1221
      else if (cmp == 0)
 
1222
      {
 
1223
        DBUG_PRINT("info", ("already in list"));
 
1224
        DBUG_VOID_RETURN;
 
1225
      }
 
1226
    }
 
1227
  }
 
1228
  *prev_changed = changed_table_dup(key, key_length);
 
1229
  DBUG_PRINT("info", ("key_length: %ld  %u", key_length,
 
1230
                      (*prev_changed)->key_length));
 
1231
  DBUG_VOID_RETURN;
 
1232
}
 
1233
 
 
1234
 
 
1235
CHANGED_TABLE_LIST* THD::changed_table_dup(const char *key, long key_length)
 
1236
{
 
1237
  CHANGED_TABLE_LIST* new_table = 
 
1238
    (CHANGED_TABLE_LIST*) trans_alloc(ALIGN_SIZE(sizeof(CHANGED_TABLE_LIST))+
 
1239
                                      key_length + 1);
 
1240
  if (!new_table)
 
1241
  {
 
1242
    my_error(EE_OUTOFMEMORY, MYF(ME_BELL),
 
1243
             ALIGN_SIZE(sizeof(TABLE_LIST)) + key_length + 1);
 
1244
    killed= KILL_CONNECTION;
 
1245
    return 0;
 
1246
  }
 
1247
 
 
1248
  new_table->key= ((char*)new_table)+ ALIGN_SIZE(sizeof(CHANGED_TABLE_LIST));
 
1249
  new_table->next = 0;
 
1250
  new_table->key_length = key_length;
 
1251
  ::memcpy(new_table->key, key, key_length);
 
1252
  return new_table;
 
1253
}
 
1254
 
 
1255
 
 
1256
int THD::send_explain_fields(select_result *result)
 
1257
{
 
1258
  List<Item> field_list;
 
1259
  Item *item;
 
1260
  CHARSET_INFO *cs= system_charset_info;
 
1261
  field_list.push_back(new Item_return_int("id",3, MYSQL_TYPE_LONGLONG));
 
1262
  field_list.push_back(new Item_empty_string("select_type", 19, cs));
 
1263
  field_list.push_back(item= new Item_empty_string("table", NAME_CHAR_LEN, cs));
 
1264
  item->maybe_null= 1;
 
1265
  field_list.push_back(item= new Item_empty_string("type", 10, cs));
 
1266
  item->maybe_null= 1;
 
1267
  field_list.push_back(item=new Item_empty_string("possible_keys",
 
1268
                                                  NAME_CHAR_LEN*MAX_KEY, cs));
 
1269
  item->maybe_null=1;
 
1270
  field_list.push_back(item=new Item_empty_string("key", NAME_CHAR_LEN, cs));
 
1271
  item->maybe_null=1;
 
1272
  field_list.push_back(item=
 
1273
    new Item_empty_string("key_len",
 
1274
                          MAX_KEY *
 
1275
                          (MAX_KEY_LENGTH_DECIMAL_WIDTH + 1 /* for comma */),
 
1276
                          cs));
 
1277
  item->maybe_null=1;
 
1278
  field_list.push_back(item=new Item_empty_string("ref",
 
1279
                                                  NAME_CHAR_LEN*MAX_REF_PARTS,
 
1280
                                                  cs));
 
1281
  item->maybe_null=1;
 
1282
  field_list.push_back(item= new Item_return_int("rows", 10,
 
1283
                                                 MYSQL_TYPE_LONGLONG));
 
1284
  if (lex->describe & DESCRIBE_EXTENDED)
 
1285
  {
 
1286
    field_list.push_back(item= new Item_float("filtered", 0.1234, 2, 4));
 
1287
    item->maybe_null=1;
 
1288
  }
 
1289
  item->maybe_null= 1;
 
1290
  field_list.push_back(new Item_empty_string("Extra", 255, cs));
 
1291
  return (result->send_fields(field_list,
 
1292
                              Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF));
 
1293
}
 
1294
 
 
1295
#ifdef SIGNAL_WITH_VIO_CLOSE
 
1296
void THD::close_active_vio()
 
1297
{
 
1298
  DBUG_ENTER("close_active_vio");
 
1299
  safe_mutex_assert_owner(&LOCK_delete); 
 
1300
  if (active_vio)
 
1301
  {
 
1302
    vio_close(active_vio);
 
1303
    active_vio = 0;
 
1304
  }
 
1305
  DBUG_VOID_RETURN;
 
1306
}
 
1307
#endif
 
1308
 
 
1309
 
 
1310
struct Item_change_record: public ilink
 
1311
{
 
1312
  Item **place;
 
1313
  Item *old_value;
 
1314
  /* Placement new was hidden by `new' in ilink (TODO: check): */
 
1315
  static void *operator new(size_t size, void *mem) { return mem; }
 
1316
  static void operator delete(void *ptr, size_t size) {}
 
1317
  static void operator delete(void *ptr, void *mem) { /* never called */ }
 
1318
};
 
1319
 
 
1320
 
 
1321
/*
 
1322
  Register an item tree tree transformation, performed by the query
 
1323
  optimizer. We need a pointer to runtime_memroot because it may be !=
 
1324
  thd->mem_root (due to possible set_n_backup_active_arena called for thd).
 
1325
*/
 
1326
 
 
1327
void THD::nocheck_register_item_tree_change(Item **place, Item *old_value,
 
1328
                                            MEM_ROOT *runtime_memroot)
 
1329
{
 
1330
  Item_change_record *change;
 
1331
  /*
 
1332
    Now we use one node per change, which adds some memory overhead,
 
1333
    but still is rather fast as we use alloc_root for allocations.
 
1334
    A list of item tree changes of an average query should be short.
 
1335
  */
 
1336
  void *change_mem= alloc_root(runtime_memroot, sizeof(*change));
 
1337
  if (change_mem == 0)
 
1338
  {
 
1339
    /*
 
1340
      OOM, thd->fatal_error() is called by the error handler of the
 
1341
      memroot. Just return.
 
1342
    */
 
1343
    return;
 
1344
  }
 
1345
  change= new (change_mem) Item_change_record;
 
1346
  change->place= place;
 
1347
  change->old_value= old_value;
 
1348
  change_list.append(change);
 
1349
}
 
1350
 
 
1351
 
 
1352
void THD::rollback_item_tree_changes()
 
1353
{
 
1354
  I_List_iterator<Item_change_record> it(change_list);
 
1355
  Item_change_record *change;
 
1356
  DBUG_ENTER("rollback_item_tree_changes");
 
1357
 
 
1358
  while ((change= it++))
 
1359
    *change->place= change->old_value;
 
1360
  /* We can forget about changes memory: it's allocated in runtime memroot */
 
1361
  change_list.empty();
 
1362
  DBUG_VOID_RETURN;
 
1363
}
 
1364
 
 
1365
 
 
1366
/**
 
1367
  Check that the endpoint is still available.
 
1368
*/
 
1369
 
 
1370
bool THD::vio_is_connected()
 
1371
{
 
1372
  uint bytes= 0;
 
1373
 
 
1374
  /* End of input is signaled by poll if the socket is aborted. */
 
1375
  if (vio_poll_read(net.vio, 0))
 
1376
    return TRUE;
 
1377
 
 
1378
  /* Socket is aborted if signaled but no data is available. */
 
1379
  if (vio_peek_read(net.vio, &bytes))
 
1380
    return TRUE;
 
1381
 
 
1382
  return bytes ? TRUE : FALSE;
 
1383
}
 
1384
 
 
1385
 
 
1386
/*****************************************************************************
 
1387
** Functions to provide a interface to select results
 
1388
*****************************************************************************/
 
1389
 
 
1390
select_result::select_result()
 
1391
{
 
1392
  thd=current_thd;
 
1393
}
 
1394
 
 
1395
void select_result::send_error(uint errcode,const char *err)
 
1396
{
 
1397
  my_message(errcode, err, MYF(0));
 
1398
}
 
1399
 
 
1400
 
 
1401
void select_result::cleanup()
 
1402
{
 
1403
  /* do nothing */
 
1404
}
 
1405
 
 
1406
bool select_result::check_simple_select() const
 
1407
{
 
1408
  my_error(ER_SP_BAD_CURSOR_QUERY, MYF(0));
 
1409
  return TRUE;
 
1410
}
 
1411
 
 
1412
 
 
1413
static String default_line_term("\n",default_charset_info);
 
1414
static String default_escaped("\\",default_charset_info);
 
1415
static String default_field_term("\t",default_charset_info);
 
1416
static String default_xml_row_term("<row>", default_charset_info);
 
1417
 
 
1418
sql_exchange::sql_exchange(char *name, bool flag,
 
1419
                           enum enum_filetype filetype_arg)
 
1420
  :file_name(name), opt_enclosed(0), dumpfile(flag), skip_lines(0)
 
1421
{
 
1422
  filetype= filetype_arg;
 
1423
  field_term= &default_field_term;
 
1424
  enclosed=   line_start= &my_empty_string;
 
1425
  line_term=  filetype == FILETYPE_CSV ?
 
1426
              &default_line_term : &default_xml_row_term;
 
1427
  escaped=    &default_escaped;
 
1428
  cs= NULL;
 
1429
}
 
1430
 
 
1431
bool select_send::send_fields(List<Item> &list, uint flags)
 
1432
{
 
1433
  bool res;
 
1434
  if (!(res= thd->protocol->send_fields(&list, flags)))
 
1435
    is_result_set_started= 1;
 
1436
  return res;
 
1437
}
 
1438
 
 
1439
void select_send::abort()
 
1440
{
 
1441
  DBUG_ENTER("select_send::abort");
 
1442
  DBUG_VOID_RETURN;
 
1443
}
 
1444
 
 
1445
 
 
1446
/** 
 
1447
  Cleanup an instance of this class for re-use
 
1448
  at next execution of a prepared statement/
 
1449
  stored procedure statement.
 
1450
*/
 
1451
 
 
1452
void select_send::cleanup()
 
1453
{
 
1454
  is_result_set_started= FALSE;
 
1455
}
 
1456
 
 
1457
/* Send data to client. Returns 0 if ok */
 
1458
 
 
1459
bool select_send::send_data(List<Item> &items)
 
1460
{
 
1461
  if (unit->offset_limit_cnt)
 
1462
  {                                             // using limit offset,count
 
1463
    unit->offset_limit_cnt--;
 
1464
    return 0;
 
1465
  }
 
1466
 
 
1467
  /*
 
1468
    We may be passing the control from mysqld to the client: release the
 
1469
    InnoDB adaptive hash S-latch to avoid thread deadlocks if it was reserved
 
1470
    by thd
 
1471
  */
 
1472
  ha_release_temporary_latches(thd);
 
1473
 
 
1474
  List_iterator_fast<Item> li(items);
 
1475
  Protocol *protocol= thd->protocol;
 
1476
  char buff[MAX_FIELD_WIDTH];
 
1477
  String buffer(buff, sizeof(buff), &my_charset_bin);
 
1478
  DBUG_ENTER("select_send::send_data");
 
1479
 
 
1480
  protocol->prepare_for_resend();
 
1481
  Item *item;
 
1482
  while ((item=li++))
 
1483
  {
 
1484
    if (item->send(protocol, &buffer))
 
1485
    {
 
1486
      protocol->free();                         // Free used buffer
 
1487
      my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
 
1488
      break;
 
1489
    }
 
1490
  }
 
1491
  thd->sent_row_count++;
 
1492
  if (thd->is_error())
 
1493
  {
 
1494
    protocol->remove_last_row();
 
1495
    DBUG_RETURN(1);
 
1496
  }
 
1497
  if (thd->vio_ok())
 
1498
    DBUG_RETURN(protocol->write());
 
1499
  DBUG_RETURN(0);
 
1500
}
 
1501
 
 
1502
bool select_send::send_eof()
 
1503
{
 
1504
  /* 
 
1505
    We may be passing the control from mysqld to the client: release the
 
1506
    InnoDB adaptive hash S-latch to avoid thread deadlocks if it was reserved
 
1507
    by thd 
 
1508
  */
 
1509
  ha_release_temporary_latches(thd);
 
1510
 
 
1511
  /* Unlock tables before sending packet to gain some speed */
 
1512
  if (thd->lock)
 
1513
  {
 
1514
    mysql_unlock_tables(thd, thd->lock);
 
1515
    thd->lock=0;
 
1516
  }
 
1517
  ::my_eof(thd);
 
1518
  is_result_set_started= 0;
 
1519
  return FALSE;
 
1520
}
 
1521
 
 
1522
 
 
1523
/************************************************************************
 
1524
  Handling writing to file
 
1525
************************************************************************/
 
1526
 
 
1527
void select_to_file::send_error(uint errcode,const char *err)
 
1528
{
 
1529
  my_message(errcode, err, MYF(0));
 
1530
  if (file > 0)
 
1531
  {
 
1532
    (void) end_io_cache(&cache);
 
1533
    (void) my_close(file,MYF(0));
 
1534
    (void) my_delete(path,MYF(0));              // Delete file on error
 
1535
    file= -1;
 
1536
  }
 
1537
}
 
1538
 
 
1539
 
 
1540
bool select_to_file::send_eof()
 
1541
{
 
1542
  int error= test(end_io_cache(&cache));
 
1543
  if (my_close(file,MYF(MY_WME)))
 
1544
    error= 1;
 
1545
  if (!error)
 
1546
  {
 
1547
    /*
 
1548
      In order to remember the value of affected rows for ROW_COUNT()
 
1549
      function, SELECT INTO has to have an own SQLCOM.
 
1550
      TODO: split from SQLCOM_SELECT
 
1551
    */
 
1552
    ::my_ok(thd,row_count);
 
1553
  }
 
1554
  file= -1;
 
1555
  return error;
 
1556
}
 
1557
 
 
1558
 
 
1559
void select_to_file::cleanup()
 
1560
{
 
1561
  /* In case of error send_eof() may be not called: close the file here. */
 
1562
  if (file >= 0)
 
1563
  {
 
1564
    (void) end_io_cache(&cache);
 
1565
    (void) my_close(file,MYF(0));
 
1566
    file= -1;
 
1567
  }
 
1568
  path[0]= '\0';
 
1569
  row_count= 0;
 
1570
}
 
1571
 
 
1572
 
 
1573
select_to_file::~select_to_file()
 
1574
{
 
1575
  if (file >= 0)
 
1576
  {                                     // This only happens in case of error
 
1577
    (void) end_io_cache(&cache);
 
1578
    (void) my_close(file,MYF(0));
 
1579
    file= -1;
 
1580
  }
 
1581
}
 
1582
 
 
1583
/***************************************************************************
 
1584
** Export of select to textfile
 
1585
***************************************************************************/
 
1586
 
 
1587
select_export::~select_export()
 
1588
{
 
1589
  thd->sent_row_count=row_count;
 
1590
}
 
1591
 
 
1592
 
 
1593
/*
 
1594
  Create file with IO cache
 
1595
 
 
1596
  SYNOPSIS
 
1597
    create_file()
 
1598
    thd                 Thread handle
 
1599
    path                File name
 
1600
    exchange            Excange class
 
1601
    cache               IO cache
 
1602
 
 
1603
  RETURN
 
1604
    >= 0        File handle
 
1605
   -1           Error
 
1606
*/
 
1607
 
 
1608
 
 
1609
static File create_file(THD *thd, char *path, sql_exchange *exchange,
 
1610
                        IO_CACHE *cache)
 
1611
{
 
1612
  File file;
 
1613
  uint option= MY_UNPACK_FILENAME | MY_RELATIVE_PATH;
 
1614
 
 
1615
#ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS
 
1616
  option|= MY_REPLACE_DIR;                      // Force use of db directory
 
1617
#endif
 
1618
 
 
1619
  if (!dirname_length(exchange->file_name))
 
1620
  {
 
1621
    strxnmov(path, FN_REFLEN-1, mysql_real_data_home, thd->db ? thd->db : "",
 
1622
             NullS);
 
1623
    (void) fn_format(path, exchange->file_name, path, "", option);
 
1624
  }
 
1625
  else
 
1626
    (void) fn_format(path, exchange->file_name, mysql_real_data_home, "", option);
 
1627
 
 
1628
  if (opt_secure_file_priv &&
 
1629
      strncmp(opt_secure_file_priv, path, strlen(opt_secure_file_priv)))
 
1630
  {
 
1631
    /* Write only allowed to dir or subdir specified by secure_file_priv */
 
1632
    my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
 
1633
    return -1;
 
1634
  }
 
1635
 
 
1636
  if (!access(path, F_OK))
 
1637
  {
 
1638
    my_error(ER_FILE_EXISTS_ERROR, MYF(0), exchange->file_name);
 
1639
    return -1;
 
1640
  }
 
1641
  /* Create the file world readable */
 
1642
  if ((file= my_create(path, 0666, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0)
 
1643
    return file;
 
1644
#ifdef HAVE_FCHMOD
 
1645
  (void) fchmod(file, 0666);                    // Because of umask()
 
1646
#else
 
1647
  (void) chmod(path, 0666);
 
1648
#endif
 
1649
  if (init_io_cache(cache, file, 0L, WRITE_CACHE, 0L, 1, MYF(MY_WME)))
 
1650
  {
 
1651
    my_close(file, MYF(0));
 
1652
    my_delete(path, MYF(0));  // Delete file on error, it was just created 
 
1653
    return -1;
 
1654
  }
 
1655
  return file;
 
1656
}
 
1657
 
 
1658
 
 
1659
int
 
1660
select_export::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
 
1661
{
 
1662
  bool blob_flag=0;
 
1663
  bool string_results= FALSE, non_string_results= FALSE;
 
1664
  unit= u;
 
1665
  if ((uint) strlen(exchange->file_name) + NAME_LEN >= FN_REFLEN)
 
1666
    strmake(path,exchange->file_name,FN_REFLEN-1);
 
1667
 
 
1668
  if ((file= create_file(thd, path, exchange, &cache)) < 0)
 
1669
    return 1;
 
1670
  /* Check if there is any blobs in data */
 
1671
  {
 
1672
    List_iterator_fast<Item> li(list);
 
1673
    Item *item;
 
1674
    while ((item=li++))
 
1675
    {
 
1676
      if (item->max_length >= MAX_BLOB_WIDTH)
 
1677
      {
 
1678
        blob_flag=1;
 
1679
        break;
 
1680
      }
 
1681
      if (item->result_type() == STRING_RESULT)
 
1682
        string_results= TRUE;
 
1683
      else
 
1684
        non_string_results= TRUE;
 
1685
    }
 
1686
  }
 
1687
  field_term_length=exchange->field_term->length();
 
1688
  field_term_char= field_term_length ?
 
1689
                   (int) (uchar) (*exchange->field_term)[0] : INT_MAX;
 
1690
  if (!exchange->line_term->length())
 
1691
    exchange->line_term=exchange->field_term;   // Use this if it exists
 
1692
  field_sep_char= (exchange->enclosed->length() ?
 
1693
                  (int) (uchar) (*exchange->enclosed)[0] : field_term_char);
 
1694
  escape_char=  (exchange->escaped->length() ?
 
1695
                (int) (uchar) (*exchange->escaped)[0] : -1);
 
1696
  is_ambiguous_field_sep= test(strchr(ESCAPE_CHARS, field_sep_char));
 
1697
  is_unsafe_field_sep= test(strchr(NUMERIC_CHARS, field_sep_char));
 
1698
  line_sep_char= (exchange->line_term->length() ?
 
1699
                 (int) (uchar) (*exchange->line_term)[0] : INT_MAX);
 
1700
  if (!field_term_length)
 
1701
    exchange->opt_enclosed=0;
 
1702
  if (!exchange->enclosed->length())
 
1703
    exchange->opt_enclosed=1;                   // A little quicker loop
 
1704
  fixed_row_size= (!field_term_length && !exchange->enclosed->length() &&
 
1705
                   !blob_flag);
 
1706
  if ((is_ambiguous_field_sep && exchange->enclosed->is_empty() &&
 
1707
       (string_results || is_unsafe_field_sep)) ||
 
1708
      (exchange->opt_enclosed && non_string_results &&
 
1709
       field_term_length && strchr(NUMERIC_CHARS, field_term_char)))
 
1710
  {
 
1711
    push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
 
1712
                 ER_AMBIGUOUS_FIELD_TERM, ER(ER_AMBIGUOUS_FIELD_TERM));
 
1713
    is_ambiguous_field_term= TRUE;
 
1714
  }
 
1715
  else
 
1716
    is_ambiguous_field_term= FALSE;
 
1717
 
 
1718
  return 0;
 
1719
}
 
1720
 
 
1721
 
 
1722
#define NEED_ESCAPING(x) ((int) (uchar) (x) == escape_char    || \
 
1723
                          (enclosed ? (int) (uchar) (x) == field_sep_char      \
 
1724
                                    : (int) (uchar) (x) == field_term_char) || \
 
1725
                          (int) (uchar) (x) == line_sep_char  || \
 
1726
                          !(x))
 
1727
 
 
1728
bool select_export::send_data(List<Item> &items)
 
1729
{
 
1730
 
 
1731
  DBUG_ENTER("select_export::send_data");
 
1732
  char buff[MAX_FIELD_WIDTH],null_buff[2],space[MAX_FIELD_WIDTH];
 
1733
  bool space_inited=0;
 
1734
  String tmp(buff,sizeof(buff),&my_charset_bin),*res;
 
1735
  tmp.length(0);
 
1736
 
 
1737
  if (unit->offset_limit_cnt)
 
1738
  {                                             // using limit offset,count
 
1739
    unit->offset_limit_cnt--;
 
1740
    DBUG_RETURN(0);
 
1741
  }
 
1742
  row_count++;
 
1743
  Item *item;
 
1744
  uint used_length=0,items_left=items.elements;
 
1745
  List_iterator_fast<Item> li(items);
 
1746
 
 
1747
  if (my_b_write(&cache,(uchar*) exchange->line_start->ptr(),
 
1748
                 exchange->line_start->length()))
 
1749
    goto err;
 
1750
  while ((item=li++))
 
1751
  {
 
1752
    Item_result result_type=item->result_type();
 
1753
    bool enclosed = (exchange->enclosed->length() &&
 
1754
                     (!exchange->opt_enclosed || result_type == STRING_RESULT));
 
1755
    res=item->str_result(&tmp);
 
1756
    if (res && enclosed)
 
1757
    {
 
1758
      if (my_b_write(&cache,(uchar*) exchange->enclosed->ptr(),
 
1759
                     exchange->enclosed->length()))
 
1760
        goto err;
 
1761
    }
 
1762
    if (!res)
 
1763
    {                                           // NULL
 
1764
      if (!fixed_row_size)
 
1765
      {
 
1766
        if (escape_char != -1)                  // Use \N syntax
 
1767
        {
 
1768
          null_buff[0]=escape_char;
 
1769
          null_buff[1]='N';
 
1770
          if (my_b_write(&cache,(uchar*) null_buff,2))
 
1771
            goto err;
 
1772
        }
 
1773
        else if (my_b_write(&cache,(uchar*) "NULL",4))
 
1774
          goto err;
 
1775
      }
 
1776
      else
 
1777
      {
 
1778
        used_length=0;                          // Fill with space
 
1779
      }
 
1780
    }
 
1781
    else
 
1782
    {
 
1783
      if (fixed_row_size)
 
1784
        used_length=min(res->length(),item->max_length);
 
1785
      else
 
1786
        used_length=res->length();
 
1787
      if ((result_type == STRING_RESULT || is_unsafe_field_sep) &&
 
1788
           escape_char != -1)
 
1789
      {
 
1790
        char *pos, *start, *end;
 
1791
        CHARSET_INFO *res_charset= res->charset();
 
1792
        CHARSET_INFO *character_set_client= thd->variables.
 
1793
                                            character_set_client;
 
1794
        bool check_second_byte= (res_charset == &my_charset_bin) &&
 
1795
                                 character_set_client->
 
1796
                                 escape_with_backslash_is_dangerous;
 
1797
        DBUG_ASSERT(character_set_client->mbmaxlen == 2 ||
 
1798
                    !character_set_client->escape_with_backslash_is_dangerous);
 
1799
        for (start=pos=(char*) res->ptr(),end=pos+used_length ;
 
1800
             pos != end ;
 
1801
             pos++)
 
1802
        {
 
1803
#ifdef USE_MB
 
1804
          if (use_mb(res_charset))
 
1805
          {
 
1806
            int l;
 
1807
            if ((l=my_ismbchar(res_charset, pos, end)))
 
1808
            {
 
1809
              pos += l-1;
 
1810
              continue;
 
1811
            }
 
1812
          }
 
1813
#endif
 
1814
 
 
1815
          /*
 
1816
            Special case when dumping BINARY/VARBINARY/BLOB values
 
1817
            for the clients with character sets big5, cp932, gbk and sjis,
 
1818
            which can have the escape character (0x5C "\" by default)
 
1819
            as the second byte of a multi-byte sequence.
 
1820
            
 
1821
            If
 
1822
            - pos[0] is a valid multi-byte head (e.g 0xEE) and
 
1823
            - pos[1] is 0x00, which will be escaped as "\0",
 
1824
            
 
1825
            then we'll get "0xEE + 0x5C + 0x30" in the output file.
 
1826
            
 
1827
            If this file is later loaded using this sequence of commands:
 
1828
            
 
1829
            mysql> create table t1 (a varchar(128)) character set big5;
 
1830
            mysql> LOAD DATA INFILE 'dump.txt' INTO TABLE t1;
 
1831
            
 
1832
            then 0x5C will be misinterpreted as the second byte
 
1833
            of a multi-byte character "0xEE + 0x5C", instead of
 
1834
            escape character for 0x00.
 
1835
            
 
1836
            To avoid this confusion, we'll escape the multi-byte
 
1837
            head character too, so the sequence "0xEE + 0x00" will be
 
1838
            dumped as "0x5C + 0xEE + 0x5C + 0x30".
 
1839
            
 
1840
            Note, in the condition below we only check if
 
1841
            mbcharlen is equal to 2, because there are no
 
1842
            character sets with mbmaxlen longer than 2
 
1843
            and with escape_with_backslash_is_dangerous set.
 
1844
            DBUG_ASSERT before the loop makes that sure.
 
1845
          */
 
1846
 
 
1847
          if ((NEED_ESCAPING(*pos) ||
 
1848
               (check_second_byte &&
 
1849
                my_mbcharlen(character_set_client, (uchar) *pos) == 2 &&
 
1850
                pos + 1 < end &&
 
1851
                NEED_ESCAPING(pos[1]))) &&
 
1852
              /*
 
1853
               Don't escape field_term_char by doubling - doubling is only
 
1854
               valid for ENCLOSED BY characters:
 
1855
              */
 
1856
              (enclosed || !is_ambiguous_field_term ||
 
1857
               (int) (uchar) *pos != field_term_char))
 
1858
          {
 
1859
            char tmp_buff[2];
 
1860
            tmp_buff[0]= ((int) (uchar) *pos == field_sep_char &&
 
1861
                          is_ambiguous_field_sep) ?
 
1862
                          field_sep_char : escape_char;
 
1863
            tmp_buff[1]= *pos ? *pos : '0';
 
1864
            if (my_b_write(&cache,(uchar*) start,(uint) (pos-start)) ||
 
1865
                my_b_write(&cache,(uchar*) tmp_buff,2))
 
1866
              goto err;
 
1867
            start=pos+1;
 
1868
          }
 
1869
        }
 
1870
        if (my_b_write(&cache,(uchar*) start,(uint) (pos-start)))
 
1871
          goto err;
 
1872
      }
 
1873
      else if (my_b_write(&cache,(uchar*) res->ptr(),used_length))
 
1874
        goto err;
 
1875
    }
 
1876
    if (fixed_row_size)
 
1877
    {                                           // Fill with space
 
1878
      if (item->max_length > used_length)
 
1879
      {
 
1880
        /* QQ:  Fix by adding a my_b_fill() function */
 
1881
        if (!space_inited)
 
1882
        {
 
1883
          space_inited=1;
 
1884
          bfill(space,sizeof(space),' ');
 
1885
        }
 
1886
        uint length=item->max_length-used_length;
 
1887
        for (; length > sizeof(space) ; length-=sizeof(space))
 
1888
        {
 
1889
          if (my_b_write(&cache,(uchar*) space,sizeof(space)))
 
1890
            goto err;
 
1891
        }
 
1892
        if (my_b_write(&cache,(uchar*) space,length))
 
1893
          goto err;
 
1894
      }
 
1895
    }
 
1896
    if (res && enclosed)
 
1897
    {
 
1898
      if (my_b_write(&cache, (uchar*) exchange->enclosed->ptr(),
 
1899
                     exchange->enclosed->length()))
 
1900
        goto err;
 
1901
    }
 
1902
    if (--items_left)
 
1903
    {
 
1904
      if (my_b_write(&cache, (uchar*) exchange->field_term->ptr(),
 
1905
                     field_term_length))
 
1906
        goto err;
 
1907
    }
 
1908
  }
 
1909
  if (my_b_write(&cache,(uchar*) exchange->line_term->ptr(),
 
1910
                 exchange->line_term->length()))
 
1911
    goto err;
 
1912
  DBUG_RETURN(0);
 
1913
err:
 
1914
  DBUG_RETURN(1);
 
1915
}
 
1916
 
 
1917
 
 
1918
/***************************************************************************
 
1919
** Dump  of select to a binary file
 
1920
***************************************************************************/
 
1921
 
 
1922
 
 
1923
int
 
1924
select_dump::prepare(List<Item> &list __attribute__((unused)),
 
1925
                     SELECT_LEX_UNIT *u)
 
1926
{
 
1927
  unit= u;
 
1928
  return (int) ((file= create_file(thd, path, exchange, &cache)) < 0);
 
1929
}
 
1930
 
 
1931
 
 
1932
bool select_dump::send_data(List<Item> &items)
 
1933
{
 
1934
  List_iterator_fast<Item> li(items);
 
1935
  char buff[MAX_FIELD_WIDTH];
 
1936
  String tmp(buff,sizeof(buff),&my_charset_bin),*res;
 
1937
  tmp.length(0);
 
1938
  Item *item;
 
1939
  DBUG_ENTER("select_dump::send_data");
 
1940
 
 
1941
  if (unit->offset_limit_cnt)
 
1942
  {                                             // using limit offset,count
 
1943
    unit->offset_limit_cnt--;
 
1944
    DBUG_RETURN(0);
 
1945
  }
 
1946
  if (row_count++ > 1) 
 
1947
  {
 
1948
    my_message(ER_TOO_MANY_ROWS, ER(ER_TOO_MANY_ROWS), MYF(0));
 
1949
    goto err;
 
1950
  }
 
1951
  while ((item=li++))
 
1952
  {
 
1953
    res=item->str_result(&tmp);
 
1954
    if (!res)                                   // If NULL
 
1955
    {
 
1956
      if (my_b_write(&cache,(uchar*) "",1))
 
1957
        goto err;
 
1958
    }
 
1959
    else if (my_b_write(&cache,(uchar*) res->ptr(),res->length()))
 
1960
    {
 
1961
      my_error(ER_ERROR_ON_WRITE, MYF(0), path, my_errno);
 
1962
      goto err;
 
1963
    }
 
1964
  }
 
1965
  DBUG_RETURN(0);
 
1966
err:
 
1967
  DBUG_RETURN(1);
 
1968
}
 
1969
 
 
1970
 
 
1971
select_subselect::select_subselect(Item_subselect *item_arg)
 
1972
{
 
1973
  item= item_arg;
 
1974
}
 
1975
 
 
1976
 
 
1977
bool select_singlerow_subselect::send_data(List<Item> &items)
 
1978
{
 
1979
  DBUG_ENTER("select_singlerow_subselect::send_data");
 
1980
  Item_singlerow_subselect *it= (Item_singlerow_subselect *)item;
 
1981
  if (it->assigned())
 
1982
  {
 
1983
    my_message(ER_SUBQUERY_NO_1_ROW, ER(ER_SUBQUERY_NO_1_ROW), MYF(0));
 
1984
    DBUG_RETURN(1);
 
1985
  }
 
1986
  if (unit->offset_limit_cnt)
 
1987
  {                                       // Using limit offset,count
 
1988
    unit->offset_limit_cnt--;
 
1989
    DBUG_RETURN(0);
 
1990
  }
 
1991
  List_iterator_fast<Item> li(items);
 
1992
  Item *val_item;
 
1993
  for (uint i= 0; (val_item= li++); i++)
 
1994
    it->store(i, val_item);
 
1995
  it->assigned(1);
 
1996
  DBUG_RETURN(0);
 
1997
}
 
1998
 
 
1999
 
 
2000
void select_max_min_finder_subselect::cleanup()
 
2001
{
 
2002
  DBUG_ENTER("select_max_min_finder_subselect::cleanup");
 
2003
  cache= 0;
 
2004
  DBUG_VOID_RETURN;
 
2005
}
 
2006
 
 
2007
 
 
2008
bool select_max_min_finder_subselect::send_data(List<Item> &items)
 
2009
{
 
2010
  DBUG_ENTER("select_max_min_finder_subselect::send_data");
 
2011
  Item_maxmin_subselect *it= (Item_maxmin_subselect *)item;
 
2012
  List_iterator_fast<Item> li(items);
 
2013
  Item *val_item= li++;
 
2014
  it->register_value();
 
2015
  if (it->assigned())
 
2016
  {
 
2017
    cache->store(val_item);
 
2018
    if ((this->*op)())
 
2019
      it->store(0, cache);
 
2020
  }
 
2021
  else
 
2022
  {
 
2023
    if (!cache)
 
2024
    {
 
2025
      cache= Item_cache::get_cache(val_item);
 
2026
      switch (val_item->result_type())
 
2027
      {
 
2028
      case REAL_RESULT:
 
2029
        op= &select_max_min_finder_subselect::cmp_real;
 
2030
        break;
 
2031
      case INT_RESULT:
 
2032
        op= &select_max_min_finder_subselect::cmp_int;
 
2033
        break;
 
2034
      case STRING_RESULT:
 
2035
        op= &select_max_min_finder_subselect::cmp_str;
 
2036
        break;
 
2037
      case DECIMAL_RESULT:
 
2038
        op= &select_max_min_finder_subselect::cmp_decimal;
 
2039
        break;
 
2040
      case ROW_RESULT:
 
2041
        // This case should never be choosen
 
2042
        DBUG_ASSERT(0);
 
2043
        op= 0;
 
2044
      }
 
2045
    }
 
2046
    cache->store(val_item);
 
2047
    it->store(0, cache);
 
2048
  }
 
2049
  it->assigned(1);
 
2050
  DBUG_RETURN(0);
 
2051
}
 
2052
 
 
2053
bool select_max_min_finder_subselect::cmp_real()
 
2054
{
 
2055
  Item *maxmin= ((Item_singlerow_subselect *)item)->element_index(0);
 
2056
  double val1= cache->val_real(), val2= maxmin->val_real();
 
2057
  if (fmax)
 
2058
    return (cache->null_value && !maxmin->null_value) ||
 
2059
      (!cache->null_value && !maxmin->null_value &&
 
2060
       val1 > val2);
 
2061
  return (maxmin->null_value && !cache->null_value) ||
 
2062
    (!cache->null_value && !maxmin->null_value &&
 
2063
     val1 < val2);
 
2064
}
 
2065
 
 
2066
bool select_max_min_finder_subselect::cmp_int()
 
2067
{
 
2068
  Item *maxmin= ((Item_singlerow_subselect *)item)->element_index(0);
 
2069
  longlong val1= cache->val_int(), val2= maxmin->val_int();
 
2070
  if (fmax)
 
2071
    return (cache->null_value && !maxmin->null_value) ||
 
2072
      (!cache->null_value && !maxmin->null_value &&
 
2073
       val1 > val2);
 
2074
  return (maxmin->null_value && !cache->null_value) ||
 
2075
    (!cache->null_value && !maxmin->null_value &&
 
2076
     val1 < val2);
 
2077
}
 
2078
 
 
2079
bool select_max_min_finder_subselect::cmp_decimal()
 
2080
{
 
2081
  Item *maxmin= ((Item_singlerow_subselect *)item)->element_index(0);
 
2082
  my_decimal cval, *cvalue= cache->val_decimal(&cval);
 
2083
  my_decimal mval, *mvalue= maxmin->val_decimal(&mval);
 
2084
  if (fmax)
 
2085
    return (cache->null_value && !maxmin->null_value) ||
 
2086
      (!cache->null_value && !maxmin->null_value &&
 
2087
       my_decimal_cmp(cvalue, mvalue) > 0) ;
 
2088
  return (maxmin->null_value && !cache->null_value) ||
 
2089
    (!cache->null_value && !maxmin->null_value &&
 
2090
     my_decimal_cmp(cvalue,mvalue) < 0);
 
2091
}
 
2092
 
 
2093
bool select_max_min_finder_subselect::cmp_str()
 
2094
{
 
2095
  String *val1, *val2, buf1, buf2;
 
2096
  Item *maxmin= ((Item_singlerow_subselect *)item)->element_index(0);
 
2097
  /*
 
2098
    as far as both operand is Item_cache buf1 & buf2 will not be used,
 
2099
    but added for safety
 
2100
  */
 
2101
  val1= cache->val_str(&buf1);
 
2102
  val2= maxmin->val_str(&buf1);
 
2103
  if (fmax)
 
2104
    return (cache->null_value && !maxmin->null_value) ||
 
2105
      (!cache->null_value && !maxmin->null_value &&
 
2106
       sortcmp(val1, val2, cache->collation.collation) > 0) ;
 
2107
  return (maxmin->null_value && !cache->null_value) ||
 
2108
    (!cache->null_value && !maxmin->null_value &&
 
2109
     sortcmp(val1, val2, cache->collation.collation) < 0);
 
2110
}
 
2111
 
 
2112
bool select_exists_subselect::send_data(List<Item> &items)
 
2113
{
 
2114
  DBUG_ENTER("select_exists_subselect::send_data");
 
2115
  Item_exists_subselect *it= (Item_exists_subselect *)item;
 
2116
  if (unit->offset_limit_cnt)
 
2117
  {                                       // Using limit offset,count
 
2118
    unit->offset_limit_cnt--;
 
2119
    DBUG_RETURN(0);
 
2120
  }
 
2121
  it->value= 1;
 
2122
  it->assigned(1);
 
2123
  DBUG_RETURN(0);
 
2124
}
 
2125
 
 
2126
 
 
2127
/***************************************************************************
 
2128
  Dump of select to variables
 
2129
***************************************************************************/
 
2130
 
 
2131
int select_dumpvar::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
 
2132
{
 
2133
  unit= u;
 
2134
  
 
2135
  if (var_list.elements != list.elements)
 
2136
  {
 
2137
    my_message(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT,
 
2138
               ER(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT), MYF(0));
 
2139
    return 1;
 
2140
  }               
 
2141
  return 0;
 
2142
}
 
2143
 
 
2144
 
 
2145
bool select_dumpvar::check_simple_select() const
 
2146
{
 
2147
  my_error(ER_SP_BAD_CURSOR_SELECT, MYF(0));
 
2148
  return TRUE;
 
2149
}
 
2150
 
 
2151
 
 
2152
void select_dumpvar::cleanup()
 
2153
{
 
2154
  row_count= 0;
 
2155
}
 
2156
 
 
2157
 
 
2158
void Query_arena::free_items()
 
2159
{
 
2160
  Item *next;
 
2161
  DBUG_ENTER("Query_arena::free_items");
 
2162
  /* This works because items are allocated with sql_alloc() */
 
2163
  for (; free_list; free_list= next)
 
2164
  {
 
2165
    next= free_list->next;
 
2166
    free_list->delete_self();
 
2167
  }
 
2168
  /* Postcondition: free_list is 0 */
 
2169
  DBUG_VOID_RETURN;
 
2170
}
 
2171
 
 
2172
 
 
2173
void Query_arena::set_query_arena(Query_arena *set)
 
2174
{
 
2175
  mem_root=  set->mem_root;
 
2176
  free_list= set->free_list;
 
2177
  state= set->state;
 
2178
}
 
2179
 
 
2180
 
 
2181
void Query_arena::cleanup_stmt()
 
2182
{
 
2183
  DBUG_ASSERT("Query_arena::cleanup_stmt()" == "not implemented");
 
2184
}
 
2185
 
 
2186
/*
 
2187
  Statement functions
 
2188
*/
 
2189
 
 
2190
Statement::Statement(LEX *lex_arg, MEM_ROOT *mem_root_arg,
 
2191
                     enum enum_state state_arg, ulong id_arg)
 
2192
  :Query_arena(mem_root_arg, state_arg),
 
2193
  id(id_arg),
 
2194
  mark_used_columns(MARK_COLUMNS_READ),
 
2195
  lex(lex_arg),
 
2196
  query(0),
 
2197
  query_length(0),
 
2198
  db(NULL),
 
2199
  db_length(0)
 
2200
{
 
2201
  name.str= NULL;
 
2202
}
 
2203
 
 
2204
 
 
2205
void Statement::set_statement(Statement *stmt)
 
2206
{
 
2207
  id=             stmt->id;
 
2208
  mark_used_columns=   stmt->mark_used_columns;
 
2209
  lex=            stmt->lex;
 
2210
  query=          stmt->query;
 
2211
  query_length=   stmt->query_length;
 
2212
}
 
2213
 
 
2214
 
 
2215
void
 
2216
Statement::set_n_backup_statement(Statement *stmt, Statement *backup)
 
2217
{
 
2218
  DBUG_ENTER("Statement::set_n_backup_statement");
 
2219
  backup->set_statement(this);
 
2220
  set_statement(stmt);
 
2221
  DBUG_VOID_RETURN;
 
2222
}
 
2223
 
 
2224
 
 
2225
void Statement::restore_backup_statement(Statement *stmt, Statement *backup)
 
2226
{
 
2227
  DBUG_ENTER("Statement::restore_backup_statement");
 
2228
  stmt->set_statement(this);
 
2229
  set_statement(backup);
 
2230
  DBUG_VOID_RETURN;
 
2231
}
 
2232
 
 
2233
 
 
2234
void THD::end_statement()
 
2235
{
 
2236
  /* Cleanup SQL processing state to reuse this statement in next query. */
 
2237
  lex_end(lex);
 
2238
  delete lex->result;
 
2239
  lex->result= 0;
 
2240
  /* Note that free_list is freed in cleanup_after_query() */
 
2241
 
 
2242
  /*
 
2243
    Don't free mem_root, as mem_root is freed in the end of dispatch_command
 
2244
    (once for any command).
 
2245
  */
 
2246
}
 
2247
 
 
2248
 
 
2249
void THD::set_n_backup_active_arena(Query_arena *set, Query_arena *backup)
 
2250
{
 
2251
  DBUG_ENTER("THD::set_n_backup_active_arena");
 
2252
  DBUG_ASSERT(backup->is_backup_arena == FALSE);
 
2253
 
 
2254
  backup->set_query_arena(this);
 
2255
  set_query_arena(set);
 
2256
#ifndef DBUG_OFF
 
2257
  backup->is_backup_arena= TRUE;
 
2258
#endif
 
2259
  DBUG_VOID_RETURN;
 
2260
}
 
2261
 
 
2262
 
 
2263
void THD::restore_active_arena(Query_arena *set, Query_arena *backup)
 
2264
{
 
2265
  DBUG_ENTER("THD::restore_active_arena");
 
2266
  DBUG_ASSERT(backup->is_backup_arena);
 
2267
  set->set_query_arena(this);
 
2268
  set_query_arena(backup);
 
2269
#ifndef DBUG_OFF
 
2270
  backup->is_backup_arena= FALSE;
 
2271
#endif
 
2272
  DBUG_VOID_RETURN;
 
2273
}
 
2274
 
 
2275
bool select_dumpvar::send_data(List<Item> &items)
 
2276
{
 
2277
  List_iterator_fast<my_var> var_li(var_list);
 
2278
  List_iterator<Item> it(items);
 
2279
  Item *item;
 
2280
  my_var *mv;
 
2281
  DBUG_ENTER("select_dumpvar::send_data");
 
2282
 
 
2283
  if (unit->offset_limit_cnt)
 
2284
  {                                             // using limit offset,count
 
2285
    unit->offset_limit_cnt--;
 
2286
    DBUG_RETURN(0);
 
2287
  }
 
2288
  if (row_count++) 
 
2289
  {
 
2290
    my_message(ER_TOO_MANY_ROWS, ER(ER_TOO_MANY_ROWS), MYF(0));
 
2291
    DBUG_RETURN(1);
 
2292
  }
 
2293
  while ((mv= var_li++) && (item= it++))
 
2294
  {
 
2295
    if (mv->local == 0)
 
2296
    {
 
2297
      Item_func_set_user_var *suv= new Item_func_set_user_var(mv->s, item);
 
2298
      suv->fix_fields(thd, 0);
 
2299
      suv->check(0);
 
2300
      suv->update();
 
2301
    }
 
2302
  }
 
2303
  DBUG_RETURN(thd->is_error());
 
2304
}
 
2305
 
 
2306
bool select_dumpvar::send_eof()
 
2307
{
 
2308
  if (! row_count)
 
2309
    push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
 
2310
                 ER_SP_FETCH_NO_DATA, ER(ER_SP_FETCH_NO_DATA));
 
2311
  /*
 
2312
    In order to remember the value of affected rows for ROW_COUNT()
 
2313
    function, SELECT INTO has to have an own SQLCOM.
 
2314
    TODO: split from SQLCOM_SELECT
 
2315
  */
 
2316
  ::my_ok(thd,row_count);
 
2317
  return 0;
 
2318
}
 
2319
 
 
2320
/****************************************************************************
 
2321
  TMP_TABLE_PARAM
 
2322
****************************************************************************/
 
2323
 
 
2324
void TMP_TABLE_PARAM::init()
 
2325
{
 
2326
  DBUG_ENTER("TMP_TABLE_PARAM::init");
 
2327
  DBUG_PRINT("enter", ("this: 0x%lx", (ulong)this));
 
2328
  field_count= sum_func_count= func_count= hidden_field_count= 0;
 
2329
  group_parts= group_length= group_null_parts= 0;
 
2330
  quick_group= 1;
 
2331
  table_charset= 0;
 
2332
  precomputed_group_by= 0;
 
2333
  bit_fields_as_long= 0;
 
2334
  DBUG_VOID_RETURN;
 
2335
}
 
2336
 
 
2337
 
 
2338
void thd_increment_bytes_sent(ulong length)
 
2339
{
 
2340
  THD *thd=current_thd;
 
2341
  if (likely(thd != 0))
 
2342
  { /* current_thd==0 when close_connection() calls net_send_error() */
 
2343
    thd->status_var.bytes_sent+= length;
 
2344
  }
 
2345
}
 
2346
 
 
2347
 
 
2348
void thd_increment_bytes_received(ulong length)
 
2349
{
 
2350
  current_thd->status_var.bytes_received+= length;
 
2351
}
 
2352
 
 
2353
 
 
2354
void thd_increment_net_big_packet_count(ulong length)
 
2355
{
 
2356
  current_thd->status_var.net_big_packet_count+= length;
 
2357
}
 
2358
 
 
2359
 
 
2360
void THD::set_status_var_init()
 
2361
{
 
2362
  bzero((char*) &status_var, sizeof(status_var));
 
2363
}
 
2364
 
 
2365
 
 
2366
void Security_context::init()
 
2367
{
 
2368
  host= user= priv_user= ip= 0;
 
2369
  host_or_ip= "connecting host";
 
2370
  priv_host[0]= '\0';
 
2371
}
 
2372
 
 
2373
 
 
2374
void Security_context::destroy()
 
2375
{
 
2376
  // If not pointer to constant
 
2377
  if (host != my_localhost)
 
2378
    safeFree(host);
 
2379
  safeFree(user);
 
2380
  safeFree(ip);
 
2381
}
 
2382
 
 
2383
 
 
2384
void Security_context::skip_grants()
 
2385
{
 
2386
  /* privileges for the user are unknown everything is allowed */
 
2387
  host_or_ip= (char *)"";
 
2388
  priv_user= (char *)"";
 
2389
  *priv_host= '\0';
 
2390
}
 
2391
 
 
2392
 
 
2393
/****************************************************************************
 
2394
  Handling of open and locked tables states.
 
2395
 
 
2396
  This is used when we want to open/lock (and then close) some tables when
 
2397
  we already have a set of tables open and locked. We use these methods for
 
2398
  access to mysql.proc table to find definitions of stored routines.
 
2399
****************************************************************************/
 
2400
 
 
2401
void THD::reset_n_backup_open_tables_state(Open_tables_state *backup)
 
2402
{
 
2403
  DBUG_ENTER("reset_n_backup_open_tables_state");
 
2404
  backup->set_open_tables_state(this);
 
2405
  reset_open_tables_state();
 
2406
  state_flags|= Open_tables_state::BACKUPS_AVAIL;
 
2407
  DBUG_VOID_RETURN;
 
2408
}
 
2409
 
 
2410
 
 
2411
void THD::restore_backup_open_tables_state(Open_tables_state *backup)
 
2412
{
 
2413
  DBUG_ENTER("restore_backup_open_tables_state");
 
2414
  /*
 
2415
    Before we will throw away current open tables state we want
 
2416
    to be sure that it was properly cleaned up.
 
2417
  */
 
2418
  DBUG_ASSERT(open_tables == 0 && temporary_tables == 0 &&
 
2419
              handler_tables == 0 && derived_tables == 0 &&
 
2420
              lock == 0 && locked_tables == 0);
 
2421
  set_open_tables_state(backup);
 
2422
  DBUG_VOID_RETURN;
 
2423
}
 
2424
 
 
2425
/**
 
2426
  Check the killed state of a user thread
 
2427
  @param thd  user thread
 
2428
  @retval 0 the user thread is active
 
2429
  @retval 1 the user thread has been killed
 
2430
*/
 
2431
extern "C" int thd_killed(const MYSQL_THD thd)
 
2432
{
 
2433
  return(thd->killed);
 
2434
}
 
2435
 
 
2436
/**
 
2437
  Return the thread id of a user thread
 
2438
  @param thd user thread
 
2439
  @return thread id
 
2440
*/
 
2441
extern "C" unsigned long thd_get_thread_id(const MYSQL_THD thd)
 
2442
{
 
2443
  return((unsigned long)thd->thread_id);
 
2444
}
 
2445
 
 
2446
 
 
2447
#ifdef INNODB_COMPATIBILITY_HOOKS
 
2448
extern "C" struct charset_info_st *thd_charset(MYSQL_THD thd)
 
2449
{
 
2450
  return(thd->charset());
 
2451
}
 
2452
 
 
2453
extern "C" char **thd_query(MYSQL_THD thd)
 
2454
{
 
2455
  return(&thd->query);
 
2456
}
 
2457
 
 
2458
extern "C" int thd_slave_thread(const MYSQL_THD thd)
 
2459
{
 
2460
  return(thd->slave_thread);
 
2461
}
 
2462
 
 
2463
extern "C" int thd_non_transactional_update(const MYSQL_THD thd)
 
2464
{
 
2465
  return(thd->transaction.all.modified_non_trans_table);
 
2466
}
 
2467
 
 
2468
extern "C" int thd_binlog_format(const MYSQL_THD thd)
 
2469
{
 
2470
  return (int) thd->variables.binlog_format;
 
2471
}
 
2472
 
 
2473
extern "C" void thd_mark_transaction_to_rollback(MYSQL_THD thd, bool all)
 
2474
{
 
2475
  mark_transaction_to_rollback(thd, all);
 
2476
}
 
2477
#endif // INNODB_COMPATIBILITY_HOOKS */
 
2478
 
 
2479
 
 
2480
/**
 
2481
  Mark transaction to rollback and mark error as fatal to a sub-statement.
 
2482
 
 
2483
  @param  thd   Thread handle
 
2484
  @param  all   TRUE <=> rollback main transaction.
 
2485
*/
 
2486
 
 
2487
void mark_transaction_to_rollback(THD *thd, bool all)
 
2488
{
 
2489
  if (thd)
 
2490
  {
 
2491
    thd->is_fatal_sub_stmt_error= TRUE;
 
2492
    thd->transaction_rollback_request= all;
 
2493
  }
 
2494
}
 
2495
/***************************************************************************
 
2496
  Handling of XA id cacheing
 
2497
***************************************************************************/
 
2498
 
 
2499
pthread_mutex_t LOCK_xid_cache;
 
2500
HASH xid_cache;
 
2501
 
 
2502
extern "C" uchar *xid_get_hash_key(const uchar *, size_t *, my_bool);
 
2503
extern "C" void xid_free_hash(void *);
 
2504
 
 
2505
uchar *xid_get_hash_key(const uchar *ptr, size_t *length,
 
2506
                                  my_bool not_used __attribute__((unused)))
 
2507
{
 
2508
  *length=((XID_STATE*)ptr)->xid.key_length();
 
2509
  return ((XID_STATE*)ptr)->xid.key();
 
2510
}
 
2511
 
 
2512
void xid_free_hash(void *ptr)
 
2513
{
 
2514
  if (!((XID_STATE*)ptr)->in_thd)
 
2515
    my_free((uchar*)ptr, MYF(0));
 
2516
}
 
2517
 
 
2518
bool xid_cache_init()
 
2519
{
 
2520
  pthread_mutex_init(&LOCK_xid_cache, MY_MUTEX_INIT_FAST);
 
2521
  return hash_init(&xid_cache, &my_charset_bin, 100, 0, 0,
 
2522
                   xid_get_hash_key, xid_free_hash, 0) != 0;
 
2523
}
 
2524
 
 
2525
void xid_cache_free()
 
2526
{
 
2527
  if (hash_inited(&xid_cache))
 
2528
  {
 
2529
    hash_free(&xid_cache);
 
2530
    pthread_mutex_destroy(&LOCK_xid_cache);
 
2531
  }
 
2532
}
 
2533
 
 
2534
XID_STATE *xid_cache_search(XID *xid)
 
2535
{
 
2536
  pthread_mutex_lock(&LOCK_xid_cache);
 
2537
  XID_STATE *res=(XID_STATE *)hash_search(&xid_cache, xid->key(), xid->key_length());
 
2538
  pthread_mutex_unlock(&LOCK_xid_cache);
 
2539
  return res;
 
2540
}
 
2541
 
 
2542
 
 
2543
bool xid_cache_insert(XID *xid, enum xa_states xa_state)
 
2544
{
 
2545
  XID_STATE *xs;
 
2546
  my_bool res;
 
2547
  pthread_mutex_lock(&LOCK_xid_cache);
 
2548
  if (hash_search(&xid_cache, xid->key(), xid->key_length()))
 
2549
    res=0;
 
2550
  else if (!(xs=(XID_STATE *)my_malloc(sizeof(*xs), MYF(MY_WME))))
 
2551
    res=1;
 
2552
  else
 
2553
  {
 
2554
    xs->xa_state=xa_state;
 
2555
    xs->xid.set(xid);
 
2556
    xs->in_thd=0;
 
2557
    res=my_hash_insert(&xid_cache, (uchar*)xs);
 
2558
  }
 
2559
  pthread_mutex_unlock(&LOCK_xid_cache);
 
2560
  return res;
 
2561
}
 
2562
 
 
2563
 
 
2564
bool xid_cache_insert(XID_STATE *xid_state)
 
2565
{
 
2566
  pthread_mutex_lock(&LOCK_xid_cache);
 
2567
  DBUG_ASSERT(hash_search(&xid_cache, xid_state->xid.key(),
 
2568
                          xid_state->xid.key_length())==0);
 
2569
  my_bool res=my_hash_insert(&xid_cache, (uchar*)xid_state);
 
2570
  pthread_mutex_unlock(&LOCK_xid_cache);
 
2571
  return res;
 
2572
}
 
2573
 
 
2574
 
 
2575
void xid_cache_delete(XID_STATE *xid_state)
 
2576
{
 
2577
  pthread_mutex_lock(&LOCK_xid_cache);
 
2578
  hash_delete(&xid_cache, (uchar *)xid_state);
 
2579
  pthread_mutex_unlock(&LOCK_xid_cache);
 
2580
}
 
2581
 
 
2582
/*
 
2583
  Implementation of interface to write rows to the binary log through the
 
2584
  thread.  The thread is responsible for writing the rows it has
 
2585
  inserted/updated/deleted.
 
2586
*/
 
2587
 
 
2588
#ifndef MYSQL_CLIENT
 
2589
 
 
2590
/*
 
2591
  Template member function for ensuring that there is an rows log
 
2592
  event of the apropriate type before proceeding.
 
2593
 
 
2594
  PRE CONDITION:
 
2595
    - Events of type 'RowEventT' have the type code 'type_code'.
 
2596
    
 
2597
  POST CONDITION:
 
2598
    If a non-NULL pointer is returned, the pending event for thread 'thd' will
 
2599
    be an event of type 'RowEventT' (which have the type code 'type_code')
 
2600
    will either empty or have enough space to hold 'needed' bytes.  In
 
2601
    addition, the columns bitmap will be correct for the row, meaning that
 
2602
    the pending event will be flushed if the columns in the event differ from
 
2603
    the columns suppled to the function.
 
2604
 
 
2605
  RETURNS
 
2606
    If no error, a non-NULL pending event (either one which already existed or
 
2607
    the newly created one).
 
2608
    If error, NULL.
 
2609
 */
 
2610
 
 
2611
template <class RowsEventT> Rows_log_event* 
 
2612
THD::binlog_prepare_pending_rows_event(TABLE* table, uint32 serv_id,
 
2613
                                       size_t needed,
 
2614
                                       bool is_transactional,
 
2615
                                       RowsEventT *hint __attribute__((unused)))
 
2616
{
 
2617
  DBUG_ENTER("binlog_prepare_pending_rows_event");
 
2618
  /* Pre-conditions */
 
2619
  DBUG_ASSERT(table->s->table_map_id != ~0UL);
 
2620
 
 
2621
  /* Fetch the type code for the RowsEventT template parameter */
 
2622
  int const type_code= RowsEventT::TYPE_CODE;
 
2623
 
 
2624
  /*
 
2625
    There is no good place to set up the transactional data, so we
 
2626
    have to do it here.
 
2627
  */
 
2628
  if (binlog_setup_trx_data())
 
2629
    DBUG_RETURN(NULL);
 
2630
 
 
2631
  Rows_log_event* pending= binlog_get_pending_rows_event();
 
2632
 
 
2633
  if (unlikely(pending && !pending->is_valid()))
 
2634
    DBUG_RETURN(NULL);
 
2635
 
 
2636
  /*
 
2637
    Check if the current event is non-NULL and a write-rows
 
2638
    event. Also check if the table provided is mapped: if it is not,
 
2639
    then we have switched to writing to a new table.
 
2640
    If there is no pending event, we need to create one. If there is a pending
 
2641
    event, but it's not about the same table id, or not of the same type
 
2642
    (between Write, Update and Delete), or not the same affected columns, or
 
2643
    going to be too big, flush this event to disk and create a new pending
 
2644
    event.
 
2645
 
 
2646
    The last test is necessary for the Cluster injector to work
 
2647
    correctly. The reason is that the Cluster can inject two write
 
2648
    rows with different column bitmaps if there is an insert followed
 
2649
    by an update in the same transaction, and these are grouped into a
 
2650
    single epoch/transaction when fed to the injector.
 
2651
 
 
2652
    TODO: Fix the code so that the last test can be removed.
 
2653
  */
 
2654
  if (!pending ||
 
2655
      pending->server_id != serv_id || 
 
2656
      pending->get_table_id() != table->s->table_map_id ||
 
2657
      pending->get_type_code() != type_code || 
 
2658
      pending->get_data_size() + needed > opt_binlog_rows_event_max_size ||
 
2659
      !bitmap_cmp(pending->get_cols(), table->write_set))
 
2660
    {
 
2661
    /* Create a new RowsEventT... */
 
2662
    Rows_log_event* const
 
2663
        ev= new RowsEventT(this, table, table->s->table_map_id,
 
2664
                           is_transactional);
 
2665
    if (unlikely(!ev))
 
2666
      DBUG_RETURN(NULL);
 
2667
    ev->server_id= serv_id; // I don't like this, it's too easy to forget.
 
2668
    /*
 
2669
      flush the pending event and replace it with the newly created
 
2670
      event...
 
2671
    */
 
2672
    if (unlikely(mysql_bin_log.flush_and_set_pending_rows_event(this, ev)))
 
2673
    {
 
2674
      delete ev;
 
2675
      DBUG_RETURN(NULL);
 
2676
    }
 
2677
 
 
2678
    DBUG_RETURN(ev);               /* This is the new pending event */
 
2679
  }
 
2680
  DBUG_RETURN(pending);        /* This is the current pending event */
 
2681
}
 
2682
 
 
2683
#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
 
2684
/*
 
2685
  Instantiate the versions we need, we have -fno-implicit-template as
 
2686
  compiling option.
 
2687
*/
 
2688
template Rows_log_event*
 
2689
THD::binlog_prepare_pending_rows_event(TABLE*, uint32, size_t, bool,
 
2690
                                       Write_rows_log_event*);
 
2691
 
 
2692
template Rows_log_event*
 
2693
THD::binlog_prepare_pending_rows_event(TABLE*, uint32, size_t, bool,
 
2694
                                       Delete_rows_log_event *);
 
2695
 
 
2696
template Rows_log_event* 
 
2697
THD::binlog_prepare_pending_rows_event(TABLE*, uint32, size_t, bool,
 
2698
                                       Update_rows_log_event *);
 
2699
#endif
 
2700
 
 
2701
namespace {
 
2702
  /**
 
2703
     Class to handle temporary allocation of memory for row data.
 
2704
 
 
2705
     The responsibilities of the class is to provide memory for
 
2706
     packing one or two rows of packed data (depending on what
 
2707
     constructor is called).
 
2708
 
 
2709
     In order to make the allocation more efficient for "simple" rows,
 
2710
     i.e., rows that do not contain any blobs, a pointer to the
 
2711
     allocated memory is of memory is stored in the table structure
 
2712
     for simple rows.  If memory for a table containing a blob field
 
2713
     is requested, only memory for that is allocated, and subsequently
 
2714
     released when the object is destroyed.
 
2715
 
 
2716
   */
 
2717
  class Row_data_memory {
 
2718
  public:
 
2719
    /**
 
2720
      Build an object to keep track of a block-local piece of memory
 
2721
      for storing a row of data.
 
2722
 
 
2723
      @param table
 
2724
      Table where the pre-allocated memory is stored.
 
2725
 
 
2726
      @param length
 
2727
      Length of data that is needed, if the record contain blobs.
 
2728
     */
 
2729
    Row_data_memory(TABLE *table, size_t const len1)
 
2730
      : m_memory(0)
 
2731
    {
 
2732
#ifndef DBUG_OFF
 
2733
      m_alloc_checked= FALSE;
 
2734
#endif
 
2735
      allocate_memory(table, len1);
 
2736
      m_ptr[0]= has_memory() ? m_memory : 0;
 
2737
      m_ptr[1]= 0;
 
2738
    }
 
2739
 
 
2740
    Row_data_memory(TABLE *table, size_t const len1, size_t const len2)
 
2741
      : m_memory(0)
 
2742
    {
 
2743
#ifndef DBUG_OFF
 
2744
      m_alloc_checked= FALSE;
 
2745
#endif
 
2746
      allocate_memory(table, len1 + len2);
 
2747
      m_ptr[0]= has_memory() ? m_memory        : 0;
 
2748
      m_ptr[1]= has_memory() ? m_memory + len1 : 0;
 
2749
    }
 
2750
 
 
2751
    ~Row_data_memory()
 
2752
    {
 
2753
      if (m_memory != 0 && m_release_memory_on_destruction)
 
2754
        my_free((uchar*) m_memory, MYF(MY_WME));
 
2755
    }
 
2756
 
 
2757
    /**
 
2758
       Is there memory allocated?
 
2759
 
 
2760
       @retval true There is memory allocated
 
2761
       @retval false Memory allocation failed
 
2762
     */
 
2763
    bool has_memory() const {
 
2764
#ifndef DBUG_OFF
 
2765
      m_alloc_checked= TRUE;
 
2766
#endif
 
2767
      return m_memory != 0;
 
2768
    }
 
2769
 
 
2770
    uchar *slot(uint s)
 
2771
    {
 
2772
      DBUG_ASSERT(s < sizeof(m_ptr)/sizeof(*m_ptr));
 
2773
      DBUG_ASSERT(m_ptr[s] != 0);
 
2774
      DBUG_ASSERT(m_alloc_checked == TRUE);
 
2775
      return m_ptr[s];
 
2776
    }
 
2777
 
 
2778
  private:
 
2779
    void allocate_memory(TABLE *const table, size_t const total_length)
 
2780
    {
 
2781
      if (table->s->blob_fields == 0)
 
2782
      {
 
2783
        /*
 
2784
          The maximum length of a packed record is less than this
 
2785
          length. We use this value instead of the supplied length
 
2786
          when allocating memory for records, since we don't know how
 
2787
          the memory will be used in future allocations.
 
2788
 
 
2789
          Since table->s->reclength is for unpacked records, we have
 
2790
          to add two bytes for each field, which can potentially be
 
2791
          added to hold the length of a packed field.
 
2792
        */
 
2793
        size_t const maxlen= table->s->reclength + 2 * table->s->fields;
 
2794
 
 
2795
        /*
 
2796
          Allocate memory for two records if memory hasn't been
 
2797
          allocated. We allocate memory for two records so that it can
 
2798
          be used when processing update rows as well.
 
2799
        */
 
2800
        if (table->write_row_record == 0)
 
2801
          table->write_row_record=
 
2802
            (uchar *) alloc_root(&table->mem_root, 2 * maxlen);
 
2803
        m_memory= table->write_row_record;
 
2804
        m_release_memory_on_destruction= FALSE;
 
2805
      }
 
2806
      else
 
2807
      {
 
2808
        m_memory= (uchar *) my_malloc(total_length, MYF(MY_WME));
 
2809
        m_release_memory_on_destruction= TRUE;
 
2810
      }
 
2811
    }
 
2812
 
 
2813
#ifndef DBUG_OFF
 
2814
    mutable bool m_alloc_checked;
 
2815
#endif
 
2816
    bool m_release_memory_on_destruction;
 
2817
    uchar *m_memory;
 
2818
    uchar *m_ptr[2];
 
2819
  };
 
2820
}
 
2821
 
 
2822
 
 
2823
int THD::binlog_write_row(TABLE* table, bool is_trans, 
 
2824
                          uchar const *record) 
 
2825
 
2826
  DBUG_ASSERT(current_stmt_binlog_row_based && mysql_bin_log.is_open());
 
2827
 
 
2828
  /*
 
2829
    Pack records into format for transfer. We are allocating more
 
2830
    memory than needed, but that doesn't matter.
 
2831
  */
 
2832
  Row_data_memory memory(table, max_row_length(table, record));
 
2833
  if (!memory.has_memory())
 
2834
    return HA_ERR_OUT_OF_MEM;
 
2835
 
 
2836
  uchar *row_data= memory.slot(0);
 
2837
 
 
2838
  size_t const len= pack_row(table, table->write_set, row_data, record);
 
2839
 
 
2840
  Rows_log_event* const ev=
 
2841
    binlog_prepare_pending_rows_event(table, server_id, len, is_trans,
 
2842
                                      static_cast<Write_rows_log_event*>(0));
 
2843
 
 
2844
  if (unlikely(ev == 0))
 
2845
    return HA_ERR_OUT_OF_MEM;
 
2846
 
 
2847
  return ev->add_row_data(row_data, len);
 
2848
}
 
2849
 
 
2850
int THD::binlog_update_row(TABLE* table, bool is_trans,
 
2851
                           const uchar *before_record,
 
2852
                           const uchar *after_record)
 
2853
 
2854
  DBUG_ASSERT(current_stmt_binlog_row_based && mysql_bin_log.is_open());
 
2855
 
 
2856
  size_t const before_maxlen = max_row_length(table, before_record);
 
2857
  size_t const after_maxlen  = max_row_length(table, after_record);
 
2858
 
 
2859
  Row_data_memory row_data(table, before_maxlen, after_maxlen);
 
2860
  if (!row_data.has_memory())
 
2861
    return HA_ERR_OUT_OF_MEM;
 
2862
 
 
2863
  uchar *before_row= row_data.slot(0);
 
2864
  uchar *after_row= row_data.slot(1);
 
2865
 
 
2866
  size_t const before_size= pack_row(table, table->read_set, before_row,
 
2867
                                        before_record);
 
2868
  size_t const after_size= pack_row(table, table->write_set, after_row,
 
2869
                                       after_record);
 
2870
 
 
2871
  /*
 
2872
    Don't print debug messages when running valgrind since they can
 
2873
    trigger false warnings.
 
2874
   */
 
2875
#ifndef HAVE_purify
 
2876
  DBUG_DUMP("before_record", before_record, table->s->reclength);
 
2877
  DBUG_DUMP("after_record",  after_record, table->s->reclength);
 
2878
  DBUG_DUMP("before_row",    before_row, before_size);
 
2879
  DBUG_DUMP("after_row",     after_row, after_size);
 
2880
#endif
 
2881
 
 
2882
  Rows_log_event* const ev=
 
2883
    binlog_prepare_pending_rows_event(table, server_id,
 
2884
                                      before_size + after_size, is_trans,
 
2885
                                      static_cast<Update_rows_log_event*>(0));
 
2886
 
 
2887
  if (unlikely(ev == 0))
 
2888
    return HA_ERR_OUT_OF_MEM;
 
2889
 
 
2890
  return
 
2891
    ev->add_row_data(before_row, before_size) ||
 
2892
    ev->add_row_data(after_row, after_size);
 
2893
}
 
2894
 
 
2895
int THD::binlog_delete_row(TABLE* table, bool is_trans, 
 
2896
                           uchar const *record)
 
2897
 
2898
  DBUG_ASSERT(current_stmt_binlog_row_based && mysql_bin_log.is_open());
 
2899
 
 
2900
  /* 
 
2901
     Pack records into format for transfer. We are allocating more
 
2902
     memory than needed, but that doesn't matter.
 
2903
  */
 
2904
  Row_data_memory memory(table, max_row_length(table, record));
 
2905
  if (unlikely(!memory.has_memory()))
 
2906
    return HA_ERR_OUT_OF_MEM;
 
2907
 
 
2908
  uchar *row_data= memory.slot(0);
 
2909
 
 
2910
  DBUG_DUMP("table->read_set", (uchar*) table->read_set->bitmap, (table->s->fields + 7) / 8);
 
2911
  size_t const len= pack_row(table, table->read_set, row_data, record);
 
2912
 
 
2913
  Rows_log_event* const ev=
 
2914
    binlog_prepare_pending_rows_event(table, server_id, len, is_trans,
 
2915
                                      static_cast<Delete_rows_log_event*>(0));
 
2916
 
 
2917
  if (unlikely(ev == 0))
 
2918
    return HA_ERR_OUT_OF_MEM;
 
2919
 
 
2920
  return ev->add_row_data(row_data, len);
 
2921
}
 
2922
 
 
2923
 
 
2924
int THD::binlog_flush_pending_rows_event(bool stmt_end)
 
2925
{
 
2926
  DBUG_ENTER("THD::binlog_flush_pending_rows_event");
 
2927
  /*
 
2928
    We shall flush the pending event even if we are not in row-based
 
2929
    mode: it might be the case that we left row-based mode before
 
2930
    flushing anything (e.g., if we have explicitly locked tables).
 
2931
   */
 
2932
  if (!mysql_bin_log.is_open())
 
2933
    DBUG_RETURN(0);
 
2934
 
 
2935
  /*
 
2936
    Mark the event as the last event of a statement if the stmt_end
 
2937
    flag is set.
 
2938
  */
 
2939
  int error= 0;
 
2940
  if (Rows_log_event *pending= binlog_get_pending_rows_event())
 
2941
  {
 
2942
    if (stmt_end)
 
2943
    {
 
2944
      pending->set_flags(Rows_log_event::STMT_END_F);
 
2945
      pending->flags|= LOG_EVENT_UPDATE_TABLE_MAP_VERSION_F;
 
2946
      binlog_table_maps= 0;
 
2947
    }
 
2948
 
 
2949
    error= mysql_bin_log.flush_and_set_pending_rows_event(this, 0);
 
2950
  }
 
2951
 
 
2952
  DBUG_RETURN(error);
 
2953
}
 
2954
 
 
2955
 
 
2956
/*
 
2957
  Member function that will log query, either row-based or
 
2958
  statement-based depending on the value of the 'current_stmt_binlog_row_based'
 
2959
  the value of the 'qtype' flag.
 
2960
 
 
2961
  This function should be called after the all calls to ha_*_row()
 
2962
  functions have been issued, but before tables are unlocked and
 
2963
  closed.
 
2964
 
 
2965
  OBSERVE
 
2966
    There shall be no writes to any system table after calling
 
2967
    binlog_query(), so these writes has to be moved to before the call
 
2968
    of binlog_query() for correct functioning.
 
2969
 
 
2970
    This is necessesary not only for RBR, but the master might crash
 
2971
    after binlogging the query but before changing the system tables.
 
2972
    This means that the slave and the master are not in the same state
 
2973
    (after the master has restarted), so therefore we have to
 
2974
    eliminate this problem.
 
2975
 
 
2976
  RETURN VALUE
 
2977
    Error code, or 0 if no error.
 
2978
*/
 
2979
int THD::binlog_query(THD::enum_binlog_query_type qtype, char const *query_arg,
 
2980
                      ulong query_len, bool is_trans, bool suppress_use,
 
2981
                      THD::killed_state killed_status_arg)
 
2982
{
 
2983
  DBUG_ENTER("THD::binlog_query");
 
2984
  DBUG_PRINT("enter", ("qtype: %d  query: '%s'", qtype, query_arg));
 
2985
  DBUG_ASSERT(query_arg && mysql_bin_log.is_open());
 
2986
 
 
2987
  if (int error= binlog_flush_pending_rows_event(TRUE))
 
2988
    DBUG_RETURN(error);
 
2989
 
 
2990
  /*
 
2991
    If we are in statement mode and trying to log an unsafe statement,
 
2992
    we should print a warning.
 
2993
  */
 
2994
  if (lex->is_stmt_unsafe() &&
 
2995
      variables.binlog_format == BINLOG_FORMAT_STMT)
 
2996
  {
 
2997
    DBUG_ASSERT(this->query != NULL);
 
2998
    push_warning(this, MYSQL_ERROR::WARN_LEVEL_WARN,
 
2999
                 ER_BINLOG_UNSAFE_STATEMENT,
 
3000
                 ER(ER_BINLOG_UNSAFE_STATEMENT));
 
3001
    if (!(binlog_flags & BINLOG_FLAG_UNSAFE_STMT_PRINTED))
 
3002
    {
 
3003
      char warn_buf[MYSQL_ERRMSG_SIZE];
 
3004
      my_snprintf(warn_buf, MYSQL_ERRMSG_SIZE, "%s Statement: %s",
 
3005
                  ER(ER_BINLOG_UNSAFE_STATEMENT), this->query);
 
3006
      sql_print_warning(warn_buf);
 
3007
      binlog_flags|= BINLOG_FLAG_UNSAFE_STMT_PRINTED;
 
3008
    }
 
3009
  }
 
3010
 
 
3011
  switch (qtype) {
 
3012
  case THD::ROW_QUERY_TYPE:
 
3013
    if (current_stmt_binlog_row_based)
 
3014
      DBUG_RETURN(0);
 
3015
    /* Otherwise, we fall through */
 
3016
  case THD::MYSQL_QUERY_TYPE:
 
3017
    /*
 
3018
      Using this query type is a conveniece hack, since we have been
 
3019
      moving back and forth between using RBR for replication of
 
3020
      system tables and not using it.
 
3021
 
 
3022
      Make sure to change in check_table_binlog_row_based() according
 
3023
      to how you treat this.
 
3024
    */
 
3025
  case THD::STMT_QUERY_TYPE:
 
3026
    /*
 
3027
      The MYSQL_LOG::write() function will set the STMT_END_F flag and
 
3028
      flush the pending rows event if necessary.
 
3029
     */
 
3030
    {
 
3031
      Query_log_event qinfo(this, query_arg, query_len, is_trans, suppress_use,
 
3032
                            killed_status_arg);
 
3033
      qinfo.flags|= LOG_EVENT_UPDATE_TABLE_MAP_VERSION_F;
 
3034
      /*
 
3035
        Binlog table maps will be irrelevant after a Query_log_event
 
3036
        (they are just removed on the slave side) so after the query
 
3037
        log event is written to the binary log, we pretend that no
 
3038
        table maps were written.
 
3039
       */
 
3040
      int error= mysql_bin_log.write(&qinfo);
 
3041
      binlog_table_maps= 0;
 
3042
      DBUG_RETURN(error);
 
3043
    }
 
3044
    break;
 
3045
 
 
3046
  case THD::QUERY_TYPE_COUNT:
 
3047
  default:
 
3048
    DBUG_ASSERT(0 <= qtype && qtype < QUERY_TYPE_COUNT);
 
3049
  }
 
3050
  DBUG_RETURN(0);
 
3051
}
 
3052
 
 
3053
bool Discrete_intervals_list::append(ulonglong start, ulonglong val,
 
3054
                                 ulonglong incr)
 
3055
{
 
3056
  DBUG_ENTER("Discrete_intervals_list::append");
 
3057
  /* first, see if this can be merged with previous */
 
3058
  if ((head == NULL) || tail->merge_if_contiguous(start, val, incr))
 
3059
  {
 
3060
    /* it cannot, so need to add a new interval */
 
3061
    Discrete_interval *new_interval= new Discrete_interval(start, val, incr);
 
3062
    DBUG_RETURN(append(new_interval));
 
3063
  }
 
3064
  DBUG_RETURN(0);
 
3065
}
 
3066
 
 
3067
bool Discrete_intervals_list::append(Discrete_interval *new_interval)
 
3068
{
 
3069
  DBUG_ENTER("Discrete_intervals_list::append");
 
3070
  if (unlikely(new_interval == NULL))
 
3071
    DBUG_RETURN(1);
 
3072
  DBUG_PRINT("info",("adding new auto_increment interval"));
 
3073
  if (head == NULL)
 
3074
    head= current= new_interval;
 
3075
  else
 
3076
    tail->next= new_interval;
 
3077
  tail= new_interval;
 
3078
  elements++;
 
3079
  DBUG_RETURN(0);
 
3080
}
 
3081
 
 
3082
#endif /* !defined(MYSQL_CLIENT) */