~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/session.cc

  • Committer: Brian Aker
  • Date: 2009-01-24 09:43:35 UTC
  • Revision ID: brian@gir-3.local-20090124094335-6qdtvc35gl5fvivz
Adding in an example singe thread scheduler

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
18
 */
19
19
 
20
 
/**
21
 
 * @file Implementation of the Session class and API
22
 
 */
23
20
 
24
 
#include "config.h"
 
21
/*****************************************************************************
 
22
**
 
23
** This file implements classes defined in session.h
 
24
** Especially the classes to handle a result from a select
 
25
**
 
26
*****************************************************************************/
 
27
#include <drizzled/server_includes.h>
25
28
#include <drizzled/session.h>
26
 
#include "drizzled/session_list.h"
27
29
#include <sys/stat.h>
 
30
#include <mysys/thr_alarm.h>
 
31
#include <mysys/mysys_err.h>
28
32
#include <drizzled/error.h>
29
 
#include <drizzled/gettext.h>
30
33
#include <drizzled/query_id.h>
31
34
#include <drizzled/data_home.h>
32
35
#include <drizzled/sql_base.h>
36
39
#include <drizzled/item/return_int.h>
37
40
#include <drizzled/item/empty_string.h>
38
41
#include <drizzled/show.h>
39
 
#include <drizzled/plugin/client.h>
40
 
#include "drizzled/plugin/scheduler.h"
41
 
#include "drizzled/plugin/authentication.h"
42
 
#include "drizzled/plugin/logging.h"
43
 
#include "drizzled/plugin/transactional_storage_engine.h"
44
 
#include "drizzled/probes.h"
45
 
#include "drizzled/table_proto.h"
46
 
#include "drizzled/db.h"
47
 
#include "drizzled/pthread_globals.h"
48
 
#include "drizzled/transaction_services.h"
49
 
 
50
 
#include "plugin/myisam/myisam.h"
51
 
#include "drizzled/internal/iocache.h"
52
 
 
53
 
#include <fcntl.h>
54
 
#include <algorithm>
55
 
#include <climits>
56
 
 
57
 
using namespace std;
58
 
namespace drizzled
59
 
{
60
 
 
61
 
extern "C"
62
 
{
63
 
  unsigned char *get_var_key(user_var_entry *entry, size_t *length, bool );
64
 
  void free_user_var(user_var_entry *entry);
65
 
}
66
 
 
 
42
 
 
43
extern scheduler_functions thread_scheduler;
67
44
/*
68
45
  The following is used to initialise Table_ident with a internal
69
46
  table name
74
51
const char * const Session::DEFAULT_WHERE= "field list";
75
52
extern pthread_key_t THR_Session;
76
53
extern pthread_key_t THR_Mem_root;
77
 
extern uint32_t max_used_connections;
78
 
extern atomic<uint32_t> connection_count;
 
54
 
 
55
 
 
56
/*****************************************************************************
 
57
** Instansiate templates
 
58
*****************************************************************************/
 
59
 
 
60
#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
 
61
/* Used templates */
 
62
template class List<Key>;
 
63
template class List_iterator<Key>;
 
64
template class List<Key_part_spec>;
 
65
template class List_iterator<Key_part_spec>;
 
66
template class List<Alter_drop>;
 
67
template class List_iterator<Alter_drop>;
 
68
template class List<Alter_column>;
 
69
template class List_iterator<Alter_column>;
 
70
#endif
79
71
 
80
72
 
81
73
/****************************************************************************
82
74
** User variables
83
75
****************************************************************************/
84
 
unsigned char *get_var_key(user_var_entry *entry, size_t *length, bool )
 
76
 
 
77
extern "C" unsigned char *get_var_key(user_var_entry *entry, size_t *length,
 
78
                              bool not_used __attribute__((unused)))
85
79
{
86
80
  *length= entry->name.length;
87
81
  return (unsigned char*) entry->name.str;
88
82
}
89
83
 
90
 
void free_user_var(user_var_entry *entry)
 
84
extern "C" void free_user_var(user_var_entry *entry)
91
85
{
92
 
  delete entry;
 
86
  char *pos= (char*) entry+ALIGN_SIZE(sizeof(*entry));
 
87
  if (entry->value && entry->value != pos)
 
88
    free(entry->value);
 
89
  free((char*) entry);
93
90
}
94
91
 
95
92
bool Key_part_spec::operator==(const Key_part_spec& other) const
99
96
         !strcmp(field_name.str, other.field_name.str);
100
97
}
101
98
 
102
 
Open_tables_state::Open_tables_state(uint64_t version_arg)
103
 
  :version(version_arg), backups_available(false)
 
99
/**
 
100
  Construct an (almost) deep copy of this key. Only those
 
101
  elements that are known to never change are not copied.
 
102
  If out of memory, a partial copy is returned and an error is set
 
103
  in Session.
 
104
*/
 
105
 
 
106
Key::Key(const Key &rhs, MEM_ROOT *mem_root)
 
107
  :type(rhs.type),
 
108
  key_create_info(rhs.key_create_info),
 
109
  columns(rhs.columns, mem_root),
 
110
  name(rhs.name),
 
111
  generated(rhs.generated)
 
112
{
 
113
  list_copy_and_replace_each_value(columns, mem_root);
 
114
}
 
115
 
 
116
/**
 
117
  Construct an (almost) deep copy of this foreign key. Only those
 
118
  elements that are known to never change are not copied.
 
119
  If out of memory, a partial copy is returned and an error is set
 
120
  in Session.
 
121
*/
 
122
 
 
123
Foreign_key::Foreign_key(const Foreign_key &rhs, MEM_ROOT *mem_root)
 
124
  :Key(rhs),
 
125
  ref_table(rhs.ref_table),
 
126
  ref_columns(rhs.ref_columns),
 
127
  delete_opt(rhs.delete_opt),
 
128
  update_opt(rhs.update_opt),
 
129
  match_opt(rhs.match_opt)
 
130
{
 
131
  list_copy_and_replace_each_value(ref_columns, mem_root);
 
132
}
 
133
 
 
134
/*
 
135
  Test if a foreign key (= generated key) is a prefix of the given key
 
136
  (ignoring key name, key type and order of columns)
 
137
 
 
138
  NOTES:
 
139
    This is only used to test if an index for a FOREIGN KEY exists
 
140
 
 
141
  IMPLEMENTATION
 
142
    We only compare field names
 
143
 
 
144
  RETURN
 
145
    0   Generated key is a prefix of other key
 
146
    1   Not equal
 
147
*/
 
148
 
 
149
bool foreign_key_prefix(Key *a, Key *b)
 
150
{
 
151
  /* Ensure that 'a' is the generated key */
 
152
  if (a->generated)
 
153
  {
 
154
    if (b->generated && a->columns.elements > b->columns.elements)
 
155
      std::swap(a, b);                       // Put shorter key in 'a'
 
156
  }
 
157
  else
 
158
  {
 
159
    if (!b->generated)
 
160
      return true;                              // No foreign key
 
161
    std::swap(a, b);                       // Put generated key in 'a'
 
162
  }
 
163
 
 
164
  /* Test if 'a' is a prefix of 'b' */
 
165
  if (a->columns.elements > b->columns.elements)
 
166
    return true;                                // Can't be prefix
 
167
 
 
168
  List_iterator<Key_part_spec> col_it1(a->columns);
 
169
  List_iterator<Key_part_spec> col_it2(b->columns);
 
170
  const Key_part_spec *col1, *col2;
 
171
 
 
172
#ifdef ENABLE_WHEN_INNODB_CAN_HANDLE_SWAPED_FOREIGN_KEY_COLUMNS
 
173
  while ((col1= col_it1++))
 
174
  {
 
175
    bool found= 0;
 
176
    col_it2.rewind();
 
177
    while ((col2= col_it2++))
 
178
    {
 
179
      if (*col1 == *col2)
 
180
      {
 
181
        found= true;
 
182
        break;
 
183
      }
 
184
    }
 
185
    if (!found)
 
186
      return true;                              // Error
 
187
  }
 
188
  return false;                                 // Is prefix
 
189
#else
 
190
  while ((col1= col_it1++))
 
191
  {
 
192
    col2= col_it2++;
 
193
    if (!(*col1 == *col2))
 
194
      return true;
 
195
  }
 
196
  return false;                                 // Is prefix
 
197
#endif
 
198
}
 
199
 
 
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
 
 
253
/****************************************************************************
 
254
** Thread specific functions
 
255
****************************************************************************/
 
256
 
 
257
Open_tables_state::Open_tables_state(ulong version_arg)
 
258
  :version(version_arg), state_flags(0U)
104
259
{
105
260
  reset_open_tables_state();
106
261
}
108
263
/*
109
264
  The following functions form part of the C plugin API
110
265
*/
 
266
 
111
267
extern "C" int mysql_tmpfile(const char *prefix)
112
268
{
113
269
  char filename[FN_REFLEN];
114
 
  int fd = internal::create_temp_file(filename, drizzle_tmpdir, prefix, MYF(MY_WME));
 
270
  File fd = create_temp_file(filename, drizzle_tmpdir, prefix,
 
271
                             O_CREAT | O_EXCL | O_RDWR,
 
272
                             MYF(MY_WME));
115
273
  if (fd >= 0) {
116
274
    unlink(filename);
117
275
  }
119
277
  return fd;
120
278
}
121
279
 
 
280
 
 
281
extern "C"
 
282
int session_in_lock_tables(const Session *session)
 
283
{
 
284
  return test(session->in_lock_tables);
 
285
}
 
286
 
 
287
 
122
288
extern "C"
123
289
int session_tablespace_op(const Session *session)
124
290
{
125
291
  return test(session->tablespace_op);
126
292
}
127
293
 
 
294
 
128
295
/**
129
296
   Set the process info field of the Session structure.
130
297
 
145
312
  return session->get_proc_info();
146
313
}
147
314
 
148
 
void **Session::getEngineData(const plugin::MonitoredInTransaction *monitored)
149
 
{
150
 
  return static_cast<void **>(&ha_data[monitored->getId()].ha_ptr);
151
 
}
152
 
 
153
 
ResourceContext *Session::getResourceContext(const plugin::MonitoredInTransaction *monitored,
154
 
                                             size_t index)
155
 
{
156
 
  return &ha_data[monitored->getId()].resource_context[index];
 
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;
157
319
}
158
320
 
159
321
extern "C"
174
336
  return (int) session->variables.tx_isolation;
175
337
}
176
338
 
177
 
Session::Session(plugin::Client *client_arg)
178
 
  :
179
 
  Open_tables_state(refresh_version),
180
 
  mem_root(&main_mem_root),
181
 
  lex(&main_lex),
182
 
  query(),
183
 
  client(client_arg),
184
 
  scheduler(NULL),
185
 
  scheduler_arg(NULL),
186
 
  lock_id(&main_lock_id),
187
 
  user_time(0),
188
 
  ha_data(plugin::num_trx_monitored_objects),
189
 
  arg_of_last_insert_id_function(false),
190
 
  first_successful_insert_id_in_prev_stmt(0),
191
 
  first_successful_insert_id_in_cur_stmt(0),
192
 
  limit_found_rows(0),
193
 
  global_read_lock(0),
194
 
  some_tables_deleted(false),
195
 
  no_errors(false),
196
 
  password(false),
197
 
  is_fatal_error(false),
198
 
  transaction_rollback_request(false),
199
 
  is_fatal_sub_stmt_error(0),
200
 
  derived_tables_processing(false),
201
 
  tablespace_op(false),
202
 
  m_lip(NULL),
203
 
  cached_table(0),
204
 
  transaction_message(NULL),
205
 
  statement_message(NULL)
206
 
{
207
 
  memset(process_list_info, 0, PROCESS_LIST_WIDTH);
208
 
  client->setSession(this);
 
339
extern "C"
 
340
void session_inc_row_count(Session *session)
 
341
{
 
342
  session->row_count++;
 
343
}
 
344
 
 
345
/**
 
346
  Clear this diagnostics area.
 
347
 
 
348
  Normally called at the end of a statement.
 
349
*/
 
350
 
 
351
void
 
352
Diagnostics_area::reset_diagnostics_area()
 
353
{
 
354
  can_overwrite_status= false;
 
355
  /** Don't take chances in production */
 
356
  m_message[0]= '\0';
 
357
  m_sql_errno= 0;
 
358
  m_server_status= 0;
 
359
  m_affected_rows= 0;
 
360
  m_last_insert_id= 0;
 
361
  m_total_warn_count= 0;
 
362
  is_sent= false;
 
363
  /** Tiny reset in debug mode to see garbage right away */
 
364
  m_status= DA_EMPTY;
 
365
}
 
366
 
 
367
 
 
368
/**
 
369
  Set OK status -- ends commands that do not return a
 
370
  result set, e.g. INSERT/UPDATE/DELETE.
 
371
*/
 
372
 
 
373
void
 
374
Diagnostics_area::set_ok_status(Session *session, ha_rows affected_rows_arg,
 
375
                                uint64_t last_insert_id_arg,
 
376
                                const char *message_arg)
 
377
{
 
378
  assert(! is_set());
 
379
  /*
 
380
    In production, refuse to overwrite an error or a custom response
 
381
    with an OK packet.
 
382
  */
 
383
  if (is_error() || is_disabled())
 
384
    return;
 
385
  /** Only allowed to report success if has not yet reported an error */
 
386
 
 
387
  m_server_status= session->server_status;
 
388
  m_total_warn_count= session->total_warn_count;
 
389
  m_affected_rows= affected_rows_arg;
 
390
  m_last_insert_id= last_insert_id_arg;
 
391
  if (message_arg)
 
392
    strncpy(m_message, message_arg, sizeof(m_message) - 1);
 
393
  else
 
394
    m_message[0]= '\0';
 
395
  m_status= DA_OK;
 
396
}
 
397
 
 
398
 
 
399
/**
 
400
  Set EOF status.
 
401
*/
 
402
 
 
403
void
 
404
Diagnostics_area::set_eof_status(Session *session)
 
405
{
 
406
  /** Only allowed to report eof if has not yet reported an error */
 
407
 
 
408
  assert(! is_set());
 
409
  /*
 
410
    In production, refuse to overwrite an error or a custom response
 
411
    with an EOF packet.
 
412
  */
 
413
  if (is_error() || is_disabled())
 
414
    return;
 
415
 
 
416
  m_server_status= session->server_status;
 
417
  /*
 
418
    If inside a stored procedure, do not return the total
 
419
    number of warnings, since they are not available to the client
 
420
    anyway.
 
421
  */
 
422
  m_total_warn_count= session->total_warn_count;
 
423
 
 
424
  m_status= DA_EOF;
 
425
}
 
426
 
 
427
/**
 
428
  Set ERROR status.
 
429
*/
 
430
 
 
431
void
 
432
Diagnostics_area::set_error_status(Session *session __attribute__((unused)),
 
433
                                   uint32_t sql_errno_arg,
 
434
                                   const char *message_arg)
 
435
{
 
436
  /*
 
437
    Only allowed to report error if has not yet reported a success
 
438
    The only exception is when we flush the message to the client,
 
439
    an error can happen during the flush.
 
440
  */
 
441
  assert(! is_set() || can_overwrite_status);
 
442
  /*
 
443
    In production, refuse to overwrite a custom response with an
 
444
    ERROR packet.
 
445
  */
 
446
  if (is_disabled())
 
447
    return;
 
448
 
 
449
  m_sql_errno= sql_errno_arg;
 
450
  strncpy(m_message, message_arg, sizeof(m_message) - 1);
 
451
 
 
452
  m_status= DA_ERROR;
 
453
}
 
454
 
 
455
 
 
456
/**
 
457
  Mark the diagnostics area as 'DISABLED'.
 
458
 
 
459
  This is used in rare cases when the COM_ command at hand sends a response
 
460
  in a custom format. One example is the query cache, another is
 
461
  COM_STMT_PREPARE.
 
462
*/
 
463
 
 
464
void
 
465
Diagnostics_area::disable_status()
 
466
{
 
467
  assert(! is_set());
 
468
  m_status= DA_DISABLED;
 
469
}
 
470
 
 
471
 
 
472
Session::Session()
 
473
   :Statement(&main_lex, &main_mem_root,
 
474
              /* statement id */ 0),
 
475
   Open_tables_state(refresh_version),
 
476
   lock_id(&main_lock_id),
 
477
   user_time(0),
 
478
   arg_of_last_insert_id_function(false),
 
479
   first_successful_insert_id_in_prev_stmt(0),
 
480
   first_successful_insert_id_in_cur_stmt(0),
 
481
   global_read_lock(0),
 
482
   is_fatal_error(0),
 
483
   transaction_rollback_request(0),
 
484
   is_fatal_sub_stmt_error(0),
 
485
   in_lock_tables(0),
 
486
   derived_tables_processing(false),
 
487
   m_lip(NULL),
 
488
   scheduler(0)
 
489
{
 
490
  ulong tmp;
209
491
 
210
492
  /*
211
493
    Pass nominal parameters to init_alloc_root only to ensure that
212
494
    the destructor works OK in case of an error. The main_mem_root
213
495
    will be re-initialized in init_for_queries().
214
496
  */
215
 
  memory::init_sql_alloc(&main_mem_root, memory::ROOT_MIN_BLOCK_SIZE, 0);
216
 
  thread_stack= NULL;
 
497
  init_sql_alloc(&main_mem_root, ALLOC_ROOT_MIN_BLOCK_SIZE, 0);
 
498
  thread_stack= 0;
 
499
  catalog= (char*)"std"; // the only catalog we have for now
 
500
  some_tables_deleted=no_errors=password= 0;
217
501
  count_cuted_fields= CHECK_FIELD_IGNORE;
218
502
  killed= NOT_KILLED;
219
 
  col_access= 0;
220
 
  tmp_table= 0;
221
 
  used_tables= 0;
 
503
  col_access=0;
 
504
  is_slave_error= thread_specific_used= false;
 
505
  hash_clear(&handler_tables_hash);
 
506
  tmp_table=0;
 
507
  used_tables=0;
222
508
  cuted_fields= sent_row_count= row_count= 0L;
 
509
  limit_found_rows= 0;
223
510
  row_count_func= -1;
224
511
  statement_id_counter= 0UL;
225
512
  // Must be reset to handle error with Session's created for init of mysqld
227
514
  start_time=(time_t) 0;
228
515
  start_utime= 0L;
229
516
  utime_after_lock= 0L;
 
517
  slave_thread = 0;
230
518
  memset(&variables, 0, sizeof(variables));
231
519
  thread_id= 0;
232
520
  file_id = 0;
233
521
  query_id= 0;
234
 
  warn_query_id= 0;
235
 
  mysys_var= 0;
 
522
  warn_id= 0;
 
523
  db_charset= global_system_variables.collation_database;
 
524
  memset(ha_data, 0, sizeof(ha_data));
 
525
  replication_data= 0;
 
526
  mysys_var=0;
 
527
  binlog_evt_union.do_union= false;
236
528
  dbug_sentry=Session_SENTRY_MAGIC;
237
 
  cleanup_done= abort_on_warning= no_warnings_for_error= false;
 
529
  net.vio= 0;
 
530
  client_capabilities= 0;                       // minimalistic client
 
531
  system_thread= NON_SYSTEM_THREAD;
 
532
  cleanup_done= abort_on_warning= no_warnings_for_error= 0;
 
533
  peer_port= 0;                                 // For SHOW PROCESSLIST
 
534
  transaction.on= 1;
238
535
  pthread_mutex_init(&LOCK_delete, MY_MUTEX_INIT_FAST);
239
536
 
240
537
  /* Variables with default values */
241
538
  proc_info="login";
242
539
  where= Session::DEFAULT_WHERE;
243
 
  command= COM_CONNECT;
244
 
 
245
 
  plugin_sessionvar_init(this);
246
 
  /*
247
 
    variables= global_system_variables above has reset
248
 
    variables.pseudo_thread_id to 0. We need to correct it here to
249
 
    avoid temporary tables replication failure.
250
 
  */
251
 
  variables.pseudo_thread_id= thread_id;
252
 
  server_status= SERVER_STATUS_AUTOCOMMIT;
253
 
  options= session_startup_options;
254
 
 
255
 
  if (variables.max_join_size == HA_POS_ERROR)
256
 
    options |= OPTION_BIG_SELECTS;
257
 
  else
258
 
    options &= ~OPTION_BIG_SELECTS;
259
 
 
260
 
  open_options=ha_open_options;
261
 
  update_lock_default= TL_WRITE;
262
 
  session_tx_isolation= (enum_tx_isolation) variables.tx_isolation;
263
 
  warn_list.empty();
264
 
  memset(warn_count, 0, sizeof(warn_count));
265
 
  total_warn_count= 0;
266
 
  memset(&status_var, 0, sizeof(status_var));
267
 
 
 
540
  server_id = ::server_id;
 
541
  command=COM_CONNECT;
 
542
  *scramble= '\0';
 
543
 
 
544
  init();
268
545
  /* Initialize sub structures */
269
 
  memory::init_sql_alloc(&warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE);
 
546
  init_sql_alloc(&warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE);
 
547
  user_connect=(USER_CONN *)0;
270
548
  hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0,
271
549
            (hash_get_key) get_var_key,
272
550
            (hash_free_key) free_user_var, 0);
273
551
 
 
552
  /* For user vars replication*/
 
553
  if (opt_bin_log)
 
554
    my_init_dynamic_array(&user_var_events,
 
555
                          sizeof(BINLOG_USER_VAR_EVENT *), 16, 16);
 
556
  else
 
557
    memset(&user_var_events, 0, sizeof(user_var_events));
 
558
 
 
559
  /* Protocol */
 
560
  protocol= &protocol_text;                     // Default protocol
 
561
  protocol_text.init(this);
 
562
 
 
563
  const Query_id& query_id= Query_id::get_query_id();
 
564
  tablespace_op= false;
 
565
  tmp= sql_rnd();
 
566
  randominit(&rand, tmp + (ulong) &rand, tmp + query_id.value());
274
567
  substitute_null_with_insert_id = false;
275
568
  thr_lock_info_init(&lock_info); /* safety: will be reset after start */
276
569
  thr_lock_owner_init(&main_lock_id, &lock_info);
278
571
  m_internal_handler= NULL;
279
572
}
280
573
 
281
 
void Session::free_items()
282
 
{
283
 
  Item *next;
284
 
  /* This works because items are allocated with memory::sql_alloc() */
285
 
  for (; free_list; free_list= next)
286
 
  {
287
 
    next= free_list->next;
288
 
    free_list->delete_self();
289
 
  }
290
 
}
291
574
 
292
575
void Session::push_internal_handler(Internal_error_handler *handler)
293
576
{
299
582
  m_internal_handler= handler;
300
583
}
301
584
 
 
585
 
302
586
bool Session::handle_error(uint32_t sql_errno, const char *message,
303
587
                       DRIZZLE_ERROR::enum_warning_level level)
304
588
{
310
594
  return false;                                 // 'false', as per coding style
311
595
}
312
596
 
 
597
 
313
598
void Session::pop_internal_handler()
314
599
{
315
600
  assert(m_internal_handler != NULL);
354
639
}
355
640
#endif
356
641
 
 
642
/*
 
643
  Init common variables that has to be reset on start and on change_user
 
644
*/
 
645
 
 
646
void Session::init(void)
 
647
{
 
648
  pthread_mutex_lock(&LOCK_global_system_variables);
 
649
  plugin_sessionvar_init(this);
 
650
  variables.time_format= date_time_format_copy((Session*) 0,
 
651
                                               variables.time_format);
 
652
  variables.date_format= date_time_format_copy((Session*) 0,
 
653
                                               variables.date_format);
 
654
  variables.datetime_format= date_time_format_copy((Session*) 0,
 
655
                                                   variables.datetime_format);
 
656
  /*
 
657
    variables= global_system_variables above has reset
 
658
    variables.pseudo_thread_id to 0. We need to correct it here to
 
659
    avoid temporary tables replication failure.
 
660
  */
 
661
  variables.pseudo_thread_id= thread_id;
 
662
  pthread_mutex_unlock(&LOCK_global_system_variables);
 
663
  server_status= SERVER_STATUS_AUTOCOMMIT;
 
664
  options= session_startup_options;
 
665
 
 
666
  if (variables.max_join_size == HA_POS_ERROR)
 
667
    options |= OPTION_BIG_SELECTS;
 
668
  else
 
669
    options &= ~OPTION_BIG_SELECTS;
 
670
 
 
671
  transaction.all.modified_non_trans_table= transaction.stmt.modified_non_trans_table= false;
 
672
  open_options=ha_open_options;
 
673
  update_lock_default= TL_WRITE;
 
674
  session_tx_isolation= (enum_tx_isolation) variables.tx_isolation;
 
675
  warn_list.empty();
 
676
  memset(warn_count, 0, sizeof(warn_count));
 
677
  total_warn_count= 0;
 
678
  update_charset();
 
679
  memset(&status_var, 0, sizeof(status_var));
 
680
}
 
681
 
 
682
 
 
683
/*
 
684
  Init Session for query processing.
 
685
  This has to be called once before we call mysql_parse.
 
686
  See also comments in session.h.
 
687
*/
 
688
 
 
689
void Session::init_for_queries()
 
690
{
 
691
  set_time();
 
692
  ha_enable_transaction(this,true);
 
693
 
 
694
  reset_root_defaults(mem_root, variables.query_alloc_block_size,
 
695
                      variables.query_prealloc_size);
 
696
  reset_root_defaults(&transaction.mem_root,
 
697
                      variables.trans_alloc_block_size,
 
698
                      variables.trans_prealloc_size);
 
699
  transaction.xid_state.xid.null();
 
700
  transaction.xid_state.in_session=1;
 
701
}
 
702
 
 
703
 
357
704
/* Do operations that may take a long time */
358
705
 
359
706
void Session::cleanup(void)
360
707
{
361
 
  assert(cleanup_done == false);
 
708
  assert(cleanup_done == 0);
362
709
 
363
710
  killed= KILL_CONNECTION;
364
711
#ifdef ENABLE_WHEN_BINLOG_WILL_BE_ABLE_TO_PREPARE
368
715
  }
369
716
#endif
370
717
  {
371
 
    TransactionServices &transaction_services= TransactionServices::singleton();
372
 
    transaction_services.ha_rollback_trans(this, true);
 
718
    ha_rollback(this);
373
719
    xid_cache_delete(&transaction.xid_state);
374
720
  }
 
721
  if (locked_tables)
 
722
  {
 
723
    lock=locked_tables; locked_tables=0;
 
724
    close_thread_tables(this);
 
725
  }
 
726
  mysql_ha_cleanup(this);
 
727
  delete_dynamic(&user_var_events);
375
728
  hash_free(&user_vars);
376
729
  close_temporary_tables();
 
730
  free((char*) variables.time_format);
 
731
  free((char*) variables.date_format);
 
732
  free((char*) variables.datetime_format);
377
733
 
378
734
  if (global_read_lock)
379
735
    unlock_global_read_lock(this);
380
736
 
381
 
  cleanup_done= true;
 
737
  cleanup_done=1;
 
738
  return;
382
739
}
383
740
 
384
741
Session::~Session()
385
742
{
386
 
  this->checkSentry();
 
743
  Session_CHECK_SENTRY(this);
 
744
  /* Ensure that no one is using Session */
 
745
  pthread_mutex_lock(&LOCK_delete);
 
746
  pthread_mutex_unlock(&LOCK_delete);
387
747
  add_to_status(&global_status_var, &status_var);
388
748
 
389
 
  if (client->isConnected())
390
 
  {
391
 
    if (global_system_variables.log_warnings)
392
 
        errmsg_printf(ERRMSG_LVL_WARN, ER(ER_FORCING_CLOSE),internal::my_progname,
393
 
                      thread_id,
394
 
                      (getSecurityContext().getUser().c_str() ?
395
 
                       getSecurityContext().getUser().c_str() : ""));
396
 
    disconnect(0, false);
397
 
  }
398
 
 
399
749
  /* Close connection */
400
 
  client->close();
401
 
  delete client;
402
 
 
403
 
  if (cleanup_done == false)
 
750
  if (net.vio)
 
751
  {
 
752
    net_close(&net);
 
753
    net_end(&net);
 
754
  }
 
755
  if (!cleanup_done)
404
756
    cleanup();
405
757
 
406
 
  plugin::StorageEngine::closeConnection(this);
 
758
  ha_close_connection(this);
407
759
  plugin_sessionvar_cleanup(this);
408
760
 
 
761
  if (db)
 
762
  {
 
763
    free(db);
 
764
    db= NULL;
 
765
  }
409
766
  free_root(&warn_root,MYF(0));
 
767
  free_root(&transaction.mem_root,MYF(0));
410
768
  mysys_var=0;                                  // Safety (shouldn't be needed)
 
769
  pthread_mutex_destroy(&LOCK_delete);
411
770
  dbug_sentry= Session_SENTRY_GONE;
412
771
 
413
772
  free_root(&main_mem_root, MYF(0));
414
773
  pthread_setspecific(THR_Session,  0);
415
 
 
416
 
  plugin::Logging::postEndDo(this);
417
 
 
418
 
  /* Ensure that no one is using Session */
419
 
  pthread_mutex_unlock(&LOCK_delete);
420
 
  pthread_mutex_destroy(&LOCK_delete);
 
774
  return;
421
775
}
422
776
 
 
777
 
423
778
/*
424
779
  Add all status variables to another status variable array
425
780
 
433
788
    If this assumption will change, then we have to explictely add
434
789
    the other variables after the while loop
435
790
*/
436
 
void add_to_status(system_status_var *to_var, system_status_var *from_var)
 
791
 
 
792
void add_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var)
437
793
{
438
794
  ulong *end= (ulong*) ((unsigned char*) to_var +
439
 
                        offsetof(system_status_var, last_system_status_var) +
 
795
                        offsetof(STATUS_VAR, last_system_status_var) +
440
796
                        sizeof(ulong));
441
797
  ulong *to= (ulong*) to_var, *from= (ulong*) from_var;
442
798
 
456
812
  NOTE
457
813
    This function assumes that all variables are long/ulong.
458
814
*/
459
 
void add_diff_to_status(system_status_var *to_var, system_status_var *from_var,
460
 
                        system_status_var *dec_var)
 
815
 
 
816
void add_diff_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var,
 
817
                        STATUS_VAR *dec_var)
461
818
{
462
 
  ulong *end= (ulong*) ((unsigned char*) to_var + offsetof(system_status_var,
 
819
  ulong *end= (ulong*) ((unsigned char*) to_var + offsetof(STATUS_VAR,
463
820
                                                  last_system_status_var) +
464
821
                        sizeof(ulong));
465
822
  ulong *to= (ulong*) to_var, *from= (ulong*) from_var, *dec= (ulong*) dec_var;
468
825
    *(to++)+= *(from++) - *(dec++);
469
826
}
470
827
 
 
828
 
471
829
void Session::awake(Session::killed_state state_to_set)
472
830
{
473
 
  this->checkSentry();
 
831
  Session_CHECK_SENTRY(this);
474
832
  safe_mutex_assert_owner(&LOCK_delete);
475
833
 
476
834
  killed= state_to_set;
477
835
  if (state_to_set != Session::KILL_QUERY)
478
836
  {
479
 
    scheduler->killSession(this);
480
 
    DRIZZLE_CONNECTION_DONE(thread_id);
 
837
    thr_alarm_kill(thread_id);
 
838
    if (!slave_thread)
 
839
      thread_scheduler.post_kill_notification(this);
481
840
  }
482
841
  if (mysys_var)
483
842
  {
484
843
    pthread_mutex_lock(&mysys_var->mutex);
 
844
    if (!system_thread)         // Don't abort locks
 
845
      mysys_var->abort=1;
485
846
    /*
486
847
      This broadcast could be up in the air if the victim thread
487
848
      exits the cond in the time between read and broadcast, but that is
509
870
    }
510
871
    pthread_mutex_unlock(&mysys_var->mutex);
511
872
  }
 
873
  return;
512
874
}
513
875
 
514
876
/*
515
877
  Remember the location of thread info, the structure needed for
516
 
  memory::sql_alloc() and the structure for the net buffer
 
878
  sql_alloc() and the structure for the net buffer
517
879
*/
518
 
bool Session::storeGlobals()
 
880
 
 
881
bool Session::store_globals()
519
882
{
520
883
  /*
521
884
    Assert that thread_stack is initialized: it's necessary to be able
525
888
 
526
889
  if (pthread_setspecific(THR_Session,  this) ||
527
890
      pthread_setspecific(THR_Mem_root, &mem_root))
528
 
    return true;
529
 
 
 
891
    return 1;
530
892
  mysys_var=my_thread_var;
531
 
 
532
893
  /*
533
894
    Let mysqld define the thread id (not mysys)
534
895
    This allows us to move Session to different threads if needed.
541
902
    created in another thread
542
903
  */
543
904
  thr_lock_info_init(&lock_info);
544
 
  return false;
 
905
  return 0;
545
906
}
546
907
 
 
908
 
547
909
/*
548
 
  Init Session for query processing.
549
 
  This has to be called once before we call mysql_parse.
550
 
  See also comments in session.h.
 
910
  Cleanup after query.
 
911
 
 
912
  SYNOPSIS
 
913
    Session::cleanup_after_query()
 
914
 
 
915
  DESCRIPTION
 
916
    This function is used to reset thread data to its default state.
 
917
 
 
918
  NOTE
 
919
    This function is not suitable for setting thread data to some
 
920
    non-default values, as there is only one replication thread, so
 
921
    different master threads may overwrite data of each other on
 
922
    slave.
551
923
*/
552
924
 
553
 
void Session::prepareForQueries()
554
 
{
555
 
  if (variables.max_join_size == HA_POS_ERROR)
556
 
    options |= OPTION_BIG_SELECTS;
557
 
 
558
 
  version= refresh_version;
559
 
  set_proc_info(NULL);
560
 
  command= COM_SLEEP;
561
 
  set_time();
562
 
 
563
 
  reset_root_defaults(mem_root, variables.query_alloc_block_size,
564
 
                      variables.query_prealloc_size);
565
 
  transaction.xid_state.xid.null();
566
 
  transaction.xid_state.in_session=1;
567
 
}
568
 
 
569
 
bool Session::initGlobals()
570
 
{
571
 
  if (storeGlobals())
572
 
  {
573
 
    disconnect(ER_OUT_OF_RESOURCES, true);
574
 
    statistic_increment(aborted_connects, &LOCK_status);
575
 
    return true;
576
 
  }
577
 
  return false;
578
 
}
579
 
 
580
 
void Session::run()
581
 
{
582
 
  if (initGlobals() || authenticate())
583
 
  {
584
 
    disconnect(0, true);
585
 
    return;
586
 
  }
587
 
 
588
 
  prepareForQueries();
589
 
 
590
 
  while (! client->haveError() && killed != KILL_CONNECTION)
591
 
  {
592
 
    if (! executeStatement())
593
 
      break;
594
 
  }
595
 
 
596
 
  disconnect(0, true);
597
 
}
598
 
 
599
 
bool Session::schedule()
600
 
{
601
 
  scheduler= plugin::Scheduler::getScheduler();
602
 
  assert(scheduler);
603
 
 
604
 
  connection_count.increment();
605
 
 
606
 
  if (connection_count > max_used_connections)
607
 
    max_used_connections= connection_count;
608
 
 
609
 
  thread_id= variables.pseudo_thread_id= global_thread_id++;
610
 
 
611
 
  pthread_mutex_lock(&LOCK_thread_count);
612
 
  getSessionList().push_back(this);
613
 
  pthread_mutex_unlock(&LOCK_thread_count);
614
 
 
615
 
  if (scheduler->addSession(this))
616
 
  {
617
 
    DRIZZLE_CONNECTION_START(thread_id);
618
 
    char error_message_buff[DRIZZLE_ERRMSG_SIZE];
619
 
 
620
 
    killed= Session::KILL_CONNECTION;
621
 
 
622
 
    statistic_increment(aborted_connects, &LOCK_status);
623
 
 
624
 
    /* Can't use my_error() since store_globals has not been called. */
625
 
    /* TODO replace will better error message */
626
 
    snprintf(error_message_buff, sizeof(error_message_buff),
627
 
             ER(ER_CANT_CREATE_THREAD), 1);
628
 
    client->sendError(ER_CANT_CREATE_THREAD, error_message_buff);
629
 
    return true;
630
 
  }
631
 
 
632
 
  return false;
633
 
}
634
 
 
635
 
 
636
 
const char* Session::enter_cond(pthread_cond_t *cond,
637
 
                                pthread_mutex_t* mutex,
638
 
                                const char* msg)
639
 
{
640
 
  const char* old_msg = get_proc_info();
641
 
  safe_mutex_assert_owner(mutex);
642
 
  mysys_var->current_mutex = mutex;
643
 
  mysys_var->current_cond = cond;
644
 
  this->set_proc_info(msg);
645
 
  return old_msg;
646
 
}
647
 
 
648
 
void Session::exit_cond(const char* old_msg)
649
 
{
650
 
  /*
651
 
    Putting the mutex unlock in exit_cond() ensures that
652
 
    mysys_var->current_mutex is always unlocked _before_ mysys_var->mutex is
653
 
    locked (if that would not be the case, you'll get a deadlock if someone
654
 
    does a Session::awake() on you).
655
 
  */
656
 
  pthread_mutex_unlock(mysys_var->current_mutex);
657
 
  pthread_mutex_lock(&mysys_var->mutex);
658
 
  mysys_var->current_mutex = 0;
659
 
  mysys_var->current_cond = 0;
660
 
  this->set_proc_info(old_msg);
661
 
  pthread_mutex_unlock(&mysys_var->mutex);
662
 
}
663
 
 
664
 
bool Session::authenticate()
665
 
{
666
 
  lex_start(this);
667
 
  if (client->authenticate())
668
 
    return false;
669
 
 
670
 
  statistic_increment(aborted_connects, &LOCK_status);
671
 
  return true;
672
 
}
673
 
 
674
 
bool Session::checkUser(const char *passwd, uint32_t passwd_len, const char *in_db)
675
 
{
676
 
  const string passwd_str(passwd, passwd_len);
677
 
  bool is_authenticated=
678
 
    plugin::Authentication::isAuthenticated(getSecurityContext(),
679
 
                                            passwd_str);
680
 
 
681
 
  if (is_authenticated != true)
682
 
  {
683
 
    /* isAuthenticated has pushed the error message */
684
 
    return false;
685
 
  }
686
 
 
687
 
  /* Change database if necessary */
688
 
  if (in_db && in_db[0])
689
 
  {
690
 
    SchemaIdentifier identifier(in_db);
691
 
    if (mysql_change_db(this, identifier))
692
 
    {
693
 
      /* mysql_change_db() has pushed the error message. */
694
 
      return false;
695
 
    }
696
 
  }
697
 
  my_ok();
698
 
  password= test(passwd_len);          // remember for error messages
699
 
 
700
 
  /* Ready to handle queries */
701
 
  return true;
702
 
}
703
 
 
704
 
bool Session::executeStatement()
705
 
{
706
 
  char *l_packet= 0;
707
 
  uint32_t packet_length;
708
 
 
709
 
  enum enum_server_command l_command;
710
 
 
711
 
  /*
712
 
    indicator of uninitialized lex => normal flow of errors handling
713
 
    (see my_message_sql)
714
 
  */
715
 
  lex->current_select= 0;
716
 
  clear_error();
717
 
  main_da.reset_diagnostics_area();
718
 
 
719
 
  if (client->readCommand(&l_packet, &packet_length) == false)
720
 
    return false;
721
 
 
722
 
  if (packet_length == 0)
723
 
    return true;
724
 
 
725
 
  l_command= (enum enum_server_command) (unsigned char) l_packet[0];
726
 
 
727
 
  if (command >= COM_END)
728
 
    command= COM_END;                           // Wrong command
729
 
 
730
 
  assert(packet_length);
731
 
  return ! dispatch_command(l_command, this, l_packet+1, (uint32_t) (packet_length-1));
732
 
}
733
 
 
734
 
bool Session::readAndStoreQuery(const char *in_packet, uint32_t in_packet_length)
735
 
{
736
 
  /* Remove garbage at start and end of query */
737
 
  while (in_packet_length > 0 && my_isspace(charset(), in_packet[0]))
738
 
  {
739
 
    in_packet++;
740
 
    in_packet_length--;
741
 
  }
742
 
  const char *pos= in_packet + in_packet_length; /* Point at end null */
743
 
  while (in_packet_length > 0 &&
744
 
         (pos[-1] == ';' || my_isspace(charset() ,pos[-1])))
745
 
  {
746
 
    pos--;
747
 
    in_packet_length--;
748
 
  }
749
 
 
750
 
  query.assign(in_packet, in_packet + in_packet_length);
751
 
 
752
 
  return true;
753
 
}
754
 
 
755
 
bool Session::endTransaction(enum enum_mysql_completiontype completion)
756
 
{
757
 
  bool do_release= 0;
758
 
  bool result= true;
759
 
  TransactionServices &transaction_services= TransactionServices::singleton();
760
 
 
761
 
  if (transaction.xid_state.xa_state != XA_NOTR)
762
 
  {
763
 
    my_error(ER_XAER_RMFAIL, MYF(0), xa_state_names[transaction.xid_state.xa_state]);
764
 
    return false;
765
 
  }
766
 
  switch (completion)
767
 
  {
768
 
    case COMMIT:
769
 
      /*
770
 
       * We don't use endActiveTransaction() here to ensure that this works
771
 
       * even if there is a problem with the OPTION_AUTO_COMMIT flag
772
 
       * (Which of course should never happen...)
773
 
       */
774
 
      server_status&= ~SERVER_STATUS_IN_TRANS;
775
 
      if (transaction_services.ha_commit_trans(this, true))
776
 
        result= false;
777
 
      options&= ~(OPTION_BEGIN);
778
 
      break;
779
 
    case COMMIT_RELEASE:
780
 
      do_release= 1; /* fall through */
781
 
    case COMMIT_AND_CHAIN:
782
 
      result= endActiveTransaction();
783
 
      if (result == true && completion == COMMIT_AND_CHAIN)
784
 
        result= startTransaction();
785
 
      break;
786
 
    case ROLLBACK_RELEASE:
787
 
      do_release= 1; /* fall through */
788
 
    case ROLLBACK:
789
 
    case ROLLBACK_AND_CHAIN:
790
 
    {
791
 
      server_status&= ~SERVER_STATUS_IN_TRANS;
792
 
      if (transaction_services.ha_rollback_trans(this, true))
793
 
        result= false;
794
 
      options&= ~(OPTION_BEGIN);
795
 
      if (result == true && (completion == ROLLBACK_AND_CHAIN))
796
 
        result= startTransaction();
797
 
      break;
798
 
    }
799
 
    default:
800
 
      my_error(ER_UNKNOWN_COM_ERROR, MYF(0));
801
 
      return false;
802
 
  }
803
 
 
804
 
  if (result == false)
805
 
    my_error(killed_errno(), MYF(0));
806
 
  else if ((result == true) && do_release)
807
 
    killed= Session::KILL_CONNECTION;
808
 
 
809
 
  return result;
810
 
}
811
 
 
812
 
bool Session::endActiveTransaction()
813
 
{
814
 
  bool result= true;
815
 
  TransactionServices &transaction_services= TransactionServices::singleton();
816
 
 
817
 
  if (transaction.xid_state.xa_state != XA_NOTR)
818
 
  {
819
 
    my_error(ER_XAER_RMFAIL, MYF(0), xa_state_names[transaction.xid_state.xa_state]);
820
 
    return false;
821
 
  }
822
 
  if (options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
823
 
  {
824
 
    server_status&= ~SERVER_STATUS_IN_TRANS;
825
 
    if (transaction_services.ha_commit_trans(this, true))
826
 
      result= false;
827
 
  }
828
 
  options&= ~(OPTION_BEGIN);
829
 
  return result;
830
 
}
831
 
 
832
 
bool Session::startTransaction(start_transaction_option_t opt)
833
 
{
834
 
  bool result= true;
835
 
 
836
 
  if (! endActiveTransaction())
837
 
  {
838
 
    result= false;
839
 
  }
840
 
  else
841
 
  {
842
 
    options|= OPTION_BEGIN;
843
 
    server_status|= SERVER_STATUS_IN_TRANS;
844
 
 
845
 
    if (plugin::TransactionalStorageEngine::notifyStartTransaction(this, opt))
846
 
    {
847
 
      result= false;
848
 
    }
849
 
  }
850
 
 
851
 
  return result;
852
 
}
853
 
 
854
925
void Session::cleanup_after_query()
855
926
{
856
927
  /*
864
935
  if (first_successful_insert_id_in_cur_stmt > 0)
865
936
  {
866
937
    /* set what LAST_INSERT_ID() will return */
867
 
    first_successful_insert_id_in_prev_stmt= first_successful_insert_id_in_cur_stmt;
 
938
    first_successful_insert_id_in_prev_stmt=
 
939
      first_successful_insert_id_in_cur_stmt;
868
940
    first_successful_insert_id_in_cur_stmt= 0;
869
941
    substitute_null_with_insert_id= true;
870
942
  }
871
 
  arg_of_last_insert_id_function= false;
 
943
  arg_of_last_insert_id_function= 0;
872
944
  /* Free Items that were created during this execution */
873
945
  free_items();
874
946
  /* Reset where. */
875
947
  where= Session::DEFAULT_WHERE;
876
948
}
877
949
 
 
950
 
878
951
/**
879
952
  Create a LEX_STRING in this connection.
880
953
 
886
959
  @return  NULL on failure, or pointer to the LEX_STRING object
887
960
*/
888
961
LEX_STRING *Session::make_lex_string(LEX_STRING *lex_str,
889
 
                                     const std::string &str,
890
 
                                     bool allocate_lex_string)
891
 
{
892
 
  return make_lex_string(lex_str, str.c_str(), str.length(), allocate_lex_string);
893
 
}
894
 
 
895
 
LEX_STRING *Session::make_lex_string(LEX_STRING *lex_str,
896
 
                                     const char* str, uint32_t length,
897
 
                                     bool allocate_lex_string)
 
962
                                 const char* str, uint32_t length,
 
963
                                 bool allocate_lex_string)
898
964
{
899
965
  if (allocate_lex_string)
900
966
    if (!(lex_str= (LEX_STRING *)alloc(sizeof(LEX_STRING))))
905
971
  return lex_str;
906
972
}
907
973
 
 
974
 
 
975
/*
 
976
  Convert a string to another character set
 
977
 
 
978
  SYNOPSIS
 
979
    convert_string()
 
980
    to                          Store new allocated string here
 
981
    to_cs                       New character set for allocated string
 
982
    from                        String to convert
 
983
    from_length                 Length of string to convert
 
984
    from_cs                     Original character set
 
985
 
 
986
  NOTES
 
987
    to will be 0-terminated to make it easy to pass to system funcs
 
988
 
 
989
  RETURN
 
990
    0   ok
 
991
    1   End of memory.
 
992
        In this case to->str will point to 0 and to->length will be 0.
 
993
*/
 
994
 
 
995
bool Session::convert_string(LEX_STRING *to, const CHARSET_INFO * const to_cs,
 
996
                         const char *from, uint32_t from_length,
 
997
                         const CHARSET_INFO * const from_cs)
 
998
{
 
999
  size_t new_length= to_cs->mbmaxlen * from_length;
 
1000
  uint32_t dummy_errors;
 
1001
  if (!(to->str= (char*) alloc(new_length+1)))
 
1002
  {
 
1003
    to->length= 0;                              // Safety fix
 
1004
    return(1);                          // EOM
 
1005
  }
 
1006
  to->length= copy_and_convert((char*) to->str, new_length, to_cs,
 
1007
                               from, from_length, from_cs, &dummy_errors);
 
1008
  to->str[to->length]=0;                        // Safety
 
1009
  return(0);
 
1010
}
 
1011
 
 
1012
 
 
1013
/*
 
1014
  Convert string from source character set to target character set inplace.
 
1015
 
 
1016
  SYNOPSIS
 
1017
    Session::convert_string
 
1018
 
 
1019
  DESCRIPTION
 
1020
    Convert string using convert_buffer - buffer for character set
 
1021
    conversion shared between all protocols.
 
1022
 
 
1023
  RETURN
 
1024
    0   ok
 
1025
   !0   out of memory
 
1026
*/
 
1027
 
 
1028
bool Session::convert_string(String *s, const CHARSET_INFO * const from_cs,
 
1029
                         const CHARSET_INFO * const to_cs)
 
1030
{
 
1031
  uint32_t dummy_errors;
 
1032
  if (convert_buffer.copy(s->ptr(), s->length(), from_cs, to_cs, &dummy_errors))
 
1033
    return true;
 
1034
  /* If convert_buffer >> s copying is more efficient long term */
 
1035
  if (convert_buffer.alloced_length() >= convert_buffer.length() * 2 ||
 
1036
      !s->is_alloced())
 
1037
  {
 
1038
    return s->copy(convert_buffer);
 
1039
  }
 
1040
  s->swap(convert_buffer);
 
1041
  return false;
 
1042
}
 
1043
 
 
1044
 
 
1045
/*
 
1046
  Update some cache variables when character set changes
 
1047
*/
 
1048
 
 
1049
void Session::update_charset()
 
1050
{
 
1051
  uint32_t not_used;
 
1052
  charset_is_system_charset= !String::needs_conversion(0,charset(),
 
1053
                                                       system_charset_info,
 
1054
                                                       &not_used);
 
1055
  charset_is_collation_connection=
 
1056
    !String::needs_conversion(0,charset(),variables.getCollation(),
 
1057
                              &not_used);
 
1058
  charset_is_character_set_filesystem=
 
1059
    !String::needs_conversion(0, charset(),
 
1060
                              variables.character_set_filesystem, &not_used);
 
1061
}
 
1062
 
 
1063
 
 
1064
/* routings to adding tables to list of changed in transaction tables */
 
1065
 
 
1066
inline static void list_include(CHANGED_TableList** prev,
 
1067
                                CHANGED_TableList* curr,
 
1068
                                CHANGED_TableList* new_table)
 
1069
{
 
1070
  if (new_table)
 
1071
  {
 
1072
    *prev = new_table;
 
1073
    (*prev)->next = curr;
 
1074
  }
 
1075
}
 
1076
 
 
1077
/* add table to list of changed in transaction tables */
 
1078
 
 
1079
void Session::add_changed_table(Table *table)
 
1080
{
 
1081
  assert((options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) &&
 
1082
              table->file->has_transactions());
 
1083
  add_changed_table(table->s->table_cache_key.str,
 
1084
                    (long) table->s->table_cache_key.length);
 
1085
  return;
 
1086
}
 
1087
 
 
1088
 
 
1089
void Session::add_changed_table(const char *key, long key_length)
 
1090
{
 
1091
  CHANGED_TableList **prev_changed = &transaction.changed_tables;
 
1092
  CHANGED_TableList *curr = transaction.changed_tables;
 
1093
 
 
1094
  for (; curr; prev_changed = &(curr->next), curr = curr->next)
 
1095
  {
 
1096
    int cmp =  (long)curr->key_length - (long)key_length;
 
1097
    if (cmp < 0)
 
1098
    {
 
1099
      list_include(prev_changed, curr, changed_table_dup(key, key_length));
 
1100
      return;
 
1101
    }
 
1102
    else if (cmp == 0)
 
1103
    {
 
1104
      cmp = memcmp(curr->key, key, curr->key_length);
 
1105
      if (cmp < 0)
 
1106
      {
 
1107
        list_include(prev_changed, curr, changed_table_dup(key, key_length));
 
1108
        return;
 
1109
      }
 
1110
      else if (cmp == 0)
 
1111
      {
 
1112
        return;
 
1113
      }
 
1114
    }
 
1115
  }
 
1116
  *prev_changed = changed_table_dup(key, key_length);
 
1117
  return;
 
1118
}
 
1119
 
 
1120
 
 
1121
CHANGED_TableList* Session::changed_table_dup(const char *key, long key_length)
 
1122
{
 
1123
  CHANGED_TableList* new_table =
 
1124
    (CHANGED_TableList*) trans_alloc(ALIGN_SIZE(sizeof(CHANGED_TableList))+
 
1125
                                      key_length + 1);
 
1126
  if (!new_table)
 
1127
  {
 
1128
    my_error(EE_OUTOFMEMORY, MYF(ME_BELL),
 
1129
             ALIGN_SIZE(sizeof(TableList)) + key_length + 1);
 
1130
    killed= KILL_CONNECTION;
 
1131
    return 0;
 
1132
  }
 
1133
 
 
1134
  new_table->key= ((char*)new_table)+ ALIGN_SIZE(sizeof(CHANGED_TableList));
 
1135
  new_table->next = 0;
 
1136
  new_table->key_length = key_length;
 
1137
  ::memcpy(new_table->key, key, key_length);
 
1138
  return new_table;
 
1139
}
 
1140
 
 
1141
 
908
1142
int Session::send_explain_fields(select_result *result)
909
1143
{
910
1144
  List<Item> field_list;
940
1174
  }
941
1175
  item->maybe_null= 1;
942
1176
  field_list.push_back(new Item_empty_string("Extra", 255, cs));
943
 
  return (result->send_fields(field_list));
944
 
}
945
 
 
946
 
void select_result::send_error(uint32_t errcode, const char *err)
 
1177
  return (result->send_fields(field_list,
 
1178
                              Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF));
 
1179
}
 
1180
 
 
1181
 
 
1182
struct Item_change_record: public ilink
 
1183
{
 
1184
  Item **place;
 
1185
  Item *old_value;
 
1186
  /* Placement new was hidden by `new' in ilink (TODO: check): */
 
1187
  static void *operator new(size_t size __attribute__((unused)),
 
1188
                            void *mem)
 
1189
    { return mem; }
 
1190
  static void operator delete(void *ptr __attribute__((unused)),
 
1191
                              size_t size __attribute__((unused)))
 
1192
    {}
 
1193
  static void operator delete(void *ptr __attribute__((unused)),
 
1194
                              void *mem __attribute__((unused)))
 
1195
    { /* never called */ }
 
1196
};
 
1197
 
 
1198
 
 
1199
/*
 
1200
  Register an item tree tree transformation, performed by the query
 
1201
  optimizer. We need a pointer to runtime_memroot because it may be !=
 
1202
  session->mem_root (this may no longer be a true statement)
 
1203
*/
 
1204
 
 
1205
void Session::nocheck_register_item_tree_change(Item **place, Item *old_value,
 
1206
                                            MEM_ROOT *runtime_memroot)
 
1207
{
 
1208
  Item_change_record *change;
 
1209
  /*
 
1210
    Now we use one node per change, which adds some memory overhead,
 
1211
    but still is rather fast as we use alloc_root for allocations.
 
1212
    A list of item tree changes of an average query should be short.
 
1213
  */
 
1214
  void *change_mem= alloc_root(runtime_memroot, sizeof(*change));
 
1215
  if (change_mem == 0)
 
1216
  {
 
1217
    /*
 
1218
      OOM, session->fatal_error() is called by the error handler of the
 
1219
      memroot. Just return.
 
1220
    */
 
1221
    return;
 
1222
  }
 
1223
  change= new (change_mem) Item_change_record;
 
1224
  change->place= place;
 
1225
  change->old_value= old_value;
 
1226
  change_list.append(change);
 
1227
}
 
1228
 
 
1229
 
 
1230
void Session::rollback_item_tree_changes()
 
1231
{
 
1232
  I_List_iterator<Item_change_record> it(change_list);
 
1233
  Item_change_record *change;
 
1234
 
 
1235
  while ((change= it++))
 
1236
    *change->place= change->old_value;
 
1237
  /* We can forget about changes memory: it's allocated in runtime memroot */
 
1238
  change_list.empty();
 
1239
  return;
 
1240
}
 
1241
 
 
1242
 
 
1243
/*****************************************************************************
 
1244
** Functions to provide a interface to select results
 
1245
*****************************************************************************/
 
1246
 
 
1247
select_result::select_result()
 
1248
{
 
1249
  session=current_session;
 
1250
}
 
1251
 
 
1252
void select_result::send_error(uint32_t errcode,const char *err)
947
1253
{
948
1254
  my_message(errcode, err, MYF(0));
949
1255
}
950
1256
 
 
1257
 
 
1258
void select_result::cleanup()
 
1259
{
 
1260
  /* do nothing */
 
1261
}
 
1262
 
 
1263
static String default_line_term("\n",default_charset_info);
 
1264
static String default_escaped("\\",default_charset_info);
 
1265
static String default_field_term("\t",default_charset_info);
 
1266
 
 
1267
sql_exchange::sql_exchange(char *name, bool flag,
 
1268
                           enum enum_filetype filetype_arg)
 
1269
  :file_name(name), opt_enclosed(0), dumpfile(flag), skip_lines(0)
 
1270
{
 
1271
  filetype= filetype_arg;
 
1272
  field_term= &default_field_term;
 
1273
  enclosed=   line_start= &my_empty_string;
 
1274
  line_term=  &default_line_term;
 
1275
  escaped=    &default_escaped;
 
1276
  cs= NULL;
 
1277
}
 
1278
 
 
1279
bool select_send::send_fields(List<Item> &list, uint32_t flags)
 
1280
{
 
1281
  bool res;
 
1282
  if (!(res= session->protocol->send_fields(&list, flags)))
 
1283
    is_result_set_started= 1;
 
1284
  return res;
 
1285
}
 
1286
 
 
1287
void select_send::abort()
 
1288
{
 
1289
  return;
 
1290
}
 
1291
 
 
1292
 
 
1293
/**
 
1294
  Cleanup an instance of this class for re-use
 
1295
  at next execution of a prepared statement/
 
1296
  stored procedure statement.
 
1297
*/
 
1298
 
 
1299
void select_send::cleanup()
 
1300
{
 
1301
  is_result_set_started= false;
 
1302
}
 
1303
 
 
1304
/* Send data to client. Returns 0 if ok */
 
1305
 
 
1306
bool select_send::send_data(List<Item> &items)
 
1307
{
 
1308
  if (unit->offset_limit_cnt)
 
1309
  {                                             // using limit offset,count
 
1310
    unit->offset_limit_cnt--;
 
1311
    return 0;
 
1312
  }
 
1313
 
 
1314
  /*
 
1315
    We may be passing the control from mysqld to the client: release the
 
1316
    InnoDB adaptive hash S-latch to avoid thread deadlocks if it was reserved
 
1317
    by session
 
1318
  */
 
1319
  ha_release_temporary_latches(session);
 
1320
 
 
1321
  List_iterator_fast<Item> li(items);
 
1322
  Protocol *protocol= session->protocol;
 
1323
  char buff[MAX_FIELD_WIDTH];
 
1324
  String buffer(buff, sizeof(buff), &my_charset_bin);
 
1325
 
 
1326
  protocol->prepare_for_resend();
 
1327
  Item *item;
 
1328
  while ((item=li++))
 
1329
  {
 
1330
    if (item->send(protocol, &buffer))
 
1331
    {
 
1332
      protocol->free();                         // Free used buffer
 
1333
      my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
 
1334
      break;
 
1335
    }
 
1336
  }
 
1337
  session->sent_row_count++;
 
1338
  if (session->is_error())
 
1339
  {
 
1340
    protocol->remove_last_row();
 
1341
    return(1);
 
1342
  }
 
1343
  if (session->vio_ok())
 
1344
    return(protocol->write());
 
1345
  return(0);
 
1346
}
 
1347
 
 
1348
bool select_send::send_eof()
 
1349
{
 
1350
  /*
 
1351
    We may be passing the control from mysqld to the client: release the
 
1352
    InnoDB adaptive hash S-latch to avoid thread deadlocks if it was reserved
 
1353
    by session
 
1354
  */
 
1355
  ha_release_temporary_latches(session);
 
1356
 
 
1357
  /* Unlock tables before sending packet to gain some speed */
 
1358
  if (session->lock)
 
1359
  {
 
1360
    mysql_unlock_tables(session, session->lock);
 
1361
    session->lock=0;
 
1362
  }
 
1363
  ::my_eof(session);
 
1364
  is_result_set_started= 0;
 
1365
  return false;
 
1366
}
 
1367
 
 
1368
 
951
1369
/************************************************************************
952
1370
  Handling writing to file
953
1371
************************************************************************/
957
1375
  my_message(errcode, err, MYF(0));
958
1376
  if (file > 0)
959
1377
  {
960
 
    (void) end_io_cache(cache);
961
 
    (void) internal::my_close(file, MYF(0));
962
 
    (void) internal::my_delete(path, MYF(0));           // Delete file on error
 
1378
    (void) end_io_cache(&cache);
 
1379
    (void) my_close(file,MYF(0));
 
1380
    (void) my_delete(path,MYF(0));              // Delete file on error
963
1381
    file= -1;
964
1382
  }
965
1383
}
967
1385
 
968
1386
bool select_to_file::send_eof()
969
1387
{
970
 
  int error= test(end_io_cache(cache));
971
 
  if (internal::my_close(file, MYF(MY_WME)))
 
1388
  int error= test(end_io_cache(&cache));
 
1389
  if (my_close(file,MYF(MY_WME)))
972
1390
    error= 1;
973
1391
  if (!error)
974
1392
  {
977
1395
      function, SELECT INTO has to have an own SQLCOM.
978
1396
      TODO: split from SQLCOM_SELECT
979
1397
    */
980
 
    session->my_ok(row_count);
 
1398
    ::my_ok(session,row_count);
981
1399
  }
982
1400
  file= -1;
983
1401
  return error;
989
1407
  /* In case of error send_eof() may be not called: close the file here. */
990
1408
  if (file >= 0)
991
1409
  {
992
 
    (void) end_io_cache(cache);
993
 
    (void) internal::my_close(file, MYF(0));
 
1410
    (void) end_io_cache(&cache);
 
1411
    (void) my_close(file,MYF(0));
994
1412
    file= -1;
995
1413
  }
996
1414
  path[0]= '\0';
997
1415
  row_count= 0;
998
1416
}
999
1417
 
1000
 
select_to_file::select_to_file(file_exchange *ex)
1001
 
  : exchange(ex),
1002
 
    file(-1),
1003
 
    cache(static_cast<internal::IO_CACHE *>(memory::sql_calloc(sizeof(internal::IO_CACHE)))),
1004
 
    row_count(0L)
1005
 
{
1006
 
  path[0]=0;
1007
 
}
1008
1418
 
1009
1419
select_to_file::~select_to_file()
1010
1420
{
1011
 
  cleanup();
 
1421
  if (file >= 0)
 
1422
  {                                     // This only happens in case of error
 
1423
    (void) end_io_cache(&cache);
 
1424
    (void) my_close(file,MYF(0));
 
1425
    file= -1;
 
1426
  }
1012
1427
}
1013
1428
 
1014
1429
/***************************************************************************
1037
1452
*/
1038
1453
 
1039
1454
 
1040
 
static int create_file(Session *session, char *path, file_exchange *exchange, internal::IO_CACHE *cache)
 
1455
static File create_file(Session *session, char *path, sql_exchange *exchange,
 
1456
                        IO_CACHE *cache)
1041
1457
{
1042
 
  int file;
 
1458
  File file;
1043
1459
  uint32_t option= MY_UNPACK_FILENAME | MY_RELATIVE_PATH;
1044
1460
 
1045
1461
#ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS
1046
1462
  option|= MY_REPLACE_DIR;                      // Force use of db directory
1047
1463
#endif
1048
1464
 
1049
 
  if (!internal::dirname_length(exchange->file_name))
 
1465
  if (!dirname_length(exchange->file_name))
1050
1466
  {
1051
1467
    strcpy(path, drizzle_real_data_home);
1052
 
    if (! session->db.empty())
1053
 
      strncat(path, session->db.c_str(), FN_REFLEN-strlen(drizzle_real_data_home)-1);
1054
 
    (void) internal::fn_format(path, exchange->file_name, path, "", option);
 
1468
    if (session->db)
 
1469
      strncat(path, session->db, FN_REFLEN-strlen(drizzle_real_data_home)-1);
 
1470
    (void) fn_format(path, exchange->file_name, path, "", option);
1055
1471
  }
1056
1472
  else
1057
 
    (void) internal::fn_format(path, exchange->file_name, drizzle_real_data_home, "", option);
 
1473
    (void) fn_format(path, exchange->file_name, drizzle_real_data_home, "", option);
1058
1474
 
1059
1475
  if (opt_secure_file_priv &&
1060
1476
      strncmp(opt_secure_file_priv, path, strlen(opt_secure_file_priv)))
1070
1486
    return -1;
1071
1487
  }
1072
1488
  /* Create the file world readable */
1073
 
  if ((file= internal::my_create(path, 0666, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0)
 
1489
  if ((file= my_create(path, 0666, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0)
1074
1490
    return file;
 
1491
#ifdef HAVE_FCHMOD
1075
1492
  (void) fchmod(file, 0666);                    // Because of umask()
1076
 
  if (init_io_cache(cache, file, 0L, internal::WRITE_CACHE, 0L, 1, MYF(MY_WME)))
 
1493
#else
 
1494
  (void) chmod(path, 0666);
 
1495
#endif
 
1496
  if (init_io_cache(cache, file, 0L, WRITE_CACHE, 0L, 1, MYF(MY_WME)))
1077
1497
  {
1078
 
    internal::my_close(file, MYF(0));
1079
 
    internal::my_delete(path, MYF(0));  // Delete file on error, it was just created
 
1498
    my_close(file, MYF(0));
 
1499
    my_delete(path, MYF(0));  // Delete file on error, it was just created
1080
1500
    return -1;
1081
1501
  }
1082
1502
  return file;
1084
1504
 
1085
1505
 
1086
1506
int
1087
 
select_export::prepare(List<Item> &list, Select_Lex_Unit *u)
 
1507
select_export::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
1088
1508
{
1089
1509
  bool blob_flag=0;
1090
1510
  bool string_results= false, non_string_results= false;
1091
1511
  unit= u;
1092
 
  if ((uint32_t) strlen(exchange->file_name) + NAME_LEN >= FN_REFLEN)
 
1512
  if ((uint) strlen(exchange->file_name) + NAME_LEN >= FN_REFLEN)
1093
1513
    strncpy(path,exchange->file_name,FN_REFLEN-1);
1094
1514
 
1095
1515
  /* Check if there is any blobs in data */
1137
1557
    return 1;
1138
1558
  }
1139
1559
 
1140
 
  if ((file= create_file(session, path, exchange, cache)) < 0)
 
1560
  if ((file= create_file(session, path, exchange, &cache)) < 0)
1141
1561
    return 1;
1142
1562
 
1143
1563
  return 0;
1144
1564
}
1145
1565
 
 
1566
 
 
1567
#define NEED_ESCAPING(x) ((int) (unsigned char) (x) == escape_char    || \
 
1568
                          (enclosed ? (int) (unsigned char) (x) == field_sep_char      \
 
1569
                                    : (int) (unsigned char) (x) == field_term_char) || \
 
1570
                          (int) (unsigned char) (x) == line_sep_char  || \
 
1571
                          !(x))
 
1572
 
1146
1573
bool select_export::send_data(List<Item> &items)
1147
1574
{
1148
1575
  char buff[MAX_FIELD_WIDTH],null_buff[2],space[MAX_FIELD_WIDTH];
1160
1587
  uint32_t used_length=0,items_left=items.elements;
1161
1588
  List_iterator_fast<Item> li(items);
1162
1589
 
1163
 
  if (my_b_write(cache,(unsigned char*) exchange->line_start->ptr(),
1164
 
                 exchange->line_start->length()))
 
1590
  if (my_b_write(&cache,(unsigned char*) exchange->line_start->ptr(),
 
1591
                 exchange->line_start->length()))
1165
1592
    goto err;
1166
1593
  while ((item=li++))
1167
1594
  {
1171
1598
    res=item->str_result(&tmp);
1172
1599
    if (res && enclosed)
1173
1600
    {
1174
 
      if (my_b_write(cache,(unsigned char*) exchange->enclosed->ptr(),
1175
 
                     exchange->enclosed->length()))
1176
 
        goto err;
 
1601
      if (my_b_write(&cache,(unsigned char*) exchange->enclosed->ptr(),
 
1602
                     exchange->enclosed->length()))
 
1603
        goto err;
1177
1604
    }
1178
1605
    if (!res)
1179
1606
    {                                           // NULL
1180
1607
      if (!fixed_row_size)
1181
1608
      {
1182
 
        if (escape_char != -1)                  // Use \N syntax
1183
 
        {
1184
 
          null_buff[0]=escape_char;
1185
 
          null_buff[1]='N';
1186
 
          if (my_b_write(cache,(unsigned char*) null_buff,2))
1187
 
            goto err;
1188
 
        }
1189
 
        else if (my_b_write(cache,(unsigned char*) "NULL",4))
1190
 
          goto err;
 
1609
        if (escape_char != -1)                  // Use \N syntax
 
1610
        {
 
1611
          null_buff[0]=escape_char;
 
1612
          null_buff[1]='N';
 
1613
          if (my_b_write(&cache,(unsigned char*) null_buff,2))
 
1614
            goto err;
 
1615
        }
 
1616
        else if (my_b_write(&cache,(unsigned char*) "NULL",4))
 
1617
          goto err;
1191
1618
      }
1192
1619
      else
1193
1620
      {
1194
 
        used_length=0;                          // Fill with space
 
1621
        used_length=0;                          // Fill with space
1195
1622
      }
1196
1623
    }
1197
1624
    else
1198
1625
    {
1199
1626
      if (fixed_row_size)
1200
 
        used_length= min(res->length(),item->max_length);
 
1627
        used_length=cmin(res->length(),item->max_length);
1201
1628
      else
1202
 
        used_length= res->length();
1203
 
 
 
1629
        used_length=res->length();
1204
1630
      if ((result_type == STRING_RESULT || is_unsafe_field_sep) &&
1205
 
          escape_char != -1)
 
1631
           escape_char != -1)
1206
1632
      {
1207
1633
        char *pos, *start, *end;
1208
1634
        const CHARSET_INFO * const res_charset= res->charset();
1209
1635
        const CHARSET_INFO * const character_set_client= default_charset_info;
1210
1636
 
1211
1637
        bool check_second_byte= (res_charset == &my_charset_bin) &&
1212
 
          character_set_client->
1213
 
          escape_with_backslash_is_dangerous;
 
1638
                                 character_set_client->
 
1639
                                 escape_with_backslash_is_dangerous;
1214
1640
        assert(character_set_client->mbmaxlen == 2 ||
1215
1641
               !character_set_client->escape_with_backslash_is_dangerous);
1216
 
        for (start=pos=(char*) res->ptr(),end=pos+used_length ;
1217
 
             pos != end ;
1218
 
             pos++)
1219
 
        {
1220
 
          if (use_mb(res_charset))
1221
 
          {
1222
 
            int l;
1223
 
            if ((l=my_ismbchar(res_charset, pos, end)))
1224
 
            {
1225
 
              pos += l-1;
1226
 
              continue;
1227
 
            }
1228
 
          }
 
1642
        for (start=pos=(char*) res->ptr(),end=pos+used_length ;
 
1643
             pos != end ;
 
1644
             pos++)
 
1645
        {
 
1646
#ifdef USE_MB
 
1647
          if (use_mb(res_charset))
 
1648
          {
 
1649
            int l;
 
1650
            if ((l=my_ismbchar(res_charset, pos, end)))
 
1651
            {
 
1652
              pos += l-1;
 
1653
              continue;
 
1654
            }
 
1655
          }
 
1656
#endif
1229
1657
 
1230
1658
          /*
1231
1659
            Special case when dumping BINARY/VARBINARY/BLOB values
1259
1687
            assert before the loop makes that sure.
1260
1688
          */
1261
1689
 
1262
 
          if ((needs_escaping(*pos, enclosed) ||
 
1690
          if ((NEED_ESCAPING(*pos) ||
1263
1691
               (check_second_byte &&
1264
1692
                my_mbcharlen(character_set_client, (unsigned char) *pos) == 2 &&
1265
1693
                pos + 1 < end &&
1266
 
                needs_escaping(pos[1], enclosed))) &&
 
1694
                NEED_ESCAPING(pos[1]))) &&
1267
1695
              /*
1268
 
                Don't escape field_term_char by doubling - doubling is only
1269
 
                valid for ENCLOSED BY characters:
 
1696
               Don't escape field_term_char by doubling - doubling is only
 
1697
               valid for ENCLOSED BY characters:
1270
1698
              */
1271
1699
              (enclosed || !is_ambiguous_field_term ||
1272
1700
               (int) (unsigned char) *pos != field_term_char))
1273
1701
          {
1274
 
            char tmp_buff[2];
 
1702
            char tmp_buff[2];
1275
1703
            tmp_buff[0]= ((int) (unsigned char) *pos == field_sep_char &&
1276
1704
                          is_ambiguous_field_sep) ?
1277
 
              field_sep_char : escape_char;
1278
 
            tmp_buff[1]= *pos ? *pos : '0';
1279
 
            if (my_b_write(cache,(unsigned char*) start,(uint32_t) (pos-start)) ||
1280
 
                my_b_write(cache,(unsigned char*) tmp_buff,2))
1281
 
              goto err;
1282
 
            start=pos+1;
1283
 
          }
1284
 
        }
1285
 
        if (my_b_write(cache,(unsigned char*) start,(uint32_t) (pos-start)))
1286
 
          goto err;
 
1705
                          field_sep_char : escape_char;
 
1706
            tmp_buff[1]= *pos ? *pos : '0';
 
1707
            if (my_b_write(&cache,(unsigned char*) start,(uint) (pos-start)) ||
 
1708
                my_b_write(&cache,(unsigned char*) tmp_buff,2))
 
1709
              goto err;
 
1710
            start=pos+1;
 
1711
          }
 
1712
        }
 
1713
        if (my_b_write(&cache,(unsigned char*) start,(uint) (pos-start)))
 
1714
          goto err;
1287
1715
      }
1288
 
      else if (my_b_write(cache,(unsigned char*) res->ptr(),used_length))
1289
 
        goto err;
 
1716
      else if (my_b_write(&cache,(unsigned char*) res->ptr(),used_length))
 
1717
        goto err;
1290
1718
    }
1291
1719
    if (fixed_row_size)
1292
1720
    {                                           // Fill with space
1293
1721
      if (item->max_length > used_length)
1294
1722
      {
1295
 
        /* QQ:  Fix by adding a my_b_fill() function */
1296
 
        if (!space_inited)
1297
 
        {
1298
 
          space_inited=1;
1299
 
          memset(space, ' ', sizeof(space));
1300
 
        }
1301
 
        uint32_t length=item->max_length-used_length;
1302
 
        for (; length > sizeof(space) ; length-=sizeof(space))
1303
 
        {
1304
 
          if (my_b_write(cache,(unsigned char*) space,sizeof(space)))
1305
 
            goto err;
1306
 
        }
1307
 
        if (my_b_write(cache,(unsigned char*) space,length))
1308
 
          goto err;
 
1723
        /* QQ:  Fix by adding a my_b_fill() function */
 
1724
        if (!space_inited)
 
1725
        {
 
1726
          space_inited=1;
 
1727
          memset(space, ' ', sizeof(space));
 
1728
        }
 
1729
        uint32_t length=item->max_length-used_length;
 
1730
        for (; length > sizeof(space) ; length-=sizeof(space))
 
1731
        {
 
1732
          if (my_b_write(&cache,(unsigned char*) space,sizeof(space)))
 
1733
            goto err;
 
1734
        }
 
1735
        if (my_b_write(&cache,(unsigned char*) space,length))
 
1736
          goto err;
1309
1737
      }
1310
1738
    }
1311
1739
    if (res && enclosed)
1312
1740
    {
1313
 
      if (my_b_write(cache, (unsigned char*) exchange->enclosed->ptr(),
 
1741
      if (my_b_write(&cache, (unsigned char*) exchange->enclosed->ptr(),
1314
1742
                     exchange->enclosed->length()))
1315
1743
        goto err;
1316
1744
    }
1317
1745
    if (--items_left)
1318
1746
    {
1319
 
      if (my_b_write(cache, (unsigned char*) exchange->field_term->ptr(),
 
1747
      if (my_b_write(&cache, (unsigned char*) exchange->field_term->ptr(),
1320
1748
                     field_term_length))
1321
1749
        goto err;
1322
1750
    }
1323
1751
  }
1324
 
  if (my_b_write(cache,(unsigned char*) exchange->line_term->ptr(),
1325
 
                 exchange->line_term->length()))
 
1752
  if (my_b_write(&cache,(unsigned char*) exchange->line_term->ptr(),
 
1753
                 exchange->line_term->length()))
1326
1754
    goto err;
1327
1755
  return(0);
1328
1756
err:
1336
1764
 
1337
1765
 
1338
1766
int
1339
 
select_dump::prepare(List<Item> &, Select_Lex_Unit *u)
 
1767
select_dump::prepare(List<Item> &list __attribute__((unused)),
 
1768
                     SELECT_LEX_UNIT *u)
1340
1769
{
1341
1770
  unit= u;
1342
 
  return (int) ((file= create_file(session, path, exchange, cache)) < 0);
 
1771
  return (int) ((file= create_file(session, path, exchange, &cache)) < 0);
1343
1772
}
1344
1773
 
1345
1774
 
1366
1795
    res=item->str_result(&tmp);
1367
1796
    if (!res)                                   // If NULL
1368
1797
    {
1369
 
      if (my_b_write(cache,(unsigned char*) "",1))
 
1798
      if (my_b_write(&cache,(unsigned char*) "",1))
1370
1799
        goto err;
1371
1800
    }
1372
 
    else if (my_b_write(cache,(unsigned char*) res->ptr(),res->length()))
 
1801
    else if (my_b_write(&cache,(unsigned char*) res->ptr(),res->length()))
1373
1802
    {
1374
 
      my_error(ER_ERROR_ON_WRITE, MYF(0), path, errno);
 
1803
      my_error(ER_ERROR_ON_WRITE, MYF(0), path, my_errno);
1375
1804
      goto err;
1376
1805
    }
1377
1806
  }
1412
1841
void select_max_min_finder_subselect::cleanup()
1413
1842
{
1414
1843
  cache= 0;
 
1844
  return;
1415
1845
}
1416
1846
 
1417
1847
 
1518
1948
     sortcmp(val1, val2, cache->collation.collation) < 0);
1519
1949
}
1520
1950
 
1521
 
bool select_exists_subselect::send_data(List<Item> &)
 
1951
bool select_exists_subselect::send_data(List<Item> &items __attribute__((unused)))
1522
1952
{
1523
1953
  Item_exists_subselect *it= (Item_exists_subselect *)item;
1524
1954
  if (unit->offset_limit_cnt)
1531
1961
  return(0);
1532
1962
}
1533
1963
 
 
1964
 
 
1965
/***************************************************************************
 
1966
  Dump of select to variables
 
1967
***************************************************************************/
 
1968
 
 
1969
int select_dumpvar::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
 
1970
{
 
1971
  unit= u;
 
1972
 
 
1973
  if (var_list.elements != list.elements)
 
1974
  {
 
1975
    my_message(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT,
 
1976
               ER(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT), MYF(0));
 
1977
    return 1;
 
1978
  }
 
1979
  return 0;
 
1980
}
 
1981
 
 
1982
 
 
1983
void select_dumpvar::cleanup()
 
1984
{
 
1985
  row_count= 0;
 
1986
}
 
1987
 
 
1988
 
 
1989
void Query_arena::free_items()
 
1990
{
 
1991
  Item *next;
 
1992
  /* This works because items are allocated with sql_alloc() */
 
1993
  for (; free_list; free_list= next)
 
1994
  {
 
1995
    next= free_list->next;
 
1996
    free_list->delete_self();
 
1997
  }
 
1998
  /* Postcondition: free_list is 0 */
 
1999
  return;
 
2000
}
 
2001
 
 
2002
 
 
2003
/*
 
2004
  Statement functions
 
2005
*/
 
2006
 
 
2007
Statement::Statement(LEX *lex_arg, MEM_ROOT *mem_root_arg, ulong id_arg)
 
2008
  :Query_arena(mem_root_arg),
 
2009
  id(id_arg),
 
2010
  mark_used_columns(MARK_COLUMNS_READ),
 
2011
  lex(lex_arg),
 
2012
  query(0),
 
2013
  query_length(0),
 
2014
  db(NULL),
 
2015
  db_length(0)
 
2016
{
 
2017
}
 
2018
 
 
2019
 
1534
2020
/*
1535
2021
  Don't free mem_root, as mem_root is freed in the end of dispatch_command
1536
2022
  (once for any command).
1541
2027
  lex_end(lex);
1542
2028
}
1543
2029
 
 
2030
 
1544
2031
bool Session::copy_db_to(char **p_db, size_t *p_db_length)
1545
2032
{
1546
 
  if (db.empty())
 
2033
  if (db == NULL)
1547
2034
  {
1548
2035
    my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
1549
2036
    return true;
1550
2037
  }
1551
 
  *p_db= strmake(db.c_str(), db.length());
1552
 
  *p_db_length= db.length();
 
2038
  *p_db= strmake(db, db_length);
 
2039
  *p_db_length= db_length;
1553
2040
  return false;
1554
2041
}
1555
2042
 
 
2043
 
 
2044
bool select_dumpvar::send_data(List<Item> &items)
 
2045
{
 
2046
  List_iterator_fast<my_var> var_li(var_list);
 
2047
  List_iterator<Item> it(items);
 
2048
  Item *item;
 
2049
  my_var *mv;
 
2050
 
 
2051
  if (unit->offset_limit_cnt)
 
2052
  {                                             // using limit offset,count
 
2053
    unit->offset_limit_cnt--;
 
2054
    return(0);
 
2055
  }
 
2056
  if (row_count++)
 
2057
  {
 
2058
    my_message(ER_TOO_MANY_ROWS, ER(ER_TOO_MANY_ROWS), MYF(0));
 
2059
    return(1);
 
2060
  }
 
2061
  while ((mv= var_li++) && (item= it++))
 
2062
  {
 
2063
    if (mv->local == 0)
 
2064
    {
 
2065
      Item_func_set_user_var *suv= new Item_func_set_user_var(mv->s, item);
 
2066
      suv->fix_fields(session, 0);
 
2067
      suv->check(0);
 
2068
      suv->update();
 
2069
    }
 
2070
  }
 
2071
  return(session->is_error());
 
2072
}
 
2073
 
 
2074
bool select_dumpvar::send_eof()
 
2075
{
 
2076
  if (! row_count)
 
2077
    push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
2078
                 ER_SP_FETCH_NO_DATA, ER(ER_SP_FETCH_NO_DATA));
 
2079
  /*
 
2080
    In order to remember the value of affected rows for ROW_COUNT()
 
2081
    function, SELECT INTO has to have an own SQLCOM.
 
2082
    TODO: split from SQLCOM_SELECT
 
2083
  */
 
2084
  ::my_ok(session,row_count);
 
2085
  return 0;
 
2086
}
 
2087
 
1556
2088
/****************************************************************************
1557
 
  Tmp_Table_Param
 
2089
  TMP_TABLE_PARAM
1558
2090
****************************************************************************/
1559
2091
 
1560
 
void Tmp_Table_Param::init()
 
2092
void TMP_TABLE_PARAM::init()
1561
2093
{
1562
2094
  field_count= sum_func_count= func_count= hidden_field_count= 0;
1563
2095
  group_parts= group_length= group_null_parts= 0;
1564
2096
  quick_group= 1;
1565
2097
  table_charset= 0;
1566
2098
  precomputed_group_by= 0;
 
2099
  bit_fields_as_long= 0;
 
2100
  return;
1567
2101
}
1568
2102
 
1569
 
void Tmp_Table_Param::cleanup(void)
 
2103
void TMP_TABLE_PARAM::cleanup(void)
1570
2104
{
1571
2105
  /* Fix for Intel compiler */
1572
2106
  if (copy_field)
1576
2110
  }
1577
2111
}
1578
2112
 
 
2113
 
 
2114
void session_increment_bytes_sent(ulong length)
 
2115
{
 
2116
  Session *session=current_session;
 
2117
  if (likely(session != 0))
 
2118
  { /* current_session==0 when close_connection() calls net_send_error() */
 
2119
    session->status_var.bytes_sent+= length;
 
2120
  }
 
2121
}
 
2122
 
 
2123
 
 
2124
void session_increment_bytes_received(ulong length)
 
2125
{
 
2126
  current_session->status_var.bytes_received+= length;
 
2127
}
 
2128
 
 
2129
 
 
2130
void session_increment_net_big_packet_count(ulong length)
 
2131
{
 
2132
  current_session->status_var.net_big_packet_count+= length;
 
2133
}
 
2134
 
1579
2135
void Session::send_kill_message() const
1580
2136
{
1581
2137
  int err= killed_errno();
1588
2144
  memset(&status_var, 0, sizeof(status_var));
1589
2145
}
1590
2146
 
 
2147
void Security_context::skip_grants()
 
2148
{
 
2149
  /* privileges for the user are unknown everything is allowed */
 
2150
}
 
2151
 
1591
2152
 
1592
2153
/****************************************************************************
1593
2154
  Handling of open and locked tables states.
1601
2162
{
1602
2163
  backup->set_open_tables_state(this);
1603
2164
  reset_open_tables_state();
1604
 
  backups_available= false;
 
2165
  state_flags|= Open_tables_state::BACKUPS_AVAIL;
 
2166
  return;
1605
2167
}
1606
2168
 
1607
2169
 
1612
2174
    to be sure that it was properly cleaned up.
1613
2175
  */
1614
2176
  assert(open_tables == 0 && temporary_tables == 0 &&
1615
 
              derived_tables == 0 &&
1616
 
              lock == 0);
 
2177
              handler_tables == 0 && derived_tables == 0 &&
 
2178
              lock == 0 && locked_tables == 0);
1617
2179
  set_open_tables_state(backup);
 
2180
  return;
1618
2181
}
1619
2182
 
1620
 
bool Session::set_db(const std::string &new_db)
 
2183
 
 
2184
bool Session::set_db(const char *new_db, size_t new_db_len)
1621
2185
{
1622
2186
  /* Do not reallocate memory if current chunk is big enough. */
1623
 
  if (new_db.length())
1624
 
    db= new_db;
 
2187
  if (db && new_db && db_length >= new_db_len)
 
2188
    memcpy(db, new_db, new_db_len+1);
1625
2189
  else
1626
 
    db.clear();
1627
 
 
1628
 
  return false;
 
2190
  {
 
2191
    if (db)
 
2192
      free(db);
 
2193
    if (new_db)
 
2194
    {
 
2195
      db= (char *)malloc(new_db_len + 1);
 
2196
      if (db != NULL)
 
2197
      {
 
2198
        memcpy(db, new_db, new_db_len);
 
2199
        db[new_db_len]= 0;
 
2200
      }
 
2201
    }
 
2202
    else
 
2203
      db= NULL;
 
2204
  }
 
2205
  db_length= db ? new_db_len : 0;
 
2206
  return new_db && !db;
1629
2207
}
1630
2208
 
1631
2209
 
1632
 
 
1633
 
 
1634
2210
/**
1635
2211
  Check the killed state of a user thread
1636
2212
  @param session  user thread
1643
2219
}
1644
2220
 
1645
2221
/**
1646
 
  Return the session id of a user session
1647
 
  @param pointer to Session object
1648
 
  @return session's id
 
2222
  Return the thread id of a user thread
 
2223
  @param session user thread
 
2224
  @return thread id
1649
2225
*/
1650
2226
extern "C" unsigned long session_get_thread_id(const Session *session)
1651
2227
{
1652
 
  return (unsigned long) session->getSessionId();
1653
 
}
1654
 
 
1655
 
 
1656
 
const struct charset_info_st *session_charset(Session *session)
 
2228
  return((unsigned long)session->thread_id);
 
2229
}
 
2230
 
 
2231
 
 
2232
extern "C"
 
2233
LEX_STRING *session_make_lex_string(Session *session, LEX_STRING *lex_str,
 
2234
                                const char *str, unsigned int size,
 
2235
                                int allocate_lex_string)
 
2236
{
 
2237
  return session->make_lex_string(lex_str, str, size,
 
2238
                              (bool) allocate_lex_string);
 
2239
}
 
2240
 
 
2241
extern "C" const struct charset_info_st *session_charset(Session *session)
1657
2242
{
1658
2243
  return(session->charset());
1659
2244
}
1660
2245
 
1661
 
int session_non_transactional_update(const Session *session)
1662
 
{
1663
 
  return(session->transaction.all.hasModifiedNonTransData());
1664
 
}
1665
 
 
1666
 
void session_mark_transaction_to_rollback(Session *session, bool all)
 
2246
extern "C" char **session_query(Session *session)
 
2247
{
 
2248
  return(&session->query);
 
2249
}
 
2250
 
 
2251
extern "C" int session_slave_thread(const Session *session)
 
2252
{
 
2253
  return(session->slave_thread);
 
2254
}
 
2255
 
 
2256
extern "C" int session_non_transactional_update(const Session *session)
 
2257
{
 
2258
  return(session->transaction.all.modified_non_trans_table);
 
2259
}
 
2260
 
 
2261
extern "C" void session_mark_transaction_to_rollback(Session *session, bool all)
1667
2262
{
1668
2263
  mark_transaction_to_rollback(session, all);
1669
2264
}
1670
2265
 
 
2266
 
1671
2267
/**
1672
2268
  Mark transaction to rollback and mark error as fatal to a sub-statement.
1673
2269
 
1674
2270
  @param  session   Thread handle
1675
2271
  @param  all   true <=> rollback main transaction.
1676
2272
*/
 
2273
 
1677
2274
void mark_transaction_to_rollback(Session *session, bool all)
1678
2275
{
1679
2276
  if (session)
1682
2279
    session->transaction_rollback_request= all;
1683
2280
  }
1684
2281
}
1685
 
 
1686
 
void Session::disconnect(uint32_t errcode, bool should_lock)
1687
 
{
1688
 
  /* Allow any plugins to cleanup their session variables */
1689
 
  plugin_sessionvar_cleanup(this);
1690
 
 
1691
 
  /* If necessary, log any aborted or unauthorized connections */
1692
 
  if (killed || client->wasAborted())
1693
 
    statistic_increment(aborted_threads, &LOCK_status);
1694
 
 
1695
 
  if (client->wasAborted())
1696
 
  {
1697
 
    if (! killed && variables.log_warnings > 1)
1698
 
    {
1699
 
      SecurityContext *sctx= &security_ctx;
1700
 
 
1701
 
      errmsg_printf(ERRMSG_LVL_WARN, ER(ER_NEW_ABORTING_CONNECTION)
1702
 
                  , thread_id
1703
 
                  , (db.empty() ? "unconnected" : db.c_str())
1704
 
                  , sctx->getUser().empty() == false ? sctx->getUser().c_str() : "unauthenticated"
1705
 
                  , sctx->getIp().c_str()
1706
 
                  , (main_da.is_error() ? main_da.message() : ER(ER_UNKNOWN_ERROR)));
1707
 
    }
1708
 
  }
1709
 
 
1710
 
  /* Close out our connection to the client */
1711
 
  if (should_lock)
 
2282
/***************************************************************************
 
2283
  Handling of XA id cacheing
 
2284
***************************************************************************/
 
2285
 
 
2286
pthread_mutex_t LOCK_xid_cache;
 
2287
HASH xid_cache;
 
2288
 
 
2289
extern "C" unsigned char *xid_get_hash_key(const unsigned char *, size_t *, bool);
 
2290
extern "C" void xid_free_hash(void *);
 
2291
 
 
2292
unsigned char *xid_get_hash_key(const unsigned char *ptr, size_t *length,
 
2293
                        bool not_used __attribute__((unused)))
 
2294
{
 
2295
  *length=((XID_STATE*)ptr)->xid.key_length();
 
2296
  return ((XID_STATE*)ptr)->xid.key();
 
2297
}
 
2298
 
 
2299
void xid_free_hash(void *ptr)
 
2300
{
 
2301
  if (!((XID_STATE*)ptr)->in_session)
 
2302
    free((unsigned char*)ptr);
 
2303
}
 
2304
 
 
2305
bool xid_cache_init()
 
2306
{
 
2307
  pthread_mutex_init(&LOCK_xid_cache, MY_MUTEX_INIT_FAST);
 
2308
  return hash_init(&xid_cache, &my_charset_bin, 100, 0, 0,
 
2309
                   xid_get_hash_key, xid_free_hash, 0) != 0;
 
2310
}
 
2311
 
 
2312
void xid_cache_free()
 
2313
{
 
2314
  if (hash_inited(&xid_cache))
 
2315
  {
 
2316
    hash_free(&xid_cache);
 
2317
    pthread_mutex_destroy(&LOCK_xid_cache);
 
2318
  }
 
2319
}
 
2320
 
 
2321
XID_STATE *xid_cache_search(XID *xid)
 
2322
{
 
2323
  pthread_mutex_lock(&LOCK_xid_cache);
 
2324
  XID_STATE *res=(XID_STATE *)hash_search(&xid_cache, xid->key(), xid->key_length());
 
2325
  pthread_mutex_unlock(&LOCK_xid_cache);
 
2326
  return res;
 
2327
}
 
2328
 
 
2329
 
 
2330
bool xid_cache_insert(XID *xid, enum xa_states xa_state)
 
2331
{
 
2332
  XID_STATE *xs;
 
2333
  bool res;
 
2334
  pthread_mutex_lock(&LOCK_xid_cache);
 
2335
  if (hash_search(&xid_cache, xid->key(), xid->key_length()))
 
2336
    res=0;
 
2337
  else if (!(xs=(XID_STATE *)malloc(sizeof(*xs))))
 
2338
    res=1;
 
2339
  else
 
2340
  {
 
2341
    xs->xa_state=xa_state;
 
2342
    xs->xid.set(xid);
 
2343
    xs->in_session=0;
 
2344
    res=my_hash_insert(&xid_cache, (unsigned char*)xs);
 
2345
  }
 
2346
  pthread_mutex_unlock(&LOCK_xid_cache);
 
2347
  return res;
 
2348
}
 
2349
 
 
2350
 
 
2351
bool xid_cache_insert(XID_STATE *xid_state)
 
2352
{
 
2353
  pthread_mutex_lock(&LOCK_xid_cache);
 
2354
  assert(hash_search(&xid_cache, xid_state->xid.key(),
 
2355
                          xid_state->xid.key_length())==0);
 
2356
  bool res=my_hash_insert(&xid_cache, (unsigned char*)xid_state);
 
2357
  pthread_mutex_unlock(&LOCK_xid_cache);
 
2358
  return res;
 
2359
}
 
2360
 
 
2361
 
 
2362
void xid_cache_delete(XID_STATE *xid_state)
 
2363
{
 
2364
  pthread_mutex_lock(&LOCK_xid_cache);
 
2365
  hash_delete(&xid_cache, (unsigned char *)xid_state);
 
2366
  pthread_mutex_unlock(&LOCK_xid_cache);
 
2367
}
 
2368
 
 
2369
namespace {
 
2370
  /**
 
2371
     Class to handle temporary allocation of memory for row data.
 
2372
 
 
2373
     The responsibilities of the class is to provide memory for
 
2374
     packing one or two rows of packed data (depending on what
 
2375
     constructor is called).
 
2376
 
 
2377
     In order to make the allocation more efficient for "simple" rows,
 
2378
     i.e., rows that do not contain any blobs, a pointer to the
 
2379
     allocated memory is of memory is stored in the table structure
 
2380
     for simple rows.  If memory for a table containing a blob field
 
2381
     is requested, only memory for that is allocated, and subsequently
 
2382
     released when the object is destroyed.
 
2383
 
 
2384
   */
 
2385
  class Row_data_memory {
 
2386
  public:
 
2387
    /**
 
2388
      Build an object to keep track of a block-local piece of memory
 
2389
      for storing a row of data.
 
2390
 
 
2391
      @param table
 
2392
      Table where the pre-allocated memory is stored.
 
2393
 
 
2394
      @param length
 
2395
      Length of data that is needed, if the record contain blobs.
 
2396
     */
 
2397
    Row_data_memory(Table *table, size_t const len1)
 
2398
      : m_memory(0)
 
2399
    {
 
2400
      m_alloc_checked= false;
 
2401
      allocate_memory(table, len1);
 
2402
      m_ptr[0]= has_memory() ? m_memory : 0;
 
2403
      m_ptr[1]= 0;
 
2404
    }
 
2405
 
 
2406
    Row_data_memory(Table *table, size_t const len1, size_t const len2)
 
2407
      : m_memory(0)
 
2408
    {
 
2409
      m_alloc_checked= false;
 
2410
      allocate_memory(table, len1 + len2);
 
2411
      m_ptr[0]= has_memory() ? m_memory        : 0;
 
2412
      m_ptr[1]= has_memory() ? m_memory + len1 : 0;
 
2413
    }
 
2414
 
 
2415
    ~Row_data_memory()
 
2416
    {
 
2417
      if (m_memory != 0 && m_release_memory_on_destruction)
 
2418
        free((unsigned char*) m_memory);
 
2419
    }
 
2420
 
 
2421
    /**
 
2422
       Is there memory allocated?
 
2423
 
 
2424
       @retval true There is memory allocated
 
2425
       @retval false Memory allocation failed
 
2426
     */
 
2427
    bool has_memory() const {
 
2428
      m_alloc_checked= true;
 
2429
      return m_memory != 0;
 
2430
    }
 
2431
 
 
2432
    unsigned char *slot(uint32_t s)
 
2433
    {
 
2434
      assert(s < sizeof(m_ptr)/sizeof(*m_ptr));
 
2435
      assert(m_ptr[s] != 0);
 
2436
      assert(m_alloc_checked == true);
 
2437
      return m_ptr[s];
 
2438
    }
 
2439
 
 
2440
  private:
 
2441
    void allocate_memory(Table *const table, size_t const total_length)
 
2442
    {
 
2443
      if (table->s->blob_fields == 0)
 
2444
      {
 
2445
        /*
 
2446
          The maximum length of a packed record is less than this
 
2447
          length. We use this value instead of the supplied length
 
2448
          when allocating memory for records, since we don't know how
 
2449
          the memory will be used in future allocations.
 
2450
 
 
2451
          Since table->s->reclength is for unpacked records, we have
 
2452
          to add two bytes for each field, which can potentially be
 
2453
          added to hold the length of a packed field.
 
2454
        */
 
2455
        size_t const maxlen= table->s->reclength + 2 * table->s->fields;
 
2456
 
 
2457
        /*
 
2458
          Allocate memory for two records if memory hasn't been
 
2459
          allocated. We allocate memory for two records so that it can
 
2460
          be used when processing update rows as well.
 
2461
        */
 
2462
        if (table->write_row_record == 0)
 
2463
          table->write_row_record=
 
2464
            (unsigned char *) alloc_root(&table->mem_root, 2 * maxlen);
 
2465
        m_memory= table->write_row_record;
 
2466
        m_release_memory_on_destruction= false;
 
2467
      }
 
2468
      else
 
2469
      {
 
2470
        m_memory= (unsigned char *) malloc(total_length);
 
2471
        m_release_memory_on_destruction= true;
 
2472
      }
 
2473
    }
 
2474
 
 
2475
    mutable bool m_alloc_checked;
 
2476
    bool m_release_memory_on_destruction;
 
2477
    unsigned char *m_memory;
 
2478
    unsigned char *m_ptr[2];
 
2479
  };
 
2480
}
 
2481
 
 
2482
bool Discrete_intervals_list::append(uint64_t start, uint64_t val,
 
2483
                                 uint64_t incr)
 
2484
{
 
2485
  /* first, see if this can be merged with previous */
 
2486
  if ((head == NULL) || tail->merge_if_contiguous(start, val, incr))
 
2487
  {
 
2488
    /* it cannot, so need to add a new interval */
 
2489
    Discrete_interval *new_interval= new Discrete_interval(start, val, incr);
 
2490
    return(append(new_interval));
 
2491
  }
 
2492
  return(0);
 
2493
}
 
2494
 
 
2495
bool Discrete_intervals_list::append(Discrete_interval *new_interval)
 
2496
{
 
2497
  if (unlikely(new_interval == NULL))
 
2498
    return(1);
 
2499
  if (head == NULL)
 
2500
    head= current= new_interval;
 
2501
  else
 
2502
    tail->next= new_interval;
 
2503
  tail= new_interval;
 
2504
  elements++;
 
2505
  return(0);
 
2506
}
 
2507
 
 
2508
/**
 
2509
  Close a connection.
 
2510
 
 
2511
  @param session                Thread handle
 
2512
  @param errcode        Error code to print to console
 
2513
  @param lock           1 if we have have to lock LOCK_thread_count
 
2514
 
 
2515
  @note
 
2516
    For the connection that is doing shutdown, this is called twice
 
2517
*/
 
2518
void Session::close_connection(uint32_t errcode, bool lock)
 
2519
{
 
2520
  st_vio *vio;
 
2521
  if (lock)
1712
2522
    (void) pthread_mutex_lock(&LOCK_thread_count);
1713
2523
  killed= Session::KILL_CONNECTION;
1714
 
  if (client->isConnected())
 
2524
  if ((vio= net.vio) != 0)
1715
2525
  {
1716
2526
    if (errcode)
1717
 
    {
1718
 
      /*my_error(errcode, ER(errcode));*/
1719
 
      client->sendError(errcode, ER(errcode));
1720
 
    }
1721
 
    client->close();
 
2527
      net_send_error(this, errcode, ER(errcode)); /* purecov: inspected */
 
2528
    net_close(&net);            /* vio is freed in delete session */
1722
2529
  }
1723
 
  if (should_lock)
 
2530
  if (lock)
1724
2531
    (void) pthread_mutex_unlock(&LOCK_thread_count);
1725
2532
}
1726
2533
 
 
2534
 
 
2535
 
 
2536
/**
 
2537
 Reset Session part responsible for command processing state.
 
2538
 
 
2539
   This needs to be called before execution of every statement
 
2540
   (prepared or conventional).
 
2541
   It is not called by substatements of routines.
 
2542
 
 
2543
  @todo
 
2544
   Make it a method of Session and align its name with the rest of
 
2545
   reset/end/start/init methods.
 
2546
  @todo
 
2547
   Call it after we use Session for queries, not before.
 
2548
*/
 
2549
 
1727
2550
void Session::reset_for_next_command()
1728
2551
{
1729
2552
  free_list= 0;
1734
2557
  */
1735
2558
  auto_inc_intervals_in_cur_stmt_for_binlog.empty();
1736
2559
 
1737
 
  is_fatal_error= false;
 
2560
  is_fatal_error= 0;
1738
2561
  server_status&= ~ (SERVER_MORE_RESULTS_EXISTS |
1739
2562
                          SERVER_QUERY_NO_INDEX_USED |
1740
2563
                          SERVER_QUERY_NO_GOOD_INDEX_USED);
 
2564
  /*
 
2565
    If in autocommit mode and not in a transaction, reset
 
2566
    OPTION_STATUS_NO_TRANS_UPDATE | OPTION_KEEP_LOG to not get warnings
 
2567
    in ha_rollback_trans() about some tables couldn't be rolled back.
 
2568
  */
 
2569
  if (!(options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))
 
2570
  {
 
2571
    options&= ~OPTION_KEEP_LOG;
 
2572
    transaction.all.modified_non_trans_table= false;
 
2573
  }
 
2574
  thread_specific_used= false;
1741
2575
 
 
2576
  if (opt_bin_log)
 
2577
  {
 
2578
    reset_dynamic(&user_var_events);
 
2579
    user_var_events_alloc= mem_root;
 
2580
  }
1742
2581
  clear_error();
1743
2582
  main_da.reset_diagnostics_area();
1744
2583
  total_warn_count=0;                   // Warnings for this query
1745
2584
  sent_row_count= examined_row_count= 0;
 
2585
 
 
2586
  return;
 
2587
}
 
2588
 
 
2589
 
 
2590
/**
 
2591
  return true if the table was created explicitly.
 
2592
*/
 
2593
inline bool is_user_table(Table * table)
 
2594
{
 
2595
  const char *name= table->s->table_name.str;
 
2596
  return strncmp(name, TMP_FILE_PREFIX, TMP_FILE_PREFIX_LENGTH);
1746
2597
}
1747
2598
 
1748
2599
/*
1749
2600
  Close all temporary tables created by 'CREATE TEMPORARY TABLE' for thread
 
2601
  creates one DROP TEMPORARY Table binlog event for each pseudo-thread
1750
2602
*/
1751
2603
 
1752
2604
void Session::close_temporary_tables()
1754
2606
  Table *table;
1755
2607
  Table *tmp_next;
1756
2608
 
1757
 
  if (not temporary_tables)
 
2609
  if (!temporary_tables)
1758
2610
    return;
1759
2611
 
1760
2612
  for (table= temporary_tables; table; table= tmp_next)
1761
2613
  {
1762
2614
    tmp_next= table->next;
1763
 
    nukeTable(table);
1764
 
  }
1765
 
  temporary_tables= NULL;
1766
 
}
1767
 
 
1768
 
/*
1769
 
  unlink from session->temporary tables and close temporary table
1770
 
*/
1771
 
 
1772
 
void Session::close_temporary_table(Table *table)
1773
 
{
1774
 
  if (table->prev)
1775
 
  {
1776
 
    table->prev->next= table->next;
1777
 
    if (table->prev->next)
1778
 
      table->next->prev= table->prev;
1779
 
  }
1780
 
  else
1781
 
  {
1782
 
    /* removing the item from the list */
1783
 
    assert(table == temporary_tables);
1784
 
    /*
1785
 
      slave must reset its temporary list pointer to zero to exclude
1786
 
      passing non-zero value to end_slave via rli->save_temporary_tables
1787
 
      when no temp tables opened, see an invariant below.
1788
 
    */
1789
 
    temporary_tables= table->next;
1790
 
    if (temporary_tables)
1791
 
      table->next->prev= NULL;
1792
 
  }
1793
 
  nukeTable(table);
1794
 
}
1795
 
 
1796
 
/*
1797
 
  Close and drop a temporary table
1798
 
 
1799
 
  NOTE
1800
 
  This dosn't unlink table from session->temporary
1801
 
  If this is needed, use close_temporary_table()
1802
 
*/
1803
 
 
1804
 
void Session::nukeTable(Table *table)
1805
 
{
1806
 
  plugin::StorageEngine *table_type= table->s->db_type();
1807
 
 
1808
 
  table->free_io_cache();
1809
 
  table->closefrm(false);
1810
 
 
1811
 
  TableIdentifier identifier(table->s->getSchemaName(), table->s->table_name.str, table->s->path.str);
1812
 
  rm_temporary_table(table_type, identifier);
1813
 
 
1814
 
  table->s->free_table_share();
1815
 
 
1816
 
  /* This makes me sad, but we're allocating it via malloc */
1817
 
  free(table);
1818
 
}
1819
 
 
1820
 
/** Clear most status variables. */
1821
 
extern time_t flush_status_time;
1822
 
extern uint32_t max_used_connections;
1823
 
 
1824
 
void Session::refresh_status()
1825
 
{
1826
 
  pthread_mutex_lock(&LOCK_status);
1827
 
 
1828
 
  /* Add thread's status variabes to global status */
1829
 
  add_to_status(&global_status_var, &status_var);
1830
 
 
1831
 
  /* Reset thread's status variables */
1832
 
  memset(&status_var, 0, sizeof(status_var));
1833
 
 
1834
 
  /* Reset some global variables */
1835
 
  reset_status_vars();
1836
 
 
1837
 
  /* Reset the counters of all key caches (default and named). */
1838
 
  reset_key_cache_counters();
1839
 
  flush_status_time= time((time_t*) 0);
1840
 
  max_used_connections= 1; /* We set it to one, because we know we exist */
1841
 
  pthread_mutex_unlock(&LOCK_status);
1842
 
}
1843
 
 
1844
 
user_var_entry *Session::getVariable(LEX_STRING &name, bool create_if_not_exists)
1845
 
{
1846
 
  user_var_entry *entry= NULL;
1847
 
 
1848
 
  entry= (user_var_entry*) hash_search(&user_vars, (unsigned char*) name.str, name.length);
1849
 
 
1850
 
  if ((entry == NULL) && create_if_not_exists)
1851
 
  {
1852
 
    if (!hash_inited(&user_vars))
1853
 
      return NULL;
1854
 
    entry= new (nothrow) user_var_entry(name.str, query_id);
1855
 
 
1856
 
    if (entry == NULL)
1857
 
      return NULL;
1858
 
 
1859
 
    if (my_hash_insert(&user_vars, (unsigned char*) entry))
1860
 
    {
1861
 
      assert(1);
1862
 
      free((char*) entry);
1863
 
      return 0;
1864
 
    }
1865
 
 
1866
 
  }
1867
 
 
1868
 
  return entry;
1869
 
}
1870
 
 
1871
 
void Session::mark_temp_tables_as_free_for_reuse()
1872
 
{
1873
 
  for (Table *table= temporary_tables ; table ; table= table->next)
1874
 
  {
1875
 
    if (table->query_id == query_id)
1876
 
    {
1877
 
      table->query_id= 0;
1878
 
      table->cursor->ha_reset();
1879
 
    }
1880
 
  }
1881
 
}
1882
 
 
1883
 
void Session::mark_used_tables_as_free_for_reuse(Table *table)
1884
 
{
1885
 
  for (; table ; table= table->next)
1886
 
  {
1887
 
    if (table->query_id == query_id)
1888
 
    {
1889
 
      table->query_id= 0;
1890
 
      table->cursor->ha_reset();
1891
 
    }
1892
 
  }
1893
 
}
1894
 
 
1895
 
/*
1896
 
  Unlocks tables and frees derived tables.
1897
 
  Put all normal tables used by thread in free list.
1898
 
 
1899
 
  It will only close/mark as free for reuse tables opened by this
1900
 
  substatement, it will also check if we are closing tables after
1901
 
  execution of complete query (i.e. we are on upper level) and will
1902
 
  leave prelocked mode if needed.
1903
 
*/
1904
 
void Session::close_thread_tables()
1905
 
{
1906
 
  Table *table;
1907
 
 
1908
 
  /*
1909
 
    We are assuming here that session->derived_tables contains ONLY derived
1910
 
    tables for this substatement. i.e. instead of approach which uses
1911
 
    query_id matching for determining which of the derived tables belong
1912
 
    to this substatement we rely on the ability of substatements to
1913
 
    save/restore session->derived_tables during their execution.
1914
 
 
1915
 
    TODO: Probably even better approach is to simply associate list of
1916
 
          derived tables with (sub-)statement instead of thread and destroy
1917
 
          them at the end of its execution.
1918
 
  */
1919
 
  if (derived_tables)
1920
 
  {
1921
 
    Table *next;
1922
 
    /*
1923
 
      Close all derived tables generated in queries like
1924
 
      SELECT * FROM (SELECT * FROM t1)
1925
 
    */
1926
 
    for (table= derived_tables ; table ; table= next)
1927
 
    {
1928
 
      next= table->next;
1929
 
      table->free_tmp_table(this);
1930
 
    }
1931
 
    derived_tables= 0;
1932
 
  }
1933
 
 
1934
 
  /*
1935
 
    Mark all temporary tables used by this statement as free for reuse.
1936
 
  */
1937
 
  mark_temp_tables_as_free_for_reuse();
1938
 
  /*
1939
 
    Let us commit transaction for statement. Since in 5.0 we only have
1940
 
    one statement transaction and don't allow several nested statement
1941
 
    transactions this call will do nothing if we are inside of stored
1942
 
    function or trigger (i.e. statement transaction is already active and
1943
 
    does not belong to statement for which we do close_thread_tables()).
1944
 
    TODO: This should be fixed in later releases.
1945
 
   */
1946
 
  if (backups_available == false)
1947
 
  {
1948
 
    TransactionServices &transaction_services= TransactionServices::singleton();
1949
 
    main_da.can_overwrite_status= true;
1950
 
    transaction_services.ha_autocommit_or_rollback(this, is_error());
1951
 
    main_da.can_overwrite_status= false;
1952
 
    transaction.stmt.reset();
1953
 
  }
1954
 
 
1955
 
  if (lock)
1956
 
  {
1957
 
    /*
1958
 
      For RBR we flush the pending event just before we unlock all the
1959
 
      tables.  This means that we are at the end of a topmost
1960
 
      statement, so we ensure that the STMT_END_F flag is set on the
1961
 
      pending event.  For statements that are *inside* stored
1962
 
      functions, the pending event will not be flushed: that will be
1963
 
      handled either before writing a query log event (inside
1964
 
      binlog_query()) or when preparing a pending event.
1965
 
     */
1966
 
    mysql_unlock_tables(this, lock);
1967
 
    lock= 0;
1968
 
  }
1969
 
  /*
1970
 
    Note that we need to hold LOCK_open while changing the
1971
 
    open_tables list. Another thread may work on it.
1972
 
    (See: remove_table_from_cache(), mysql_wait_completed_table())
1973
 
    Closing a MERGE child before the parent would be fatal if the
1974
 
    other thread tries to abort the MERGE lock in between.
1975
 
  */
1976
 
  if (open_tables)
1977
 
    close_open_tables();
1978
 
}
1979
 
 
1980
 
void Session::close_tables_for_reopen(TableList **tables)
1981
 
{
1982
 
  /*
1983
 
    If table list consists only from tables from prelocking set, table list
1984
 
    for new attempt should be empty, so we have to update list's root pointer.
1985
 
  */
1986
 
  if (lex->first_not_own_table() == *tables)
1987
 
    *tables= 0;
1988
 
  lex->chop_off_not_own_tables();
1989
 
  for (TableList *tmp= *tables; tmp; tmp= tmp->next_global)
1990
 
    tmp->table= 0;
1991
 
  close_thread_tables();
1992
 
}
1993
 
 
1994
 
bool Session::openTablesLock(TableList *tables)
1995
 
{
1996
 
  uint32_t counter;
1997
 
  bool need_reopen;
1998
 
 
1999
 
  for ( ; ; )
2000
 
  {
2001
 
    if (open_tables_from_list(&tables, &counter))
2002
 
      return true;
2003
 
 
2004
 
    if (not lock_tables(tables, counter, &need_reopen))
2005
 
      break;
2006
 
    if (not need_reopen)
2007
 
      return true;
2008
 
    close_tables_for_reopen(&tables);
2009
 
  }
2010
 
  if ((mysql_handle_derived(lex, &mysql_derived_prepare) ||
2011
 
       (fill_derived_tables() &&
2012
 
        mysql_handle_derived(lex, &mysql_derived_filling))))
2013
 
    return true;
2014
 
 
2015
 
  return false;
2016
 
}
2017
 
 
2018
 
bool Session::openTables(TableList *tables, uint32_t flags)
2019
 
{
2020
 
  uint32_t counter;
2021
 
  bool ret= fill_derived_tables();
2022
 
  assert(ret == false);
2023
 
  if (open_tables_from_list(&tables, &counter, flags) ||
2024
 
      mysql_handle_derived(lex, &mysql_derived_prepare))
2025
 
    return true;
2026
 
  return false;
2027
 
}
2028
 
 
2029
 
bool Session::rm_temporary_table(TableIdentifier &identifier)
2030
 
{
2031
 
  if (plugin::StorageEngine::dropTable(*this, identifier))
2032
 
  {
2033
 
    errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
2034
 
                  identifier.getSQLPath().c_str(), errno);
2035
 
    dumpTemporaryTableNames("rm_temporary_table()");
2036
 
 
2037
 
    return true;
2038
 
  }
2039
 
 
2040
 
  return false;
2041
 
}
2042
 
 
2043
 
bool Session::rm_temporary_table(plugin::StorageEngine *base, TableIdentifier &identifier)
2044
 
{
2045
 
  assert(base);
2046
 
 
2047
 
  if (plugin::StorageEngine::dropTable(*this, *base, identifier))
2048
 
  {
2049
 
    errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
2050
 
                  identifier.getSQLPath().c_str(), errno);
2051
 
    dumpTemporaryTableNames("rm_temporary_table()");
2052
 
 
2053
 
    return true;
2054
 
  }
2055
 
 
2056
 
  return false;
2057
 
}
2058
 
 
2059
 
/**
2060
 
  @note this will be removed, I am looking through Hudson to see if it is finding
2061
 
  any tables that are missed during cleanup.
2062
 
*/
2063
 
void Session::dumpTemporaryTableNames(const char *foo)
2064
 
{
2065
 
  Table *table;
2066
 
 
2067
 
  if (not temporary_tables)
2068
 
    return;
2069
 
 
2070
 
  cerr << "Begin Run: " << foo << "\n";
2071
 
  for (table= temporary_tables; table; table= table->next)
2072
 
  {
2073
 
    bool have_proto= false;
2074
 
 
2075
 
    message::Table *proto= table->s->getTableProto();
2076
 
    if (table->s->getTableProto())
2077
 
      have_proto= true;
2078
 
 
2079
 
    const char *answer= have_proto ? "true" : "false";
2080
 
 
2081
 
    if (have_proto)
2082
 
    {
2083
 
      cerr << "\tTable Name " << table->s->getSchemaName() << "." << table->s->table_name.str << " : " << answer << "\n";
2084
 
      cerr << "\t\t Proto " << proto->schema() << " " << proto->name() << "\n";
2085
 
    }
2086
 
    else
2087
 
      cerr << "\tTabl;e Name " << table->s->getSchemaName() << "." << table->s->table_name.str << " : " << answer << "\n";
2088
 
  }
2089
 
}
2090
 
 
2091
 
bool Session::storeTableMessage(TableIdentifier &identifier, message::Table &table_message)
2092
 
{
2093
 
  table_message_cache.insert(make_pair(identifier.getPath(), table_message));
2094
 
 
2095
 
  return true;
2096
 
}
2097
 
 
2098
 
bool Session::removeTableMessage(TableIdentifier &identifier)
2099
 
{
2100
 
  TableMessageCache::iterator iter;
2101
 
 
2102
 
  iter= table_message_cache.find(identifier.getPath());
2103
 
 
2104
 
  if (iter == table_message_cache.end())
2105
 
    return false;
2106
 
 
2107
 
  table_message_cache.erase(iter);
2108
 
 
2109
 
  return true;
2110
 
}
2111
 
 
2112
 
bool Session::getTableMessage(TableIdentifier &identifier, message::Table &table_message)
2113
 
{
2114
 
  TableMessageCache::iterator iter;
2115
 
 
2116
 
  iter= table_message_cache.find(identifier.getPath());
2117
 
 
2118
 
  if (iter == table_message_cache.end())
2119
 
    return false;
2120
 
 
2121
 
  table_message.CopyFrom(((*iter).second));
2122
 
 
2123
 
  return true;
2124
 
}
2125
 
 
2126
 
bool Session::doesTableMessageExist(TableIdentifier &identifier)
2127
 
{
2128
 
  TableMessageCache::iterator iter;
2129
 
 
2130
 
  iter= table_message_cache.find(identifier.getPath());
2131
 
 
2132
 
  if (iter == table_message_cache.end())
2133
 
  {
2134
 
    return false;
2135
 
  }
2136
 
 
2137
 
  return true;
2138
 
}
2139
 
 
2140
 
bool Session::renameTableMessage(TableIdentifier &from, TableIdentifier &to)
2141
 
{
2142
 
  TableMessageCache::iterator iter;
2143
 
 
2144
 
  table_message_cache[to.getPath()]= table_message_cache[from.getPath()];
2145
 
 
2146
 
  iter= table_message_cache.find(to.getPath());
2147
 
 
2148
 
  if (iter == table_message_cache.end())
2149
 
  {
2150
 
    return false;
2151
 
  }
2152
 
 
2153
 
  (*iter).second.set_schema(to.getSchemaName());
2154
 
  (*iter).second.set_name(to.getTableName());
2155
 
 
2156
 
  return true;
2157
 
}
2158
 
 
2159
 
} /* namespace drizzled */
 
2615
    close_temporary(table, 1, 1);
 
2616
  }
 
2617
  temporary_tables= 0;
 
2618
 
 
2619
  return;
 
2620
}