~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/session.cc

  • Committer: Brian Aker
  • Date: 2009-02-20 22:48:37 UTC
  • Revision ID: brian@tangent.org-20090220224837-fw5wrf46n4ru3e6a
First pass of stripping uint

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 2000-2006 MySQL AB
2
 
 
3
 
   This program is free software; you can redistribute it and/or modify
4
 
   it under the terms of the GNU General Public License as published by
5
 
   the Free Software Foundation; version 2 of the License.
6
 
 
7
 
   This program is distributed in the hope that it will be useful,
8
 
   but WITHOUT ANY WARRANTY; without even the implied warranty of
9
 
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
 
   GNU General Public License for more details.
11
 
 
12
 
   You should have received a copy of the GNU General Public License
13
 
   along with this program; if not, write to the Free Software
14
 
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
 
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
 
3
 *
 
4
 *  Copyright (C) 2008 Sun Microsystems
 
5
 *
 
6
 *  This program is free software; you can redistribute it and/or modify
 
7
 *  it under the terms of the GNU General Public License as published by
 
8
 *  the Free Software Foundation; version 2 of the License.
 
9
 *
 
10
 *  This program is distributed in the hope that it will be useful,
 
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 *  GNU General Public License for more details.
 
14
 *
 
15
 *  You should have received a copy of the GNU General Public License
 
16
 *  along with this program; if not, write to the Free Software
 
17
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
18
 */
15
19
 
16
20
 
17
21
/*****************************************************************************
18
22
**
19
 
** This file implements classes defined in sql_class.h
 
23
** This file implements classes defined in session.h
20
24
** Especially the classes to handle a result from a select
21
25
**
22
26
*****************************************************************************/
23
27
#include <drizzled/server_includes.h>
24
 
#include "rpl_rli.h"
25
 
#include "rpl_record.h"
26
 
#include "log_event.h"
 
28
#include <drizzled/session.h>
27
29
#include <sys/stat.h>
28
 
#include <mysys/thr_alarm.h>
29
30
#include <mysys/mysys_err.h>
30
 
#include <drizzled/drizzled_error_messages.h>
 
31
#include <drizzled/error.h>
 
32
#include <drizzled/query_id.h>
 
33
#include <drizzled/data_home.h>
 
34
#include <drizzled/sql_base.h>
 
35
#include <drizzled/lock.h>
 
36
#include <drizzled/item/cache.h>
 
37
#include <drizzled/item/float.h>
 
38
#include <drizzled/item/return_int.h>
 
39
#include <drizzled/item/empty_string.h>
 
40
#include <drizzled/show.h>
 
41
#include <drizzled/plugin_scheduling.h>
31
42
 
 
43
extern scheduling_st thread_scheduler;
32
44
/*
33
45
  The following is used to initialise Table_ident with a internal
34
46
  table name
36
48
char internal_table_name[2]= "*";
37
49
char empty_c_string[1]= {0};    /* used for not defined db */
38
50
 
39
 
const char * const THD::DEFAULT_WHERE= "field list";
 
51
const char * const Session::DEFAULT_WHERE= "field list";
 
52
extern pthread_key_t THR_Session;
 
53
extern pthread_key_t THR_Mem_root;
40
54
 
41
55
 
42
56
/*****************************************************************************
55
69
template class List_iterator<Alter_column>;
56
70
#endif
57
71
 
 
72
 
58
73
/****************************************************************************
59
74
** User variables
60
75
****************************************************************************/
61
76
 
62
77
extern "C" unsigned char *get_var_key(user_var_entry *entry, size_t *length,
63
 
                              bool not_used __attribute__((unused)))
 
78
                              bool )
64
79
{
65
80
  *length= entry->name.length;
66
81
  return (unsigned char*) entry->name.str;
85
100
  Construct an (almost) deep copy of this key. Only those
86
101
  elements that are known to never change are not copied.
87
102
  If out of memory, a partial copy is returned and an error is set
88
 
  in THD.
 
103
  in Session.
89
104
*/
90
105
 
91
106
Key::Key(const Key &rhs, MEM_ROOT *mem_root)
102
117
  Construct an (almost) deep copy of this foreign key. Only those
103
118
  elements that are known to never change are not copied.
104
119
  If out of memory, a partial copy is returned and an error is set
105
 
  in THD.
 
120
  in Session.
106
121
*/
107
122
 
108
123
Foreign_key::Foreign_key(const Foreign_key &rhs, MEM_ROOT *mem_root)
183
198
}
184
199
 
185
200
 
 
201
/*
 
202
  Check if the foreign key options are compatible with columns
 
203
  on which the FK is created.
 
204
 
 
205
  RETURN
 
206
    0   Key valid
 
207
    1   Key invalid
 
208
*/
 
209
bool Foreign_key::validate(List<Create_field> &table_fields)
 
210
{
 
211
  Create_field  *sql_field;
 
212
  Key_part_spec *column;
 
213
  List_iterator<Key_part_spec> cols(columns);
 
214
  List_iterator<Create_field> it(table_fields);
 
215
  while ((column= cols++))
 
216
  {
 
217
    it.rewind();
 
218
    while ((sql_field= it++) &&
 
219
           my_strcasecmp(system_charset_info,
 
220
                         column->field_name.str,
 
221
                         sql_field->field_name)) {}
 
222
    if (!sql_field)
 
223
    {
 
224
      my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), column->field_name.str);
 
225
      return true;
 
226
    }
 
227
    if (type == Key::FOREIGN_KEY && sql_field->vcol_info)
 
228
    {
 
229
      if (delete_opt == FK_OPTION_SET_NULL)
 
230
      {
 
231
        my_error(ER_WRONG_FK_OPTION_FOR_VIRTUAL_COLUMN, MYF(0),
 
232
                 "ON DELETE SET NULL");
 
233
        return true;
 
234
      }
 
235
      if (update_opt == FK_OPTION_SET_NULL)
 
236
      {
 
237
        my_error(ER_WRONG_FK_OPTION_FOR_VIRTUAL_COLUMN, MYF(0),
 
238
                 "ON UPDATE SET NULL");
 
239
        return true;
 
240
      }
 
241
      if (update_opt == FK_OPTION_CASCADE)
 
242
      {
 
243
        my_error(ER_WRONG_FK_OPTION_FOR_VIRTUAL_COLUMN, MYF(0),
 
244
                 "ON UPDATE CASCADE");
 
245
        return true;
 
246
      }
 
247
    }
 
248
  }
 
249
  return false;
 
250
}
 
251
 
 
252
 
186
253
/****************************************************************************
187
254
** Thread specific functions
188
255
****************************************************************************/
200
267
extern "C" int mysql_tmpfile(const char *prefix)
201
268
{
202
269
  char filename[FN_REFLEN];
203
 
  File fd = create_temp_file(filename, mysql_tmpdir, prefix,
204
 
                             O_CREAT | O_EXCL | O_RDWR | O_TEMPORARY,
 
270
  File fd = create_temp_file(filename, drizzle_tmpdir, prefix,
 
271
                             O_CREAT | O_EXCL | O_RDWR,
205
272
                             MYF(MY_WME));
206
273
  if (fd >= 0) {
207
 
    /*
208
 
      This can be removed once the following bug is fixed:
209
 
      Bug #28903  create_temp_file() doesn't honor O_TEMPORARY option
210
 
                  (file not removed) (Unix)
211
 
    */
212
274
    unlink(filename);
213
275
  }
214
276
 
217
279
 
218
280
 
219
281
extern "C"
220
 
int thd_in_lock_tables(const THD *thd)
221
 
{
222
 
  return test(thd->in_lock_tables);
223
 
}
224
 
 
225
 
 
226
 
extern "C"
227
 
int thd_tablespace_op(const THD *thd)
228
 
{
229
 
  return test(thd->tablespace_op);
230
 
}
231
 
 
232
 
 
233
 
extern "C"
234
 
const char *set_thd_proc_info(THD *thd, const char *info,
235
 
                              const char *calling_function __attribute__((unused)),
236
 
                              const char *calling_file __attribute__((unused)),
237
 
                              const unsigned int calling_line __attribute__((unused)))
238
 
{
239
 
  const char *old_info= thd->get_proc_info();
240
 
  thd->set_proc_info(info);
241
 
  return old_info;
242
 
}
243
 
 
244
 
extern "C"
245
 
void **thd_ha_data(const THD *thd, const struct handlerton *hton)
246
 
{
247
 
  return (void **) &thd->ha_data[hton->slot].ha_ptr;
248
 
}
249
 
 
250
 
extern "C"
251
 
int64_t thd_test_options(const THD *thd, int64_t test_options)
252
 
{
253
 
  return thd->options & test_options;
254
 
}
255
 
 
256
 
extern "C"
257
 
int thd_sql_command(const THD *thd)
258
 
{
259
 
  return (int) thd->lex->sql_command;
260
 
}
261
 
 
262
 
extern "C"
263
 
int thd_tx_isolation(const THD *thd)
264
 
{
265
 
  return (int) thd->variables.tx_isolation;
266
 
}
267
 
 
268
 
extern "C"
269
 
void thd_inc_row_count(THD *thd)
270
 
{
271
 
  thd->row_count++;
272
 
}
273
 
 
274
 
/**
275
 
  Clear this diagnostics area. 
 
282
int session_in_lock_tables(const Session *session)
 
283
{
 
284
  return test(session->in_lock_tables);
 
285
}
 
286
 
 
287
 
 
288
extern "C"
 
289
int session_tablespace_op(const Session *session)
 
290
{
 
291
  return test(session->tablespace_op);
 
292
}
 
293
 
 
294
 
 
295
/**
 
296
   Set the process info field of the Session structure.
 
297
 
 
298
   This function is used by plug-ins. Internally, the
 
299
   Session::set_proc_info() function should be used.
 
300
 
 
301
   @see Session::set_proc_info
 
302
 */
 
303
extern "C" void
 
304
set_session_proc_info(Session *session, const char *info)
 
305
{
 
306
  session->set_proc_info(info);
 
307
}
 
308
 
 
309
extern "C"
 
310
const char *get_session_proc_info(Session *session)
 
311
{
 
312
  return session->get_proc_info();
 
313
}
 
314
 
 
315
extern "C"
 
316
void **session_ha_data(const Session *session, const struct handlerton *hton)
 
317
{
 
318
  return (void **) &session->ha_data[hton->slot].ha_ptr;
 
319
}
 
320
 
 
321
extern "C"
 
322
int64_t session_test_options(const Session *session, int64_t test_options)
 
323
{
 
324
  return session->options & test_options;
 
325
}
 
326
 
 
327
extern "C"
 
328
int session_sql_command(const Session *session)
 
329
{
 
330
  return (int) session->lex->sql_command;
 
331
}
 
332
 
 
333
extern "C"
 
334
int session_tx_isolation(const Session *session)
 
335
{
 
336
  return (int) session->variables.tx_isolation;
 
337
}
 
338
 
 
339
extern "C"
 
340
void session_inc_row_count(Session *session)
 
341
{
 
342
  session->row_count++;
 
343
}
 
344
 
 
345
/**
 
346
  Clear this diagnostics area.
276
347
 
277
348
  Normally called at the end of a statement.
278
349
*/
300
371
*/
301
372
 
302
373
void
303
 
Diagnostics_area::set_ok_status(THD *thd, ha_rows affected_rows_arg,
 
374
Diagnostics_area::set_ok_status(Session *session, ha_rows affected_rows_arg,
304
375
                                uint64_t last_insert_id_arg,
305
376
                                const char *message_arg)
306
377
{
313
384
    return;
314
385
  /** Only allowed to report success if has not yet reported an error */
315
386
 
316
 
  m_server_status= thd->server_status;
317
 
  m_total_warn_count= thd->total_warn_count;
 
387
  m_server_status= session->server_status;
 
388
  m_total_warn_count= session->total_warn_count;
318
389
  m_affected_rows= affected_rows_arg;
319
390
  m_last_insert_id= last_insert_id_arg;
320
391
  if (message_arg)
321
 
    strmake(m_message, message_arg, sizeof(m_message) - 1);
 
392
    strncpy(m_message, message_arg, sizeof(m_message) - 1);
322
393
  else
323
394
    m_message[0]= '\0';
324
395
  m_status= DA_OK;
330
401
*/
331
402
 
332
403
void
333
 
Diagnostics_area::set_eof_status(THD *thd)
 
404
Diagnostics_area::set_eof_status(Session *session)
334
405
{
335
406
  /** Only allowed to report eof if has not yet reported an error */
336
407
 
342
413
  if (is_error() || is_disabled())
343
414
    return;
344
415
 
345
 
  m_server_status= thd->server_status;
 
416
  m_server_status= session->server_status;
346
417
  /*
347
418
    If inside a stored procedure, do not return the total
348
419
    number of warnings, since they are not available to the client
349
420
    anyway.
350
421
  */
351
 
  m_total_warn_count= thd->total_warn_count;
 
422
  m_total_warn_count= session->total_warn_count;
352
423
 
353
424
  m_status= DA_EOF;
354
425
}
358
429
*/
359
430
 
360
431
void
361
 
Diagnostics_area::set_error_status(THD *thd __attribute__((unused)),
 
432
Diagnostics_area::set_error_status(Session *,
362
433
                                   uint32_t sql_errno_arg,
363
434
                                   const char *message_arg)
364
435
{
376
447
    return;
377
448
 
378
449
  m_sql_errno= sql_errno_arg;
379
 
  strmake(m_message, message_arg, sizeof(m_message) - 1);
 
450
  strncpy(m_message, message_arg, sizeof(m_message) - 1);
380
451
 
381
452
  m_status= DA_ERROR;
382
453
}
398
469
}
399
470
 
400
471
 
401
 
THD::THD()
 
472
Session::Session()
402
473
   :Statement(&main_lex, &main_mem_root,
403
474
              /* statement id */ 0),
404
 
   Open_tables_state(refresh_version), rli_fake(0),
 
475
   Open_tables_state(refresh_version),
405
476
   lock_id(&main_lock_id),
406
 
   user_time(0), in_sub_stmt(0),
407
 
   binlog_table_maps(0), binlog_flags(0UL),
 
477
   user_time(0),
408
478
   arg_of_last_insert_id_function(false),
409
479
   first_successful_insert_id_in_prev_stmt(0),
410
 
   first_successful_insert_id_in_prev_stmt_for_binlog(0),
411
480
   first_successful_insert_id_in_cur_stmt(0),
412
 
   stmt_depends_on_first_successful_insert_id_in_prev_stmt(false),
413
481
   global_read_lock(0),
414
482
   is_fatal_error(0),
415
483
   transaction_rollback_request(0),
416
484
   is_fatal_sub_stmt_error(0),
417
 
   rand_used(0),
418
 
   time_zone_used(0),
419
485
   in_lock_tables(0),
420
 
   bootstrap(0),
421
486
   derived_tables_processing(false),
422
 
   m_lip(NULL)
 
487
   m_lip(NULL),
 
488
   scheduler(0)
423
489
{
424
490
  ulong tmp;
425
491
 
431
497
  init_sql_alloc(&main_mem_root, ALLOC_ROOT_MIN_BLOCK_SIZE, 0);
432
498
  thread_stack= 0;
433
499
  catalog= (char*)"std"; // the only catalog we have for now
434
 
  main_security_ctx.init();
435
 
  security_ctx= &main_security_ctx;
436
500
  some_tables_deleted=no_errors=password= 0;
437
 
  query_start_used= 0;
438
501
  count_cuted_fields= CHECK_FIELD_IGNORE;
439
502
  killed= NOT_KILLED;
440
503
  col_access=0;
441
 
  is_slave_error= thread_specific_used= false;
 
504
  thread_specific_used= false;
442
505
  hash_clear(&handler_tables_hash);
443
506
  tmp_table=0;
444
507
  used_tables=0;
446
509
  limit_found_rows= 0;
447
510
  row_count_func= -1;
448
511
  statement_id_counter= 0UL;
449
 
  // Must be reset to handle error with THD's created for init of mysqld
 
512
  // Must be reset to handle error with Session's created for init of mysqld
450
513
  lex->current_select= 0;
451
514
  start_time=(time_t) 0;
452
515
  start_utime= 0L;
453
516
  utime_after_lock= 0L;
454
 
  current_linfo =  0;
455
 
  slave_thread = 0;
456
517
  memset(&variables, 0, sizeof(variables));
457
518
  thread_id= 0;
458
 
  one_shot_set= 0;
459
519
  file_id = 0;
460
520
  query_id= 0;
461
521
  warn_id= 0;
462
522
  db_charset= global_system_variables.collation_database;
463
523
  memset(ha_data, 0, sizeof(ha_data));
 
524
  replication_data= 0;
464
525
  mysys_var=0;
465
 
  binlog_evt_union.do_union= false;
466
 
  dbug_sentry=THD_SENTRY_MAGIC;
467
 
  net.vio=0;
 
526
  dbug_sentry=Session_SENTRY_MAGIC;
 
527
  net.vio= 0;
468
528
  client_capabilities= 0;                       // minimalistic client
469
529
  system_thread= NON_SYSTEM_THREAD;
470
530
  cleanup_done= abort_on_warning= no_warnings_for_error= 0;
471
531
  peer_port= 0;                                 // For SHOW PROCESSLIST
472
 
  transaction.m_pending_rows_event= 0;
473
532
  transaction.on= 1;
474
533
  pthread_mutex_init(&LOCK_delete, MY_MUTEX_INIT_FAST);
475
534
 
476
535
  /* Variables with default values */
477
536
  proc_info="login";
478
 
  where= THD::DEFAULT_WHERE;
 
537
  where= Session::DEFAULT_WHERE;
479
538
  server_id = ::server_id;
480
 
  slave_net = 0;
481
539
  command=COM_CONNECT;
482
540
  *scramble= '\0';
483
541
 
489
547
            (hash_get_key) get_var_key,
490
548
            (hash_free_key) free_user_var, 0);
491
549
 
492
 
  /* For user vars replication*/
493
 
  if (opt_bin_log)
494
 
    my_init_dynamic_array(&user_var_events,
495
 
                          sizeof(BINLOG_USER_VAR_EVENT *), 16, 16);
496
 
  else
497
 
    memset(&user_var_events, 0, sizeof(user_var_events));
498
 
 
499
550
  /* Protocol */
500
551
  protocol= &protocol_text;                     // Default protocol
501
552
  protocol_text.init(this);
502
553
 
 
554
  const Query_id& local_query_id= Query_id::get_query_id();
503
555
  tablespace_op= false;
504
556
  tmp= sql_rnd();
505
 
  randominit(&rand, tmp + (ulong) &rand, tmp + (ulong) ::global_query_id);
 
557
  drizzleclient_drizzleclient_randominit(&rand, tmp + (ulong) &rand, tmp + local_query_id.value());
506
558
  substitute_null_with_insert_id = false;
507
559
  thr_lock_info_init(&lock_info); /* safety: will be reset after start */
508
560
  thr_lock_owner_init(&main_lock_id, &lock_info);
511
563
}
512
564
 
513
565
 
514
 
void THD::push_internal_handler(Internal_error_handler *handler)
 
566
void Session::push_internal_handler(Internal_error_handler *handler)
515
567
{
516
568
  /*
517
569
    TODO: The current implementation is limited to 1 handler at a time only.
518
 
    THD and sp_rcontext need to be modified to use a common handler stack.
 
570
    Session and sp_rcontext need to be modified to use a common handler stack.
519
571
  */
520
572
  assert(m_internal_handler == NULL);
521
573
  m_internal_handler= handler;
522
574
}
523
575
 
524
576
 
525
 
bool THD::handle_error(uint32_t sql_errno, const char *message,
 
577
bool Session::handle_error(uint32_t sql_errno, const char *message,
526
578
                       DRIZZLE_ERROR::enum_warning_level level)
527
579
{
528
580
  if (m_internal_handler)
534
586
}
535
587
 
536
588
 
537
 
void THD::pop_internal_handler()
 
589
void Session::pop_internal_handler()
538
590
{
539
591
  assert(m_internal_handler != NULL);
540
592
  m_internal_handler= NULL;
541
593
}
542
594
 
543
 
extern "C"
544
 
void *thd_alloc(DRIZZLE_THD thd, unsigned int size)
545
 
{
546
 
  return thd->alloc(size);
547
 
}
548
 
 
549
 
extern "C"
550
 
void *thd_calloc(DRIZZLE_THD thd, unsigned int size)
551
 
{
552
 
  return thd->calloc(size);
553
 
}
554
 
 
555
 
extern "C"
556
 
char *thd_strdup(DRIZZLE_THD thd, const char *str)
557
 
{
558
 
  return thd->strdup(str);
559
 
}
560
 
 
561
 
extern "C"
562
 
char *thd_strmake(DRIZZLE_THD thd, const char *str, unsigned int size)
563
 
{
564
 
  return thd->strmake(str, size);
565
 
}
566
 
 
567
 
extern "C"
568
 
LEX_STRING *thd_make_lex_string(THD *thd, LEX_STRING *lex_str,
569
 
                                const char *str, unsigned int size,
570
 
                                int allocate_lex_string)
571
 
{
572
 
  return thd->make_lex_string(lex_str, str, size,
573
 
                              (bool) allocate_lex_string);
574
 
}
575
 
 
576
 
extern "C"
577
 
void *thd_memdup(DRIZZLE_THD thd, const void* str, unsigned int size)
578
 
{
579
 
  return thd->memdup(str, size);
580
 
}
581
 
 
582
 
extern "C"
583
 
void thd_get_xid(const DRIZZLE_THD thd, DRIZZLE_XID *xid)
584
 
{
585
 
  *xid = *(DRIZZLE_XID *) &thd->transaction.xid_state.xid;
586
 
}
 
595
#if defined(__cplusplus)
 
596
extern "C" {
 
597
#endif
 
598
 
 
599
void *session_alloc(Session *session, unsigned int size)
 
600
{
 
601
  return session->alloc(size);
 
602
}
 
603
 
 
604
void *session_calloc(Session *session, unsigned int size)
 
605
{
 
606
  return session->calloc(size);
 
607
}
 
608
 
 
609
char *session_strdup(Session *session, const char *str)
 
610
{
 
611
  return session->strdup(str);
 
612
}
 
613
 
 
614
char *session_strmake(Session *session, const char *str, unsigned int size)
 
615
{
 
616
  return session->strmake(str, size);
 
617
}
 
618
 
 
619
void *session_memdup(Session *session, const void* str, unsigned int size)
 
620
{
 
621
  return session->memdup(str, size);
 
622
}
 
623
 
 
624
void session_get_xid(const Session *session, DRIZZLE_XID *xid)
 
625
{
 
626
  *xid = *(DRIZZLE_XID *) &session->transaction.xid_state.xid;
 
627
}
 
628
 
 
629
#if defined(__cplusplus)
 
630
}
 
631
#endif
587
632
 
588
633
/*
589
634
  Init common variables that has to be reset on start and on change_user
590
635
*/
591
636
 
592
 
void THD::init(void)
 
637
void Session::init(void)
593
638
{
594
639
  pthread_mutex_lock(&LOCK_global_system_variables);
595
 
  plugin_thdvar_init(this);
596
 
  variables.time_format= date_time_format_copy((THD*) 0,
 
640
  plugin_sessionvar_init(this);
 
641
  variables.time_format= date_time_format_copy((Session*) 0,
597
642
                                               variables.time_format);
598
 
  variables.date_format= date_time_format_copy((THD*) 0,
 
643
  variables.date_format= date_time_format_copy((Session*) 0,
599
644
                                               variables.date_format);
600
 
  variables.datetime_format= date_time_format_copy((THD*) 0,
 
645
  variables.datetime_format= date_time_format_copy((Session*) 0,
601
646
                                                   variables.datetime_format);
602
647
  /*
603
648
    variables= global_system_variables above has reset
607
652
  variables.pseudo_thread_id= thread_id;
608
653
  pthread_mutex_unlock(&LOCK_global_system_variables);
609
654
  server_status= SERVER_STATUS_AUTOCOMMIT;
610
 
  options= thd_startup_options;
 
655
  options= session_startup_options;
611
656
 
612
657
  if (variables.max_join_size == HA_POS_ERROR)
613
658
    options |= OPTION_BIG_SELECTS;
616
661
 
617
662
  transaction.all.modified_non_trans_table= transaction.stmt.modified_non_trans_table= false;
618
663
  open_options=ha_open_options;
619
 
  update_lock_default= (variables.low_priority_updates ?
620
 
                        TL_WRITE_LOW_PRIORITY :
621
 
                        TL_WRITE);
 
664
  update_lock_default= TL_WRITE;
622
665
  session_tx_isolation= (enum_tx_isolation) variables.tx_isolation;
623
666
  warn_list.empty();
624
667
  memset(warn_count, 0, sizeof(warn_count));
625
668
  total_warn_count= 0;
626
669
  update_charset();
627
 
  reset_current_stmt_binlog_row_based();
628
670
  memset(&status_var, 0, sizeof(status_var));
629
671
}
630
672
 
631
673
 
632
674
/*
633
 
  Init THD for query processing.
 
675
  Init Session for query processing.
634
676
  This has to be called once before we call mysql_parse.
635
 
  See also comments in sql_class.h.
 
677
  See also comments in session.h.
636
678
*/
637
679
 
638
 
void THD::init_for_queries()
 
680
void Session::init_for_queries()
639
681
{
640
 
  set_time(); 
 
682
  set_time();
641
683
  ha_enable_transaction(this,true);
642
684
 
643
685
  reset_root_defaults(mem_root, variables.query_alloc_block_size,
646
688
                      variables.trans_alloc_block_size,
647
689
                      variables.trans_prealloc_size);
648
690
  transaction.xid_state.xid.null();
649
 
  transaction.xid_state.in_thd=1;
 
691
  transaction.xid_state.in_session=1;
650
692
}
651
693
 
652
694
 
653
695
/* Do operations that may take a long time */
654
696
 
655
 
void THD::cleanup(void)
 
697
void Session::cleanup(void)
656
698
{
657
699
  assert(cleanup_done == 0);
658
700
 
673
715
    close_thread_tables(this);
674
716
  }
675
717
  mysql_ha_cleanup(this);
676
 
  delete_dynamic(&user_var_events);
677
718
  hash_free(&user_vars);
678
 
  close_temporary_tables(this);
 
719
  close_temporary_tables();
679
720
  free((char*) variables.time_format);
680
721
  free((char*) variables.date_format);
681
722
  free((char*) variables.datetime_format);
682
 
  
 
723
 
683
724
  if (global_read_lock)
684
725
    unlock_global_read_lock(this);
685
726
 
687
728
  return;
688
729
}
689
730
 
690
 
THD::~THD()
 
731
Session::~Session()
691
732
{
692
 
  THD_CHECK_SENTRY(this);
693
 
  /* Ensure that no one is using THD */
 
733
  Session_CHECK_SENTRY(this);
 
734
  /* Ensure that no one is using Session */
694
735
  pthread_mutex_lock(&LOCK_delete);
695
736
  pthread_mutex_unlock(&LOCK_delete);
696
737
  add_to_status(&global_status_var, &status_var);
698
739
  /* Close connection */
699
740
  if (net.vio)
700
741
  {
701
 
    net_close(&net);
702
 
    net_end(&net);
 
742
    drizzleclient_net_close(&net);
 
743
    drizzleclient_net_end(&net);
703
744
  }
704
745
  if (!cleanup_done)
705
746
    cleanup();
706
747
 
707
748
  ha_close_connection(this);
708
 
  plugin_thdvar_cleanup(this);
 
749
  plugin_sessionvar_cleanup(this);
709
750
 
710
 
  main_security_ctx.destroy();
711
751
  if (db)
712
752
  {
713
753
    free(db);
717
757
  free_root(&transaction.mem_root,MYF(0));
718
758
  mysys_var=0;                                  // Safety (shouldn't be needed)
719
759
  pthread_mutex_destroy(&LOCK_delete);
720
 
  dbug_sentry= THD_SENTRY_GONE;
721
 
  if (rli_fake)
722
 
  {
723
 
    delete rli_fake;
724
 
    rli_fake= NULL;
725
 
  }
726
 
  
 
760
  dbug_sentry= Session_SENTRY_GONE;
 
761
 
727
762
  free_root(&main_mem_root, MYF(0));
 
763
  pthread_setspecific(THR_Session,  0);
728
764
  return;
729
765
}
730
766
 
762
798
    to_var       add to this array
763
799
    from_var     from this array
764
800
    dec_var      minus this array
765
 
  
 
801
 
766
802
  NOTE
767
803
    This function assumes that all variables are long/ulong.
768
804
*/
780
816
}
781
817
 
782
818
 
783
 
void THD::awake(THD::killed_state state_to_set)
 
819
void Session::awake(Session::killed_state state_to_set)
784
820
{
785
 
  THD_CHECK_SENTRY(this);
786
 
  safe_mutex_assert_owner(&LOCK_delete); 
 
821
  Session_CHECK_SENTRY(this);
 
822
  safe_mutex_assert_owner(&LOCK_delete);
787
823
 
788
824
  killed= state_to_set;
789
 
  if (state_to_set != THD::KILL_QUERY)
 
825
  if (state_to_set != Session::KILL_QUERY)
790
826
  {
791
 
    thr_alarm_kill(thread_id);
792
 
    if (!slave_thread)
793
 
      thread_scheduler.post_kill_notification(this);
 
827
    thread_scheduler.post_kill_notification(this);
794
828
  }
795
829
  if (mysys_var)
796
830
  {
813
847
      current_cond and current_mutex are 0), then the victim will not get
814
848
      a signal and it may wait "forever" on the cond (until
815
849
      we issue a second KILL or the status it's waiting for happens).
816
 
      It's true that we have set its thd->killed but it may not
 
850
      It's true that we have set its session->killed but it may not
817
851
      see it immediately and so may have time to reach the cond_wait().
818
852
    */
819
853
    if (mysys_var->current_cond && mysys_var->current_mutex)
832
866
  sql_alloc() and the structure for the net buffer
833
867
*/
834
868
 
835
 
bool THD::store_globals()
 
869
bool Session::store_globals()
836
870
{
837
871
  /*
838
872
    Assert that thread_stack is initialized: it's necessary to be able
840
874
  */
841
875
  assert(thread_stack);
842
876
 
843
 
  if (my_pthread_setspecific_ptr(THR_THD,  this) ||
844
 
      my_pthread_setspecific_ptr(THR_MALLOC, &mem_root))
 
877
  if (pthread_setspecific(THR_Session,  this) ||
 
878
      pthread_setspecific(THR_Mem_root, &mem_root))
845
879
    return 1;
846
880
  mysys_var=my_thread_var;
847
881
  /*
848
882
    Let mysqld define the thread id (not mysys)
849
 
    This allows us to move THD to different threads if needed.
 
883
    This allows us to move Session to different threads if needed.
850
884
  */
851
885
  mysys_var->id= thread_id;
852
886
  real_id= pthread_self();                      // For debugging
853
887
 
854
888
  /*
855
 
    We have to call thr_lock_info_init() again here as THD may have been
 
889
    We have to call thr_lock_info_init() again here as Session may have been
856
890
    created in another thread
857
891
  */
858
892
  thr_lock_info_init(&lock_info);
864
898
  Cleanup after query.
865
899
 
866
900
  SYNOPSIS
867
 
    THD::cleanup_after_query()
 
901
    Session::cleanup_after_query()
868
902
 
869
903
  DESCRIPTION
870
904
    This function is used to reset thread data to its default state.
876
910
    slave.
877
911
*/
878
912
 
879
 
void THD::cleanup_after_query()
 
913
void Session::cleanup_after_query()
880
914
{
881
915
  /*
882
 
    Reset rand_used so that detection of calls to rand() will save random 
 
916
    Reset rand_used so that detection of calls to rand() will save random
883
917
    seeds if needed by the slave.
884
 
 
885
 
    Do not reset rand_used if inside a stored function or trigger because 
886
 
    only the call to these operations is logged. Thus only the calling 
887
 
    statement needs to detect rand() calls made by its substatements. These
888
 
    substatements must not set rand_used to 0 because it would remove the
889
 
    detection of rand() by the calling statement. 
890
918
  */
891
 
  if (!in_sub_stmt) /* stored functions and triggers are a special case */
892
919
  {
893
920
    /* Forget those values, for next binlogger: */
894
 
    stmt_depends_on_first_successful_insert_id_in_prev_stmt= 0;
895
921
    auto_inc_intervals_in_cur_stmt_for_binlog.empty();
896
 
    rand_used= 0;
897
922
  }
898
923
  if (first_successful_insert_id_in_cur_stmt > 0)
899
924
  {
900
925
    /* set what LAST_INSERT_ID() will return */
901
 
    first_successful_insert_id_in_prev_stmt= 
 
926
    first_successful_insert_id_in_prev_stmt=
902
927
      first_successful_insert_id_in_cur_stmt;
903
928
    first_successful_insert_id_in_cur_stmt= 0;
904
929
    substitute_null_with_insert_id= true;
907
932
  /* Free Items that were created during this execution */
908
933
  free_items();
909
934
  /* Reset where. */
910
 
  where= THD::DEFAULT_WHERE;
 
935
  where= Session::DEFAULT_WHERE;
911
936
}
912
937
 
913
938
 
921
946
                              instead of using lex_str value
922
947
  @return  NULL on failure, or pointer to the LEX_STRING object
923
948
*/
924
 
LEX_STRING *THD::make_lex_string(LEX_STRING *lex_str,
 
949
LEX_STRING *Session::make_lex_string(LEX_STRING *lex_str,
925
950
                                 const char* str, uint32_t length,
926
951
                                 bool allocate_lex_string)
927
952
{
955
980
        In this case to->str will point to 0 and to->length will be 0.
956
981
*/
957
982
 
958
 
bool THD::convert_string(LEX_STRING *to, const CHARSET_INFO * const to_cs,
 
983
bool Session::convert_string(LEX_STRING *to, const CHARSET_INFO * const to_cs,
959
984
                         const char *from, uint32_t from_length,
960
985
                         const CHARSET_INFO * const from_cs)
961
986
{
977
1002
  Convert string from source character set to target character set inplace.
978
1003
 
979
1004
  SYNOPSIS
980
 
    THD::convert_string
 
1005
    Session::convert_string
981
1006
 
982
1007
  DESCRIPTION
983
 
    Convert string using convert_buffer - buffer for character set 
 
1008
    Convert string using convert_buffer - buffer for character set
984
1009
    conversion shared between all protocols.
985
1010
 
986
1011
  RETURN
988
1013
   !0   out of memory
989
1014
*/
990
1015
 
991
 
bool THD::convert_string(String *s, const CHARSET_INFO * const from_cs,
 
1016
bool Session::convert_string(String *s, const CHARSET_INFO * const from_cs,
992
1017
                         const CHARSET_INFO * const to_cs)
993
1018
{
994
1019
  uint32_t dummy_errors;
1009
1034
  Update some cache variables when character set changes
1010
1035
*/
1011
1036
 
1012
 
void THD::update_charset()
 
1037
void Session::update_charset()
1013
1038
{
1014
1039
  uint32_t not_used;
1015
1040
  charset_is_system_charset= !String::needs_conversion(0,charset(),
1016
1041
                                                       system_charset_info,
1017
1042
                                                       &not_used);
1018
 
  charset_is_collation_connection= 
1019
 
    !String::needs_conversion(0,charset(),variables.collation_connection,
 
1043
  charset_is_collation_connection=
 
1044
    !String::needs_conversion(0,charset(),variables.getCollation(),
1020
1045
                              &not_used);
1021
 
  charset_is_character_set_filesystem= 
 
1046
  charset_is_character_set_filesystem=
1022
1047
    !String::needs_conversion(0, charset(),
1023
1048
                              variables.character_set_filesystem, &not_used);
1024
1049
}
1039
1064
 
1040
1065
/* add table to list of changed in transaction tables */
1041
1066
 
1042
 
void THD::add_changed_table(Table *table)
 
1067
void Session::add_changed_table(Table *table)
1043
1068
{
1044
1069
  assert((options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) &&
1045
1070
              table->file->has_transactions());
1049
1074
}
1050
1075
 
1051
1076
 
1052
 
void THD::add_changed_table(const char *key, long key_length)
 
1077
void Session::add_changed_table(const char *key, long key_length)
1053
1078
{
1054
1079
  CHANGED_TableList **prev_changed = &transaction.changed_tables;
1055
1080
  CHANGED_TableList *curr = transaction.changed_tables;
1081
1106
}
1082
1107
 
1083
1108
 
1084
 
CHANGED_TableList* THD::changed_table_dup(const char *key, long key_length)
 
1109
CHANGED_TableList* Session::changed_table_dup(const char *key, long key_length)
1085
1110
{
1086
 
  CHANGED_TableList* new_table = 
 
1111
  CHANGED_TableList* new_table =
1087
1112
    (CHANGED_TableList*) trans_alloc(ALIGN_SIZE(sizeof(CHANGED_TableList))+
1088
1113
                                      key_length + 1);
1089
1114
  if (!new_table)
1102
1127
}
1103
1128
 
1104
1129
 
1105
 
int THD::send_explain_fields(select_result *result)
 
1130
int Session::send_explain_fields(select_result *result)
1106
1131
{
1107
1132
  List<Item> field_list;
1108
1133
  Item *item;
1147
1172
  Item **place;
1148
1173
  Item *old_value;
1149
1174
  /* Placement new was hidden by `new' in ilink (TODO: check): */
1150
 
  static void *operator new(size_t size __attribute__((unused)),
 
1175
  static void *operator new(size_t ,
1151
1176
                            void *mem)
1152
1177
    { return mem; }
1153
 
  static void operator delete(void *ptr __attribute__((unused)),
1154
 
                              size_t size __attribute__((unused)))
 
1178
  static void operator delete(void *,
 
1179
                              size_t )
1155
1180
    {}
1156
 
  static void operator delete(void *ptr __attribute__((unused)),
1157
 
                              void *mem __attribute__((unused)))
 
1181
  static void operator delete(void *,
 
1182
                              void *)
1158
1183
    { /* never called */ }
1159
1184
};
1160
1185
 
1162
1187
/*
1163
1188
  Register an item tree tree transformation, performed by the query
1164
1189
  optimizer. We need a pointer to runtime_memroot because it may be !=
1165
 
  thd->mem_root (this may no longer be a true statement)
 
1190
  session->mem_root (this may no longer be a true statement)
1166
1191
*/
1167
1192
 
1168
 
void THD::nocheck_register_item_tree_change(Item **place, Item *old_value,
 
1193
void Session::nocheck_register_item_tree_change(Item **place, Item *old_value,
1169
1194
                                            MEM_ROOT *runtime_memroot)
1170
1195
{
1171
1196
  Item_change_record *change;
1178
1203
  if (change_mem == 0)
1179
1204
  {
1180
1205
    /*
1181
 
      OOM, thd->fatal_error() is called by the error handler of the
 
1206
      OOM, session->fatal_error() is called by the error handler of the
1182
1207
      memroot. Just return.
1183
1208
    */
1184
1209
    return;
1190
1215
}
1191
1216
 
1192
1217
 
1193
 
void THD::rollback_item_tree_changes()
 
1218
void Session::rollback_item_tree_changes()
1194
1219
{
1195
1220
  I_List_iterator<Item_change_record> it(change_list);
1196
1221
  Item_change_record *change;
1203
1228
}
1204
1229
 
1205
1230
 
1206
 
/*****************************************************************************
1207
 
** Functions to provide a interface to select results
1208
 
*****************************************************************************/
1209
 
 
1210
 
select_result::select_result()
1211
 
{
1212
 
  thd=current_thd;
1213
 
}
1214
 
 
1215
 
void select_result::send_error(uint32_t errcode,const char *err)
1216
 
{
1217
 
  my_message(errcode, err, MYF(0));
1218
 
}
1219
 
 
1220
 
 
1221
 
void select_result::cleanup()
1222
 
{
1223
 
  /* do nothing */
1224
 
}
1225
 
 
1226
 
bool select_result::check_simple_select() const
1227
 
{
1228
 
  my_error(ER_SP_BAD_CURSOR_QUERY, MYF(0));
1229
 
  return true;
1230
 
}
1231
 
 
1232
 
 
1233
 
static String default_line_term("\n",default_charset_info);
1234
 
static String default_escaped("\\",default_charset_info);
1235
 
static String default_field_term("\t",default_charset_info);
1236
 
 
1237
 
sql_exchange::sql_exchange(char *name, bool flag,
1238
 
                           enum enum_filetype filetype_arg)
1239
 
  :file_name(name), opt_enclosed(0), dumpfile(flag), skip_lines(0)
1240
 
{
1241
 
  filetype= filetype_arg;
1242
 
  field_term= &default_field_term;
1243
 
  enclosed=   line_start= &my_empty_string;
1244
 
  line_term=  &default_line_term;
1245
 
  escaped=    &default_escaped;
1246
 
  cs= NULL;
1247
 
}
1248
 
 
1249
 
bool select_send::send_fields(List<Item> &list, uint32_t flags)
1250
 
{
1251
 
  bool res;
1252
 
  if (!(res= thd->protocol->send_fields(&list, flags)))
1253
 
    is_result_set_started= 1;
1254
 
  return res;
1255
 
}
1256
 
 
1257
 
void select_send::abort()
1258
 
{
1259
 
  return;
1260
 
}
1261
 
 
1262
 
 
1263
 
/** 
1264
 
  Cleanup an instance of this class for re-use
1265
 
  at next execution of a prepared statement/
1266
 
  stored procedure statement.
1267
 
*/
1268
 
 
1269
 
void select_send::cleanup()
1270
 
{
1271
 
  is_result_set_started= false;
1272
 
}
1273
 
 
1274
 
/* Send data to client. Returns 0 if ok */
1275
 
 
1276
 
bool select_send::send_data(List<Item> &items)
1277
 
{
1278
 
  if (unit->offset_limit_cnt)
1279
 
  {                                             // using limit offset,count
1280
 
    unit->offset_limit_cnt--;
1281
 
    return 0;
1282
 
  }
1283
 
 
1284
 
  /*
1285
 
    We may be passing the control from mysqld to the client: release the
1286
 
    InnoDB adaptive hash S-latch to avoid thread deadlocks if it was reserved
1287
 
    by thd
1288
 
  */
1289
 
  ha_release_temporary_latches(thd);
1290
 
 
1291
 
  List_iterator_fast<Item> li(items);
1292
 
  Protocol *protocol= thd->protocol;
1293
 
  char buff[MAX_FIELD_WIDTH];
1294
 
  String buffer(buff, sizeof(buff), &my_charset_bin);
1295
 
 
1296
 
  protocol->prepare_for_resend();
1297
 
  Item *item;
1298
 
  while ((item=li++))
1299
 
  {
1300
 
    if (item->send(protocol, &buffer))
1301
 
    {
1302
 
      protocol->free();                         // Free used buffer
1303
 
      my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
1304
 
      break;
1305
 
    }
1306
 
  }
1307
 
  thd->sent_row_count++;
1308
 
  if (thd->is_error())
1309
 
  {
1310
 
    protocol->remove_last_row();
1311
 
    return(1);
1312
 
  }
1313
 
  if (thd->vio_ok())
1314
 
    return(protocol->write());
1315
 
  return(0);
1316
 
}
1317
 
 
1318
 
bool select_send::send_eof()
1319
 
{
1320
 
  /* 
1321
 
    We may be passing the control from mysqld to the client: release the
1322
 
    InnoDB adaptive hash S-latch to avoid thread deadlocks if it was reserved
1323
 
    by thd 
1324
 
  */
1325
 
  ha_release_temporary_latches(thd);
1326
 
 
1327
 
  /* Unlock tables before sending packet to gain some speed */
1328
 
  if (thd->lock)
1329
 
  {
1330
 
    mysql_unlock_tables(thd, thd->lock);
1331
 
    thd->lock=0;
1332
 
  }
1333
 
  ::my_eof(thd);
1334
 
  is_result_set_started= 0;
1335
 
  return false;
1336
 
}
1337
 
 
1338
 
 
1339
1231
/************************************************************************
1340
1232
  Handling writing to file
1341
1233
************************************************************************/
1365
1257
      function, SELECT INTO has to have an own SQLCOM.
1366
1258
      TODO: split from SQLCOM_SELECT
1367
1259
    */
1368
 
    ::my_ok(thd,row_count);
 
1260
    session->my_ok(row_count);
1369
1261
  }
1370
1262
  file= -1;
1371
1263
  return error;
1402
1294
 
1403
1295
select_export::~select_export()
1404
1296
{
1405
 
  thd->sent_row_count=row_count;
 
1297
  session->sent_row_count=row_count;
1406
1298
}
1407
1299
 
1408
1300
 
1411
1303
 
1412
1304
  SYNOPSIS
1413
1305
    create_file()
1414
 
    thd                 Thread handle
 
1306
    session                     Thread handle
1415
1307
    path                File name
1416
1308
    exchange            Excange class
1417
1309
    cache               IO cache
1422
1314
*/
1423
1315
 
1424
1316
 
1425
 
static File create_file(THD *thd, char *path, sql_exchange *exchange,
1426
 
                        IO_CACHE *cache)
 
1317
static File create_file(Session *session, char *path, file_exchange *exchange, IO_CACHE *cache)
1427
1318
{
1428
1319
  File file;
1429
1320
  uint32_t option= MY_UNPACK_FILENAME | MY_RELATIVE_PATH;
1434
1325
 
1435
1326
  if (!dirname_length(exchange->file_name))
1436
1327
  {
1437
 
    strxnmov(path, FN_REFLEN-1, mysql_real_data_home, thd->db ? thd->db : "",
1438
 
             NULL);
 
1328
    strcpy(path, drizzle_real_data_home);
 
1329
    if (session->db)
 
1330
      strncat(path, session->db, FN_REFLEN-strlen(drizzle_real_data_home)-1);
1439
1331
    (void) fn_format(path, exchange->file_name, path, "", option);
1440
1332
  }
1441
1333
  else
1442
 
    (void) fn_format(path, exchange->file_name, mysql_real_data_home, "", option);
 
1334
    (void) fn_format(path, exchange->file_name, drizzle_real_data_home, "", option);
1443
1335
 
1444
1336
  if (opt_secure_file_priv &&
1445
1337
      strncmp(opt_secure_file_priv, path, strlen(opt_secure_file_priv)))
1465
1357
  if (init_io_cache(cache, file, 0L, WRITE_CACHE, 0L, 1, MYF(MY_WME)))
1466
1358
  {
1467
1359
    my_close(file, MYF(0));
1468
 
    my_delete(path, MYF(0));  // Delete file on error, it was just created 
 
1360
    my_delete(path, MYF(0));  // Delete file on error, it was just created
1469
1361
    return -1;
1470
1362
  }
1471
1363
  return file;
1473
1365
 
1474
1366
 
1475
1367
int
1476
 
select_export::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
 
1368
select_export::prepare(List<Item> &list, Select_Lex_Unit *u)
1477
1369
{
1478
1370
  bool blob_flag=0;
1479
1371
  bool string_results= false, non_string_results= false;
1480
1372
  unit= u;
1481
1373
  if ((uint) strlen(exchange->file_name) + NAME_LEN >= FN_REFLEN)
1482
 
    strmake(path,exchange->file_name,FN_REFLEN-1);
 
1374
    strncpy(path,exchange->file_name,FN_REFLEN-1);
1483
1375
 
1484
 
  if ((file= create_file(thd, path, exchange, &cache)) < 0)
1485
 
    return 1;
1486
1376
  /* Check if there is any blobs in data */
1487
1377
  {
1488
1378
    List_iterator_fast<Item> li(list);
1524
1414
      (exchange->opt_enclosed && non_string_results &&
1525
1415
       field_term_length && strchr(NUMERIC_CHARS, field_term_char)))
1526
1416
  {
1527
 
    push_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
1528
 
                 ER_AMBIGUOUS_FIELD_TERM, ER(ER_AMBIGUOUS_FIELD_TERM));
1529
 
    is_ambiguous_field_term= true;
 
1417
    my_error(ER_AMBIGUOUS_FIELD_TERM, MYF(0));
 
1418
    return 1;
1530
1419
  }
1531
 
  else
1532
 
    is_ambiguous_field_term= false;
 
1420
 
 
1421
  if ((file= create_file(session, path, exchange, &cache)) < 0)
 
1422
    return 1;
1533
1423
 
1534
1424
  return 0;
1535
1425
}
1603
1493
      {
1604
1494
        char *pos, *start, *end;
1605
1495
        const CHARSET_INFO * const res_charset= res->charset();
1606
 
        const CHARSET_INFO * const character_set_client= thd->variables.
1607
 
                                                            character_set_client;
 
1496
        const CHARSET_INFO * const character_set_client= default_charset_info;
 
1497
 
1608
1498
        bool check_second_byte= (res_charset == &my_charset_bin) &&
1609
1499
                                 character_set_client->
1610
1500
                                 escape_with_backslash_is_dangerous;
1611
1501
        assert(character_set_client->mbmaxlen == 2 ||
1612
 
                    !character_set_client->escape_with_backslash_is_dangerous);
 
1502
               !character_set_client->escape_with_backslash_is_dangerous);
1613
1503
        for (start=pos=(char*) res->ptr(),end=pos+used_length ;
1614
1504
             pos != end ;
1615
1505
             pos++)
1631
1521
            for the clients with character sets big5, cp932, gbk and sjis,
1632
1522
            which can have the escape character (0x5C "\" by default)
1633
1523
            as the second byte of a multi-byte sequence.
1634
 
            
 
1524
 
1635
1525
            If
1636
1526
            - pos[0] is a valid multi-byte head (e.g 0xEE) and
1637
1527
            - pos[1] is 0x00, which will be escaped as "\0",
1638
 
            
 
1528
 
1639
1529
            then we'll get "0xEE + 0x5C + 0x30" in the output file.
1640
 
            
 
1530
 
1641
1531
            If this file is later loaded using this sequence of commands:
1642
 
            
 
1532
 
1643
1533
            mysql> create table t1 (a varchar(128)) character set big5;
1644
1534
            mysql> LOAD DATA INFILE 'dump.txt' INTO Table t1;
1645
 
            
 
1535
 
1646
1536
            then 0x5C will be misinterpreted as the second byte
1647
1537
            of a multi-byte character "0xEE + 0x5C", instead of
1648
1538
            escape character for 0x00.
1649
 
            
 
1539
 
1650
1540
            To avoid this confusion, we'll escape the multi-byte
1651
1541
            head character too, so the sequence "0xEE + 0x00" will be
1652
1542
            dumped as "0x5C + 0xEE + 0x5C + 0x30".
1653
 
            
 
1543
 
1654
1544
            Note, in the condition below we only check if
1655
1545
            mbcharlen is equal to 2, because there are no
1656
1546
            character sets with mbmaxlen longer than 2
1735
1625
 
1736
1626
 
1737
1627
int
1738
 
select_dump::prepare(List<Item> &list __attribute__((unused)),
1739
 
                     SELECT_LEX_UNIT *u)
 
1628
select_dump::prepare(List<Item> &, Select_Lex_Unit *u)
1740
1629
{
1741
1630
  unit= u;
1742
 
  return (int) ((file= create_file(thd, path, exchange, &cache)) < 0);
 
1631
  return (int) ((file= create_file(session, path, exchange, &cache)) < 0);
1743
1632
}
1744
1633
 
1745
1634
 
1756
1645
    unit->offset_limit_cnt--;
1757
1646
    return(0);
1758
1647
  }
1759
 
  if (row_count++ > 1) 
 
1648
  if (row_count++ > 1)
1760
1649
  {
1761
1650
    my_message(ER_TOO_MANY_ROWS, ER(ER_TOO_MANY_ROWS), MYF(0));
1762
1651
    goto err;
1919
1808
     sortcmp(val1, val2, cache->collation.collation) < 0);
1920
1809
}
1921
1810
 
1922
 
bool select_exists_subselect::send_data(List<Item> &items __attribute__((unused)))
 
1811
bool select_exists_subselect::send_data(List<Item> &)
1923
1812
{
1924
1813
  Item_exists_subselect *it= (Item_exists_subselect *)item;
1925
1814
  if (unit->offset_limit_cnt)
1933
1822
}
1934
1823
 
1935
1824
 
1936
 
/***************************************************************************
1937
 
  Dump of select to variables
1938
 
***************************************************************************/
1939
 
 
1940
 
int select_dumpvar::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
1941
 
{
1942
 
  unit= u;
1943
 
  
1944
 
  if (var_list.elements != list.elements)
1945
 
  {
1946
 
    my_message(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT,
1947
 
               ER(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT), MYF(0));
1948
 
    return 1;
1949
 
  }               
1950
 
  return 0;
1951
 
}
1952
 
 
1953
 
 
1954
 
bool select_dumpvar::check_simple_select() const
1955
 
{
1956
 
  my_error(ER_SP_BAD_CURSOR_SELECT, MYF(0));
1957
 
  return true;
1958
 
}
1959
 
 
1960
 
 
1961
 
void select_dumpvar::cleanup()
1962
 
{
1963
 
  row_count= 0;
1964
 
}
1965
 
 
1966
 
 
1967
 
void Query_arena::free_items()
1968
 
{
1969
 
  Item *next;
1970
 
  /* This works because items are allocated with sql_alloc() */
1971
 
  for (; free_list; free_list= next)
1972
 
  {
1973
 
    next= free_list->next;
1974
 
    free_list->delete_self();
1975
 
  }
1976
 
  /* Postcondition: free_list is 0 */
1977
 
  return;
1978
 
}
1979
 
 
1980
 
 
1981
1825
/*
1982
1826
  Statement functions
1983
1827
*/
1999
1843
  Don't free mem_root, as mem_root is freed in the end of dispatch_command
2000
1844
  (once for any command).
2001
1845
*/
2002
 
void THD::end_statement()
 
1846
void Session::end_statement()
2003
1847
{
2004
1848
  /* Cleanup SQL processing state to reuse this statement in next query. */
2005
1849
  lex_end(lex);
2006
1850
}
2007
1851
 
2008
1852
 
2009
 
bool THD::copy_db_to(char **p_db, size_t *p_db_length)
 
1853
bool Session::copy_db_to(char **p_db, size_t *p_db_length)
2010
1854
{
2011
1855
  if (db == NULL)
2012
1856
  {
2019
1863
}
2020
1864
 
2021
1865
 
2022
 
bool select_dumpvar::send_data(List<Item> &items)
2023
 
{
2024
 
  List_iterator_fast<my_var> var_li(var_list);
2025
 
  List_iterator<Item> it(items);
2026
 
  Item *item;
2027
 
  my_var *mv;
2028
 
 
2029
 
  if (unit->offset_limit_cnt)
2030
 
  {                                             // using limit offset,count
2031
 
    unit->offset_limit_cnt--;
2032
 
    return(0);
2033
 
  }
2034
 
  if (row_count++) 
2035
 
  {
2036
 
    my_message(ER_TOO_MANY_ROWS, ER(ER_TOO_MANY_ROWS), MYF(0));
2037
 
    return(1);
2038
 
  }
2039
 
  while ((mv= var_li++) && (item= it++))
2040
 
  {
2041
 
    if (mv->local == 0)
2042
 
    {
2043
 
      Item_func_set_user_var *suv= new Item_func_set_user_var(mv->s, item);
2044
 
      suv->fix_fields(thd, 0);
2045
 
      suv->check(0);
2046
 
      suv->update();
2047
 
    }
2048
 
  }
2049
 
  return(thd->is_error());
2050
 
}
2051
 
 
2052
 
bool select_dumpvar::send_eof()
2053
 
{
2054
 
  if (! row_count)
2055
 
    push_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
2056
 
                 ER_SP_FETCH_NO_DATA, ER(ER_SP_FETCH_NO_DATA));
2057
 
  /*
2058
 
    In order to remember the value of affected rows for ROW_COUNT()
2059
 
    function, SELECT INTO has to have an own SQLCOM.
2060
 
    TODO: split from SQLCOM_SELECT
2061
 
  */
2062
 
  ::my_ok(thd,row_count);
2063
 
  return 0;
2064
 
}
2065
 
 
2066
1866
/****************************************************************************
2067
 
  TMP_TABLE_PARAM
 
1867
  Tmp_Table_Param
2068
1868
****************************************************************************/
2069
1869
 
2070
 
void TMP_TABLE_PARAM::init()
 
1870
void Tmp_Table_Param::init()
2071
1871
{
2072
1872
  field_count= sum_func_count= func_count= hidden_field_count= 0;
2073
1873
  group_parts= group_length= group_null_parts= 0;
2078
1878
  return;
2079
1879
}
2080
1880
 
2081
 
 
2082
 
void thd_increment_bytes_sent(ulong length)
2083
 
{
2084
 
  THD *thd=current_thd;
2085
 
  if (likely(thd != 0))
2086
 
  { /* current_thd==0 when close_connection() calls net_send_error() */
2087
 
    thd->status_var.bytes_sent+= length;
2088
 
  }
2089
 
}
2090
 
 
2091
 
 
2092
 
void thd_increment_bytes_received(ulong length)
2093
 
{
2094
 
  current_thd->status_var.bytes_received+= length;
2095
 
}
2096
 
 
2097
 
 
2098
 
void thd_increment_net_big_packet_count(ulong length)
2099
 
{
2100
 
  current_thd->status_var.net_big_packet_count+= length;
2101
 
}
2102
 
 
2103
 
void THD::send_kill_message() const
 
1881
void Tmp_Table_Param::cleanup(void)
 
1882
{
 
1883
  /* Fix for Intel compiler */
 
1884
  if (copy_field)
 
1885
  {
 
1886
    delete [] copy_field;
 
1887
    save_copy_field= copy_field= 0;
 
1888
  }
 
1889
}
 
1890
 
 
1891
 
 
1892
void session_increment_bytes_sent(ulong length)
 
1893
{
 
1894
  Session *session=current_session;
 
1895
  if (likely(session != 0))
 
1896
  { /* current_session==0 when close_connection() calls net_send_error() */
 
1897
    session->status_var.bytes_sent+= length;
 
1898
  }
 
1899
}
 
1900
 
 
1901
 
 
1902
void session_increment_bytes_received(ulong length)
 
1903
{
 
1904
  current_session->status_var.bytes_received+= length;
 
1905
}
 
1906
 
 
1907
 
 
1908
void session_increment_net_big_packet_count(ulong length)
 
1909
{
 
1910
  current_session->status_var.net_big_packet_count+= length;
 
1911
}
 
1912
 
 
1913
void Session::send_kill_message() const
2104
1914
{
2105
1915
  int err= killed_errno();
2106
1916
  if (err)
2107
1917
    my_message(err, ER(err), MYF(0));
2108
1918
}
2109
1919
 
2110
 
void THD::set_status_var_init()
 
1920
void Session::set_status_var_init()
2111
1921
{
2112
1922
  memset(&status_var, 0, sizeof(status_var));
2113
1923
}
2114
1924
 
2115
 
 
2116
 
void Security_context::init()
2117
 
{
2118
 
  user= ip= 0;
2119
 
}
2120
 
 
2121
 
 
2122
 
void Security_context::destroy()
2123
 
{
2124
 
  // If not pointer to constant
2125
 
  if (user)
2126
 
  {
2127
 
    free(user);
2128
 
    user= NULL;
2129
 
  }
2130
 
  if (ip)
2131
 
  {
2132
 
    free(ip);
2133
 
    ip= NULL;
2134
 
  }
2135
 
}
2136
 
 
2137
 
 
2138
1925
void Security_context::skip_grants()
2139
1926
{
2140
1927
  /* privileges for the user are unknown everything is allowed */
2149
1936
  access to mysql.proc table to find definitions of stored routines.
2150
1937
****************************************************************************/
2151
1938
 
2152
 
void THD::reset_n_backup_open_tables_state(Open_tables_state *backup)
 
1939
void Session::reset_n_backup_open_tables_state(Open_tables_state *backup)
2153
1940
{
2154
1941
  backup->set_open_tables_state(this);
2155
1942
  reset_open_tables_state();
2158
1945
}
2159
1946
 
2160
1947
 
2161
 
void THD::restore_backup_open_tables_state(Open_tables_state *backup)
 
1948
void Session::restore_backup_open_tables_state(Open_tables_state *backup)
2162
1949
{
2163
1950
  /*
2164
1951
    Before we will throw away current open tables state we want
2171
1958
  return;
2172
1959
}
2173
1960
 
 
1961
 
 
1962
bool Session::set_db(const char *new_db, size_t new_db_len)
 
1963
{
 
1964
  /* Do not reallocate memory if current chunk is big enough. */
 
1965
  if (db && new_db && db_length >= new_db_len)
 
1966
    memcpy(db, new_db, new_db_len+1);
 
1967
  else
 
1968
  {
 
1969
    if (db)
 
1970
      free(db);
 
1971
    if (new_db)
 
1972
    {
 
1973
      db= (char *)malloc(new_db_len + 1);
 
1974
      if (db != NULL)
 
1975
      {
 
1976
        memcpy(db, new_db, new_db_len);
 
1977
        db[new_db_len]= 0;
 
1978
      }
 
1979
    }
 
1980
    else
 
1981
      db= NULL;
 
1982
  }
 
1983
  db_length= db ? new_db_len : 0;
 
1984
  return new_db && !db;
 
1985
}
 
1986
 
 
1987
 
2174
1988
/**
2175
1989
  Check the killed state of a user thread
2176
 
  @param thd  user thread
 
1990
  @param session  user thread
2177
1991
  @retval 0 the user thread is active
2178
1992
  @retval 1 the user thread has been killed
2179
1993
*/
2180
 
extern "C" int thd_killed(const DRIZZLE_THD thd)
 
1994
extern "C" int session_killed(const Session *session)
2181
1995
{
2182
 
  return(thd->killed);
 
1996
  return(session->killed);
2183
1997
}
2184
1998
 
2185
1999
/**
2186
2000
  Return the thread id of a user thread
2187
 
  @param thd user thread
 
2001
  @param session user thread
2188
2002
  @return thread id
2189
2003
*/
2190
 
extern "C" unsigned long thd_get_thread_id(const DRIZZLE_THD thd)
2191
 
{
2192
 
  return((unsigned long)thd->thread_id);
2193
 
}
2194
 
 
2195
 
 
2196
 
#ifdef INNODB_COMPATIBILITY_HOOKS
2197
 
extern "C" const struct charset_info_st *thd_charset(DRIZZLE_THD thd)
2198
 
{
2199
 
  return(thd->charset());
2200
 
}
2201
 
 
2202
 
extern "C" char **thd_query(DRIZZLE_THD thd)
2203
 
{
2204
 
  return(&thd->query);
2205
 
}
2206
 
 
2207
 
extern "C" int thd_slave_thread(const DRIZZLE_THD thd)
2208
 
{
2209
 
  return(thd->slave_thread);
2210
 
}
2211
 
 
2212
 
extern "C" int thd_non_transactional_update(const DRIZZLE_THD thd)
2213
 
{
2214
 
  return(thd->transaction.all.modified_non_trans_table);
2215
 
}
2216
 
 
2217
 
extern "C" int thd_binlog_format(const DRIZZLE_THD thd)
2218
 
{
2219
 
  return (int) thd->variables.binlog_format;
2220
 
}
2221
 
 
2222
 
extern "C" void thd_mark_transaction_to_rollback(DRIZZLE_THD thd, bool all)
2223
 
{
2224
 
  mark_transaction_to_rollback(thd, all);
2225
 
}
2226
 
#endif // INNODB_COMPATIBILITY_HOOKS */
 
2004
extern "C" unsigned long session_get_thread_id(const Session *session)
 
2005
{
 
2006
  return((unsigned long)session->thread_id);
 
2007
}
 
2008
 
 
2009
 
 
2010
extern "C"
 
2011
LEX_STRING *session_make_lex_string(Session *session, LEX_STRING *lex_str,
 
2012
                                const char *str, unsigned int size,
 
2013
                                int allocate_lex_string)
 
2014
{
 
2015
  return session->make_lex_string(lex_str, str, size,
 
2016
                              (bool) allocate_lex_string);
 
2017
}
 
2018
 
 
2019
extern "C" const struct charset_info_st *session_charset(Session *session)
 
2020
{
 
2021
  return(session->charset());
 
2022
}
 
2023
 
 
2024
extern "C" char **session_query(Session *session)
 
2025
{
 
2026
  return(&session->query);
 
2027
}
 
2028
 
 
2029
extern "C" int session_non_transactional_update(const Session *session)
 
2030
{
 
2031
  return(session->transaction.all.modified_non_trans_table);
 
2032
}
 
2033
 
 
2034
extern "C" void session_mark_transaction_to_rollback(Session *session, bool all)
 
2035
{
 
2036
  mark_transaction_to_rollback(session, all);
 
2037
}
2227
2038
 
2228
2039
 
2229
2040
/**
2230
2041
  Mark transaction to rollback and mark error as fatal to a sub-statement.
2231
2042
 
2232
 
  @param  thd   Thread handle
 
2043
  @param  session   Thread handle
2233
2044
  @param  all   true <=> rollback main transaction.
2234
2045
*/
2235
2046
 
2236
 
void mark_transaction_to_rollback(THD *thd, bool all)
 
2047
void mark_transaction_to_rollback(Session *session, bool all)
2237
2048
{
2238
 
  if (thd)
 
2049
  if (session)
2239
2050
  {
2240
 
    thd->is_fatal_sub_stmt_error= true;
2241
 
    thd->transaction_rollback_request= all;
 
2051
    session->is_fatal_sub_stmt_error= true;
 
2052
    session->transaction_rollback_request= all;
2242
2053
  }
2243
2054
}
2244
2055
/***************************************************************************
2252
2063
extern "C" void xid_free_hash(void *);
2253
2064
 
2254
2065
unsigned char *xid_get_hash_key(const unsigned char *ptr, size_t *length,
2255
 
                        bool not_used __attribute__((unused)))
 
2066
                        bool )
2256
2067
{
2257
2068
  *length=((XID_STATE*)ptr)->xid.key_length();
2258
2069
  return ((XID_STATE*)ptr)->xid.key();
2260
2071
 
2261
2072
void xid_free_hash(void *ptr)
2262
2073
{
2263
 
  if (!((XID_STATE*)ptr)->in_thd)
 
2074
  if (!((XID_STATE*)ptr)->in_session)
2264
2075
    free((unsigned char*)ptr);
2265
2076
}
2266
2077
 
2296
2107
  pthread_mutex_lock(&LOCK_xid_cache);
2297
2108
  if (hash_search(&xid_cache, xid->key(), xid->key_length()))
2298
2109
    res=0;
2299
 
  else if (!(xs=(XID_STATE *)my_malloc(sizeof(*xs), MYF(MY_WME))))
 
2110
  else if (!(xs=(XID_STATE *)malloc(sizeof(*xs))))
2300
2111
    res=1;
2301
2112
  else
2302
2113
  {
2303
2114
    xs->xa_state=xa_state;
2304
2115
    xs->xid.set(xid);
2305
 
    xs->in_thd=0;
 
2116
    xs->in_session=0;
2306
2117
    res=my_hash_insert(&xid_cache, (unsigned char*)xs);
2307
2118
  }
2308
2119
  pthread_mutex_unlock(&LOCK_xid_cache);
2328
2139
  pthread_mutex_unlock(&LOCK_xid_cache);
2329
2140
}
2330
2141
 
2331
 
/*
2332
 
  Implementation of interface to write rows to the binary log through the
2333
 
  thread.  The thread is responsible for writing the rows it has
2334
 
  inserted/updated/deleted.
2335
 
*/
2336
 
 
2337
 
 
2338
 
/*
2339
 
  Template member function for ensuring that there is an rows log
2340
 
  event of the apropriate type before proceeding.
2341
 
 
2342
 
  PRE CONDITION:
2343
 
    - Events of type 'RowEventT' have the type code 'type_code'.
2344
 
    
2345
 
  POST CONDITION:
2346
 
    If a non-NULL pointer is returned, the pending event for thread 'thd' will
2347
 
    be an event of type 'RowEventT' (which have the type code 'type_code')
2348
 
    will either empty or have enough space to hold 'needed' bytes.  In
2349
 
    addition, the columns bitmap will be correct for the row, meaning that
2350
 
    the pending event will be flushed if the columns in the event differ from
2351
 
    the columns suppled to the function.
2352
 
 
2353
 
  RETURNS
2354
 
    If no error, a non-NULL pending event (either one which already existed or
2355
 
    the newly created one).
2356
 
    If error, NULL.
2357
 
 */
2358
 
 
2359
 
template <class RowsEventT> Rows_log_event* 
2360
 
THD::binlog_prepare_pending_rows_event(Table* table, uint32_t serv_id,
2361
 
                                       size_t needed,
2362
 
                                       bool is_transactional,
2363
 
                                       RowsEventT *hint __attribute__((unused)))
2364
 
{
2365
 
  /* Pre-conditions */
2366
 
  assert(table->s->table_map_id != UINT32_MAX);
2367
 
 
2368
 
  /* Fetch the type code for the RowsEventT template parameter */
2369
 
  int const type_code= RowsEventT::TYPE_CODE;
2370
 
 
2371
 
  /*
2372
 
    There is no good place to set up the transactional data, so we
2373
 
    have to do it here.
2374
 
  */
2375
 
  if (binlog_setup_trx_data())
2376
 
    return(NULL);
2377
 
 
2378
 
  Rows_log_event* pending= binlog_get_pending_rows_event();
2379
 
 
2380
 
  if (unlikely(pending && !pending->is_valid()))
2381
 
    return(NULL);
2382
 
 
2383
 
  /*
2384
 
    Check if the current event is non-NULL and a write-rows
2385
 
    event. Also check if the table provided is mapped: if it is not,
2386
 
    then we have switched to writing to a new table.
2387
 
    If there is no pending event, we need to create one. If there is a pending
2388
 
    event, but it's not about the same table id, or not of the same type
2389
 
    (between Write, Update and Delete), or not the same affected columns, or
2390
 
    going to be too big, flush this event to disk and create a new pending
2391
 
    event.
2392
 
 
2393
 
    The last test is necessary for the Cluster injector to work
2394
 
    correctly. The reason is that the Cluster can inject two write
2395
 
    rows with different column bitmaps if there is an insert followed
2396
 
    by an update in the same transaction, and these are grouped into a
2397
 
    single epoch/transaction when fed to the injector.
2398
 
 
2399
 
    TODO: Fix the code so that the last test can be removed.
2400
 
  */
2401
 
  if (!pending ||
2402
 
      pending->server_id != serv_id || 
2403
 
      pending->get_table_id() != table->s->table_map_id ||
2404
 
      pending->get_type_code() != type_code || 
2405
 
      pending->get_data_size() + needed > opt_binlog_rows_event_max_size ||
2406
 
      !bitmap_cmp(pending->get_cols(), table->write_set))
2407
 
    {
2408
 
    /* Create a new RowsEventT... */
2409
 
    Rows_log_event* const
2410
 
        ev= new RowsEventT(this, table, table->s->table_map_id,
2411
 
                           is_transactional);
2412
 
    if (unlikely(!ev))
2413
 
      return(NULL);
2414
 
    ev->server_id= serv_id; // I don't like this, it's too easy to forget.
2415
 
    /*
2416
 
      flush the pending event and replace it with the newly created
2417
 
      event...
2418
 
    */
2419
 
    if (unlikely(mysql_bin_log.flush_and_set_pending_rows_event(this, ev)))
2420
 
    {
2421
 
      delete ev;
2422
 
      return(NULL);
2423
 
    }
2424
 
 
2425
 
    return(ev);               /* This is the new pending event */
2426
 
  }
2427
 
  return(pending);        /* This is the current pending event */
2428
 
}
2429
 
 
2430
 
#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
2431
 
/*
2432
 
  Instantiate the versions we need, we have -fno-implicit-template as
2433
 
  compiling option.
2434
 
*/
2435
 
template Rows_log_event*
2436
 
THD::binlog_prepare_pending_rows_event(Table*, uint32_t, size_t, bool,
2437
 
                                       Write_rows_log_event*);
2438
 
 
2439
 
template Rows_log_event*
2440
 
THD::binlog_prepare_pending_rows_event(Table*, uint32_t, size_t, bool,
2441
 
                                       Delete_rows_log_event *);
2442
 
 
2443
 
template Rows_log_event* 
2444
 
THD::binlog_prepare_pending_rows_event(Table*, uint32_t, size_t, bool,
2445
 
                                       Update_rows_log_event *);
2446
 
#endif
2447
 
 
2448
2142
namespace {
2449
2143
  /**
2450
2144
     Class to handle temporary allocation of memory for row data.
2546
2240
      }
2547
2241
      else
2548
2242
      {
2549
 
        m_memory= (unsigned char *) my_malloc(total_length, MYF(MY_WME));
 
2243
        m_memory= (unsigned char *) malloc(total_length);
2550
2244
        m_release_memory_on_destruction= true;
2551
2245
      }
2552
2246
    }
2558
2252
  };
2559
2253
}
2560
2254
 
2561
 
 
2562
 
int THD::binlog_write_row(Table* table, bool is_trans, 
2563
 
                          unsigned char const *record) 
2564
 
2565
 
  assert(current_stmt_binlog_row_based && mysql_bin_log.is_open());
2566
 
 
2567
 
  /*
2568
 
    Pack records into format for transfer. We are allocating more
2569
 
    memory than needed, but that doesn't matter.
2570
 
  */
2571
 
  Row_data_memory memory(table, table->max_row_length(record));
2572
 
  if (!memory.has_memory())
2573
 
    return HA_ERR_OUT_OF_MEM;
2574
 
 
2575
 
  unsigned char *row_data= memory.slot(0);
2576
 
 
2577
 
  size_t const len= pack_row(table, table->write_set, row_data, record);
2578
 
 
2579
 
  Rows_log_event* const ev=
2580
 
    binlog_prepare_pending_rows_event(table, server_id, len, is_trans,
2581
 
                                      static_cast<Write_rows_log_event*>(0));
2582
 
 
2583
 
  if (unlikely(ev == 0))
2584
 
    return HA_ERR_OUT_OF_MEM;
2585
 
 
2586
 
  return ev->add_row_data(row_data, len);
2587
 
}
2588
 
 
2589
 
int THD::binlog_update_row(Table* table, bool is_trans,
2590
 
                           const unsigned char *before_record,
2591
 
                           const unsigned char *after_record)
2592
 
2593
 
  assert(current_stmt_binlog_row_based && mysql_bin_log.is_open());
2594
 
 
2595
 
  size_t const before_maxlen = table->max_row_length(before_record);
2596
 
  size_t const after_maxlen  = table->max_row_length(after_record);
2597
 
 
2598
 
  Row_data_memory row_data(table, before_maxlen, after_maxlen);
2599
 
  if (!row_data.has_memory())
2600
 
    return HA_ERR_OUT_OF_MEM;
2601
 
 
2602
 
  unsigned char *before_row= row_data.slot(0);
2603
 
  unsigned char *after_row= row_data.slot(1);
2604
 
 
2605
 
  size_t const before_size= pack_row(table, table->read_set, before_row,
2606
 
                                        before_record);
2607
 
  size_t const after_size= pack_row(table, table->write_set, after_row,
2608
 
                                       after_record);
2609
 
 
2610
 
  Rows_log_event* const ev=
2611
 
    binlog_prepare_pending_rows_event(table, server_id,
2612
 
                                      before_size + after_size, is_trans,
2613
 
                                      static_cast<Update_rows_log_event*>(0));
2614
 
 
2615
 
  if (unlikely(ev == 0))
2616
 
    return HA_ERR_OUT_OF_MEM;
2617
 
 
2618
 
  return
2619
 
    ev->add_row_data(before_row, before_size) ||
2620
 
    ev->add_row_data(after_row, after_size);
2621
 
}
2622
 
 
2623
 
int THD::binlog_delete_row(Table* table, bool is_trans, 
2624
 
                           unsigned char const *record)
2625
 
2626
 
  assert(current_stmt_binlog_row_based && mysql_bin_log.is_open());
2627
 
 
2628
 
  /* 
2629
 
     Pack records into format for transfer. We are allocating more
2630
 
     memory than needed, but that doesn't matter.
2631
 
  */
2632
 
  Row_data_memory memory(table, table->max_row_length(record));
2633
 
  if (unlikely(!memory.has_memory()))
2634
 
    return HA_ERR_OUT_OF_MEM;
2635
 
 
2636
 
  unsigned char *row_data= memory.slot(0);
2637
 
 
2638
 
  size_t const len= pack_row(table, table->read_set, row_data, record);
2639
 
 
2640
 
  Rows_log_event* const ev=
2641
 
    binlog_prepare_pending_rows_event(table, server_id, len, is_trans,
2642
 
                                      static_cast<Delete_rows_log_event*>(0));
2643
 
 
2644
 
  if (unlikely(ev == 0))
2645
 
    return HA_ERR_OUT_OF_MEM;
2646
 
 
2647
 
  return ev->add_row_data(row_data, len);
2648
 
}
2649
 
 
2650
 
 
2651
 
int THD::binlog_flush_pending_rows_event(bool stmt_end)
2652
 
{
2653
 
  /*
2654
 
    We shall flush the pending event even if we are not in row-based
2655
 
    mode: it might be the case that we left row-based mode before
2656
 
    flushing anything (e.g., if we have explicitly locked tables).
2657
 
   */
2658
 
  if (!mysql_bin_log.is_open())
2659
 
    return(0);
2660
 
 
2661
 
  /*
2662
 
    Mark the event as the last event of a statement if the stmt_end
2663
 
    flag is set.
2664
 
  */
2665
 
  int error= 0;
2666
 
  if (Rows_log_event *pending= binlog_get_pending_rows_event())
2667
 
  {
2668
 
    if (stmt_end)
2669
 
    {
2670
 
      pending->set_flags(Rows_log_event::STMT_END_F);
2671
 
      pending->flags|= LOG_EVENT_UPDATE_TABLE_MAP_VERSION_F;
2672
 
      binlog_table_maps= 0;
2673
 
    }
2674
 
 
2675
 
    error= mysql_bin_log.flush_and_set_pending_rows_event(this, 0);
2676
 
  }
2677
 
 
2678
 
  return(error);
2679
 
}
2680
 
 
 
2255
/**
 
2256
  Close a connection.
 
2257
 
 
2258
  @param session                Thread handle
 
2259
  @param errcode        Error code to print to console
 
2260
  @param should_lock 1 if we have have to lock LOCK_thread_count
 
2261
 
 
2262
  @note
 
2263
    For the connection that is doing shutdown, this is called twice
 
2264
*/
 
2265
void Session::close_connection(uint32_t errcode, bool should_lock)
 
2266
{
 
2267
  st_vio *vio;
 
2268
  if (should_lock)
 
2269
    (void) pthread_mutex_lock(&LOCK_thread_count);
 
2270
  killed= Session::KILL_CONNECTION;
 
2271
  if ((vio= net.vio) != 0)
 
2272
  {
 
2273
    if (errcode)
 
2274
      net_send_error(this, errcode, ER(errcode)); /* purecov: inspected */
 
2275
    drizzleclient_net_close(&net);              /* vio is freed in delete session */
 
2276
  }
 
2277
  if (should_lock)
 
2278
    (void) pthread_mutex_unlock(&LOCK_thread_count);
 
2279
}
 
2280
 
 
2281
 
 
2282
 
 
2283
/**
 
2284
 Reset Session part responsible for command processing state.
 
2285
 
 
2286
   This needs to be called before execution of every statement
 
2287
   (prepared or conventional).
 
2288
   It is not called by substatements of routines.
 
2289
 
 
2290
  @todo
 
2291
   Make it a method of Session and align its name with the rest of
 
2292
   reset/end/start/init methods.
 
2293
  @todo
 
2294
   Call it after we use Session for queries, not before.
 
2295
*/
 
2296
 
 
2297
void Session::reset_for_next_command()
 
2298
{
 
2299
  free_list= 0;
 
2300
  select_number= 1;
 
2301
  /*
 
2302
    Those two lines below are theoretically unneeded as
 
2303
    Session::cleanup_after_query() should take care of this already.
 
2304
  */
 
2305
  auto_inc_intervals_in_cur_stmt_for_binlog.empty();
 
2306
 
 
2307
  is_fatal_error= 0;
 
2308
  server_status&= ~ (SERVER_MORE_RESULTS_EXISTS |
 
2309
                          SERVER_QUERY_NO_INDEX_USED |
 
2310
                          SERVER_QUERY_NO_GOOD_INDEX_USED);
 
2311
  /*
 
2312
    If in autocommit mode and not in a transaction, reset
 
2313
    OPTION_STATUS_NO_TRANS_UPDATE | OPTION_KEEP_LOG to not get warnings
 
2314
    in ha_rollback_trans() about some tables couldn't be rolled back.
 
2315
  */
 
2316
  if (!(options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))
 
2317
  {
 
2318
    options&= ~OPTION_KEEP_LOG;
 
2319
    transaction.all.modified_non_trans_table= false;
 
2320
  }
 
2321
  thread_specific_used= false;
 
2322
 
 
2323
  clear_error();
 
2324
  main_da.reset_diagnostics_area();
 
2325
  total_warn_count=0;                   // Warnings for this query
 
2326
  sent_row_count= examined_row_count= 0;
 
2327
 
 
2328
  return;
 
2329
}
 
2330
 
 
2331
 
 
2332
/**
 
2333
  return true if the table was created explicitly.
 
2334
*/
 
2335
inline bool is_user_table(Table * table)
 
2336
{
 
2337
  const char *name= table->s->table_name.str;
 
2338
  return strncmp(name, TMP_FILE_PREFIX, TMP_FILE_PREFIX_LENGTH);
 
2339
}
2681
2340
 
2682
2341
/*
2683
 
  Member function that will log query, either row-based or
2684
 
  statement-based depending on the value of the 'current_stmt_binlog_row_based'
2685
 
  the value of the 'qtype' flag.
2686
 
 
2687
 
  This function should be called after the all calls to ha_*_row()
2688
 
  functions have been issued, but before tables are unlocked and
2689
 
  closed.
2690
 
 
2691
 
  OBSERVE
2692
 
    There shall be no writes to any system table after calling
2693
 
    binlog_query(), so these writes has to be moved to before the call
2694
 
    of binlog_query() for correct functioning.
2695
 
 
2696
 
    This is necessesary not only for RBR, but the master might crash
2697
 
    after binlogging the query but before changing the system tables.
2698
 
    This means that the slave and the master are not in the same state
2699
 
    (after the master has restarted), so therefore we have to
2700
 
    eliminate this problem.
2701
 
 
2702
 
  RETURN VALUE
2703
 
    Error code, or 0 if no error.
 
2342
  Close all temporary tables created by 'CREATE TEMPORARY TABLE' for thread
 
2343
  creates one DROP TEMPORARY Table binlog event for each pseudo-thread
2704
2344
*/
2705
 
int THD::binlog_query(THD::enum_binlog_query_type qtype, char const *query_arg,
2706
 
                      ulong query_len, bool is_trans, bool suppress_use,
2707
 
                      THD::killed_state killed_status_arg)
2708
 
{
2709
 
  assert(query_arg && mysql_bin_log.is_open());
2710
 
 
2711
 
  if (int error= binlog_flush_pending_rows_event(true))
2712
 
    return(error);
2713
 
 
2714
 
  /*
2715
 
    If we are in statement mode and trying to log an unsafe statement,
2716
 
    we should print a warning.
2717
 
  */
2718
 
  if (lex->is_stmt_unsafe() &&
2719
 
      variables.binlog_format == BINLOG_FORMAT_STMT)
2720
 
  {
2721
 
    assert(this->query != NULL);
2722
 
    push_warning(this, DRIZZLE_ERROR::WARN_LEVEL_WARN,
2723
 
                 ER_BINLOG_UNSAFE_STATEMENT,
2724
 
                 ER(ER_BINLOG_UNSAFE_STATEMENT));
2725
 
    if (!(binlog_flags & BINLOG_FLAG_UNSAFE_STMT_PRINTED))
2726
 
    {
2727
 
      char warn_buf[DRIZZLE_ERRMSG_SIZE];
2728
 
      snprintf(warn_buf, DRIZZLE_ERRMSG_SIZE, "%s Statement: %s",
2729
 
               ER(ER_BINLOG_UNSAFE_STATEMENT), this->query);
2730
 
      sql_print_warning(warn_buf);
2731
 
      binlog_flags|= BINLOG_FLAG_UNSAFE_STMT_PRINTED;
2732
 
    }
2733
 
  }
2734
 
 
2735
 
  switch (qtype) {
2736
 
  case THD::ROW_QUERY_TYPE:
2737
 
    if (current_stmt_binlog_row_based)
2738
 
      return(0);
2739
 
    /* Otherwise, we fall through */
2740
 
  case THD::DRIZZLE_QUERY_TYPE:
2741
 
    /*
2742
 
      Using this query type is a conveniece hack, since we have been
2743
 
      moving back and forth between using RBR for replication of
2744
 
      system tables and not using it.
2745
 
 
2746
 
      Make sure to change in check_table_binlog_row_based() according
2747
 
      to how you treat this.
2748
 
    */
2749
 
  case THD::STMT_QUERY_TYPE:
2750
 
    /*
2751
 
      The DRIZZLE_LOG::write() function will set the STMT_END_F flag and
2752
 
      flush the pending rows event if necessary.
2753
 
     */
2754
 
    {
2755
 
      Query_log_event qinfo(this, query_arg, query_len, is_trans, suppress_use,
2756
 
                            killed_status_arg);
2757
 
      qinfo.flags|= LOG_EVENT_UPDATE_TABLE_MAP_VERSION_F;
2758
 
      /*
2759
 
        Binlog table maps will be irrelevant after a Query_log_event
2760
 
        (they are just removed on the slave side) so after the query
2761
 
        log event is written to the binary log, we pretend that no
2762
 
        table maps were written.
2763
 
       */
2764
 
      int error= mysql_bin_log.write(&qinfo);
2765
 
      binlog_table_maps= 0;
2766
 
      return(error);
2767
 
    }
2768
 
    break;
2769
 
 
2770
 
  case THD::QUERY_TYPE_COUNT:
2771
 
  default:
2772
 
    assert(0 <= qtype && qtype < QUERY_TYPE_COUNT);
2773
 
  }
2774
 
  return(0);
2775
 
}
2776
 
 
2777
 
bool Discrete_intervals_list::append(uint64_t start, uint64_t val,
2778
 
                                 uint64_t incr)
2779
 
{
2780
 
  /* first, see if this can be merged with previous */
2781
 
  if ((head == NULL) || tail->merge_if_contiguous(start, val, incr))
2782
 
  {
2783
 
    /* it cannot, so need to add a new interval */
2784
 
    Discrete_interval *new_interval= new Discrete_interval(start, val, incr);
2785
 
    return(append(new_interval));
2786
 
  }
2787
 
  return(0);
2788
 
}
2789
 
 
2790
 
bool Discrete_intervals_list::append(Discrete_interval *new_interval)
2791
 
{
2792
 
  if (unlikely(new_interval == NULL))
2793
 
    return(1);
2794
 
  if (head == NULL)
2795
 
    head= current= new_interval;
2796
 
  else
2797
 
    tail->next= new_interval;
2798
 
  tail= new_interval;
2799
 
  elements++;
2800
 
  return(0);
 
2345
 
 
2346
void Session::close_temporary_tables()
 
2347
{
 
2348
  Table *table;
 
2349
  Table *tmp_next;
 
2350
 
 
2351
  if (!temporary_tables)
 
2352
    return;
 
2353
 
 
2354
  for (table= temporary_tables; table; table= tmp_next)
 
2355
  {
 
2356
    tmp_next= table->next;
 
2357
    close_temporary(table, 1, 1);
 
2358
  }
 
2359
  temporary_tables= 0;
 
2360
 
 
2361
  return;
 
2362
}
 
2363
 
 
2364
 
 
2365
/** Clear most status variables. */
 
2366
extern time_t flush_status_time;
 
2367
extern uint32_t max_used_connections;
 
2368
 
 
2369
void Session::refresh_status()
 
2370
{
 
2371
  pthread_mutex_lock(&LOCK_status);
 
2372
 
 
2373
  /* Add thread's status variabes to global status */
 
2374
  add_to_status(&global_status_var, &status_var);
 
2375
 
 
2376
  /* Reset thread's status variables */
 
2377
  memset(&status_var, 0, sizeof(status_var));
 
2378
 
 
2379
  /* Reset some global variables */
 
2380
  reset_status_vars();
 
2381
 
 
2382
  /* Reset the counters of all key caches (default and named). */
 
2383
  process_key_caches(reset_key_cache_counters);
 
2384
  flush_status_time= time((time_t*) 0);
 
2385
  max_used_connections= 1; /* We set it to one, because we know we exist */
 
2386
  pthread_mutex_unlock(&LOCK_status);
2801
2387
}