~drizzle-trunk/drizzle/development

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