~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/session.cc

mergeĀ mainline

Show diffs side-by-side

added added

removed removed

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