~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/session.cc

  • Committer: Brian Aker
  • Date: 2010-12-08 22:35:56 UTC
  • mfrom: (1819.9.158 update-innobase)
  • Revision ID: brian@tangent.org-20101208223556-37mi4omqg7lkjzf3
Merge in Stewart's changes, 1.3 changes.

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