~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/session.cc

  • Committer: Brian Aker
  • Date: 2010-03-31 19:14:14 UTC
  • Revision ID: brian@gaz-20100331191414-9yv44mmpvf0tb7l1
Updated to use show schemas specific table.

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
22
 */
23
23
 
24
24
#include "config.h"
25
 
#include "drizzled/session.h"
26
 
#include "drizzled/session/cache.h"
 
25
#include <drizzled/session.h>
 
26
#include "drizzled/session_list.h"
27
27
#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"
 
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
40
#include "drizzled/plugin/scheduler.h"
41
41
#include "drizzled/plugin/authentication.h"
42
42
#include "drizzled/plugin/logging.h"
43
43
#include "drizzled/plugin/transactional_storage_engine.h"
44
 
#include "drizzled/plugin/query_rewrite.h"
45
44
#include "drizzled/probes.h"
46
45
#include "drizzled/table_proto.h"
47
46
#include "drizzled/db.h"
48
47
#include "drizzled/pthread_globals.h"
49
48
#include "drizzled/transaction_services.h"
50
 
#include "drizzled/drizzled.h"
51
 
 
52
 
#include "drizzled/table/instance.h"
53
49
 
54
50
#include "plugin/myisam/myisam.h"
55
51
#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
52
 
63
53
#include <fcntl.h>
64
54
#include <algorithm>
65
55
#include <climits>
66
 
#include <boost/filesystem.hpp>
67
 
 
68
 
#include "drizzled/util/backtrace.h"
69
56
 
70
57
using namespace std;
71
 
 
72
 
namespace fs=boost::filesystem;
73
58
namespace drizzled
74
59
{
75
60
 
 
61
extern "C"
 
62
{
 
63
  unsigned char *get_var_key(user_var_entry *entry, size_t *length, bool );
 
64
  void free_user_var(user_var_entry *entry);
 
65
}
 
66
 
76
67
/*
77
68
  The following is used to initialise Table_ident with a internal
78
69
  table name
81
72
char empty_c_string[1]= {0};    /* used for not defined db */
82
73
 
83
74
const char * const Session::DEFAULT_WHERE= "field list";
 
75
extern pthread_key_t THR_Session;
 
76
extern pthread_key_t THR_Mem_root;
 
77
extern uint32_t max_used_connections;
 
78
extern atomic<uint32_t> connection_count;
 
79
 
 
80
 
 
81
/****************************************************************************
 
82
** User variables
 
83
****************************************************************************/
 
84
unsigned char *get_var_key(user_var_entry *entry, size_t *length, bool )
 
85
{
 
86
  *length= entry->name.length;
 
87
  return (unsigned char*) entry->name.str;
 
88
}
 
89
 
 
90
void free_user_var(user_var_entry *entry)
 
91
{
 
92
  delete entry;
 
93
}
84
94
 
85
95
bool Key_part_spec::operator==(const Key_part_spec& other) const
86
96
{
87
97
  return length == other.length &&
88
98
         field_name.length == other.field_name.length &&
89
 
    !my_strcasecmp(system_charset_info, field_name.str, other.field_name.str);
 
99
         !strcmp(field_name.str, other.field_name.str);
90
100
}
91
101
 
92
 
Open_tables_state::Open_tables_state(uint64_t version_arg) :
93
 
  version(version_arg)
 
102
Open_tables_state::Open_tables_state(uint64_t version_arg)
 
103
  :version(version_arg), backups_available(false)
94
104
{
95
 
  open_tables= temporary_tables= derived_tables= NULL;
96
 
  extra_lock= lock= NULL;
 
105
  reset_open_tables_state();
97
106
}
98
107
 
99
108
/*
100
109
  The following functions form part of the C plugin API
101
110
*/
102
 
int mysql_tmpfile(const char *prefix)
 
111
extern "C" int mysql_tmpfile(const char *prefix)
103
112
{
104
113
  char filename[FN_REFLEN];
105
 
  int fd = internal::create_temp_file(filename, drizzle_tmpdir.c_str(), prefix, MYF(MY_WME));
 
114
  int fd = internal::create_temp_file(filename, drizzle_tmpdir, prefix, MYF(MY_WME));
106
115
  if (fd >= 0) {
107
116
    unlink(filename);
108
117
  }
110
119
  return fd;
111
120
}
112
121
 
 
122
extern "C"
113
123
int session_tablespace_op(const Session *session)
114
124
{
115
125
  return test(session->tablespace_op);
123
133
 
124
134
   @see Session::set_proc_info
125
135
 */
126
 
void set_session_proc_info(Session *session, const char *info)
 
136
extern "C" void
 
137
set_session_proc_info(Session *session, const char *info)
127
138
{
128
139
  session->set_proc_info(info);
129
140
}
130
141
 
 
142
extern "C"
131
143
const char *get_session_proc_info(Session *session)
132
144
{
133
145
  return session->get_proc_info();
144
156
  return &ha_data[monitored->getId()].resource_context[index];
145
157
}
146
158
 
 
159
extern "C"
147
160
int64_t session_test_options(const Session *session, int64_t test_options)
148
161
{
149
162
  return session->options & test_options;
150
163
}
151
164
 
 
165
extern "C"
152
166
int session_sql_command(const Session *session)
153
167
{
154
168
  return (int) session->lex->sql_command;
155
169
}
156
170
 
157
 
enum_tx_isolation session_tx_isolation(const Session *session)
 
171
extern "C"
 
172
int session_tx_isolation(const Session *session)
158
173
{
159
 
  return (enum_tx_isolation)session->variables.tx_isolation;
 
174
  return (int) session->variables.tx_isolation;
160
175
}
161
176
 
162
 
Session::Session(plugin::Client *client_arg) :
 
177
Session::Session(plugin::Client *client_arg)
 
178
  :
163
179
  Open_tables_state(refresh_version),
164
180
  mem_root(&main_mem_root),
165
 
  xa_id(0),
166
181
  lex(&main_lex),
167
 
  query(new std::string),
168
 
  _schema(new std::string("")),
169
 
  catalog("LOCAL"),
 
182
  query(),
170
183
  client(client_arg),
171
184
  scheduler(NULL),
172
185
  scheduler_arg(NULL),
173
186
  lock_id(&main_lock_id),
174
187
  user_time(0),
175
188
  ha_data(plugin::num_trx_monitored_objects),
176
 
  concurrent_execute_allowed(true),
177
189
  arg_of_last_insert_id_function(false),
178
190
  first_successful_insert_id_in_prev_stmt(0),
179
191
  first_successful_insert_id_in_cur_stmt(0),
180
192
  limit_found_rows(0),
181
 
  _global_read_lock(NONE),
182
 
  _killed(NOT_KILLED),
 
193
  global_read_lock(0),
183
194
  some_tables_deleted(false),
184
195
  no_errors(false),
185
196
  password(false),
191
202
  m_lip(NULL),
192
203
  cached_table(0),
193
204
  transaction_message(NULL),
194
 
  statement_message(NULL),
195
 
  session_event_observers(NULL),
196
 
  use_usage(false)
 
205
  statement_message(NULL)
197
206
{
 
207
  memset(process_list_info, 0, PROCESS_LIST_WIDTH);
198
208
  client->setSession(this);
199
209
 
200
210
  /*
204
214
  */
205
215
  memory::init_sql_alloc(&main_mem_root, memory::ROOT_MIN_BLOCK_SIZE, 0);
206
216
  thread_stack= NULL;
207
 
  count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;
 
217
  count_cuted_fields= CHECK_FIELD_IGNORE;
 
218
  killed= NOT_KILLED;
208
219
  col_access= 0;
209
220
  tmp_table= 0;
210
221
  used_tables= 0;
222
233
  query_id= 0;
223
234
  warn_query_id= 0;
224
235
  mysys_var= 0;
225
 
  scoreboard_index= -1;
226
236
  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;
 
237
  cleanup_done= abort_on_warning= no_warnings_for_error= false;
 
238
  pthread_mutex_init(&LOCK_delete, MY_MUTEX_INIT_FAST);
232
239
 
233
240
  /* Variables with default values */
234
241
  proc_info="login";
260
267
 
261
268
  /* Initialize sub structures */
262
269
  memory::init_sql_alloc(&warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE);
 
270
  hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0,
 
271
            (hash_get_key) get_var_key,
 
272
            (hash_free_key) free_user_var, 0);
263
273
 
264
274
  substitute_null_with_insert_id = false;
265
 
  lock_info.init(); /* safety: will be reset after start */
 
275
  thr_lock_info_init(&lock_info); /* safety: will be reset after start */
266
276
  thr_lock_owner_init(&main_lock_id, &lock_info);
267
277
 
268
278
  m_internal_handler= NULL;
269
 
  
270
 
  plugin::EventObserver::registerSessionEvents(*this); 
271
279
}
272
280
 
273
281
void Session::free_items()
302
310
  return false;                                 // 'false', as per coding style
303
311
}
304
312
 
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
 
 
325
313
void Session::pop_internal_handler()
326
314
{
327
315
  assert(m_internal_handler != NULL);
328
316
  m_internal_handler= NULL;
329
317
}
330
318
 
331
 
void Session::get_xid(DRIZZLE_XID *xid)
332
 
{
333
 
  *xid = *(DRIZZLE_XID *) &transaction.xid_state.xid;
334
 
}
 
319
#if defined(__cplusplus)
 
320
extern "C" {
 
321
#endif
 
322
 
 
323
void *session_alloc(Session *session, unsigned int size)
 
324
{
 
325
  return session->alloc(size);
 
326
}
 
327
 
 
328
void *session_calloc(Session *session, unsigned int size)
 
329
{
 
330
  return session->calloc(size);
 
331
}
 
332
 
 
333
char *session_strdup(Session *session, const char *str)
 
334
{
 
335
  return session->strdup(str);
 
336
}
 
337
 
 
338
char *session_strmake(Session *session, const char *str, unsigned int size)
 
339
{
 
340
  return session->strmake(str, size);
 
341
}
 
342
 
 
343
void *session_memdup(Session *session, const void* str, unsigned int size)
 
344
{
 
345
  return session->memdup(str, size);
 
346
}
 
347
 
 
348
void session_get_xid(const Session *session, DRIZZLE_XID *xid)
 
349
{
 
350
  *xid = *(DRIZZLE_XID *) &session->transaction.xid_state.xid;
 
351
}
 
352
 
 
353
#if defined(__cplusplus)
 
354
}
 
355
#endif
335
356
 
336
357
/* Do operations that may take a long time */
337
358
 
339
360
{
340
361
  assert(cleanup_done == false);
341
362
 
342
 
  setKilled(KILL_CONNECTION);
 
363
  killed= KILL_CONNECTION;
343
364
#ifdef ENABLE_WHEN_BINLOG_WILL_BE_ABLE_TO_PREPARE
344
365
  if (transaction.xid_state.xa_state == XA_PREPARED)
345
366
  {
348
369
#endif
349
370
  {
350
371
    TransactionServices &transaction_services= TransactionServices::singleton();
351
 
    transaction_services.rollbackTransaction(this, true);
 
372
    transaction_services.ha_rollback_trans(this, true);
352
373
    xid_cache_delete(&transaction.xid_state);
353
374
  }
354
 
 
355
 
  for (UserVars::iterator iter= user_vars.begin();
356
 
       iter != user_vars.end();
357
 
       iter++)
358
 
  {
359
 
    user_var_entry *entry= (*iter).second;
360
 
    delete entry;
361
 
  }
362
 
  user_vars.clear();
363
 
 
364
 
 
 
375
  hash_free(&user_vars);
365
376
  close_temporary_tables();
366
377
 
367
378
  if (global_read_lock)
368
 
  {
369
 
    unlockGlobalReadLock();
370
 
  }
 
379
    unlock_global_read_lock(this);
371
380
 
372
381
  cleanup_done= true;
373
382
}
374
383
 
375
384
Session::~Session()
376
385
{
377
 
  this->checkSentry();
 
386
  Session_CHECK_SENTRY(this);
 
387
  add_to_status(&global_status_var, &status_var);
378
388
 
379
389
  if (client->isConnected())
380
390
  {
396
406
  plugin::StorageEngine::closeConnection(this);
397
407
  plugin_sessionvar_cleanup(this);
398
408
 
399
 
  warn_root.free_root(MYF(0));
 
409
  free_root(&warn_root,MYF(0));
400
410
  mysys_var=0;                                  // Safety (shouldn't be needed)
401
411
  dbug_sentry= Session_SENTRY_GONE;
402
412
 
403
 
  main_mem_root.free_root(MYF(0));
404
 
  currentMemRoot().release();
405
 
  currentSession().release();
 
413
  free_root(&main_mem_root, MYF(0));
 
414
  pthread_setspecific(THR_Session,  0);
406
415
 
407
416
  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
 
 
 
417
 
 
418
  /* Ensure that no one is using Session */
 
419
  pthread_mutex_unlock(&LOCK_delete);
 
420
  pthread_mutex_destroy(&LOCK_delete);
 
421
}
 
422
 
 
423
/*
 
424
  Add all status variables to another status variable array
 
425
 
 
426
  SYNOPSIS
 
427
   add_to_status()
 
428
   to_var       add to this array
 
429
   from_var     from this array
 
430
 
 
431
  NOTES
 
432
    This function assumes that all variables are long/ulong.
 
433
    If this assumption will change, then we have to explictely add
 
434
    the other variables after the while loop
 
435
*/
 
436
void add_to_status(system_status_var *to_var, system_status_var *from_var)
 
437
{
 
438
  ulong *end= (ulong*) ((unsigned char*) to_var +
 
439
                        offsetof(system_status_var, last_system_status_var) +
 
440
                        sizeof(ulong));
 
441
  ulong *to= (ulong*) to_var, *from= (ulong*) from_var;
 
442
 
 
443
  while (to != end)
 
444
    *(to++)+= *(from++);
 
445
}
 
446
 
 
447
/*
 
448
  Add the difference between two status variable arrays to another one.
 
449
 
 
450
  SYNOPSIS
 
451
    add_diff_to_status
 
452
    to_var       add to this array
 
453
    from_var     from this array
 
454
    dec_var      minus this array
 
455
 
 
456
  NOTE
 
457
    This function assumes that all variables are long/ulong.
 
458
*/
 
459
void add_diff_to_status(system_status_var *to_var, system_status_var *from_var,
 
460
                        system_status_var *dec_var)
 
461
{
 
462
  ulong *end= (ulong*) ((unsigned char*) to_var + offsetof(system_status_var,
 
463
                                                  last_system_status_var) +
 
464
                        sizeof(ulong));
 
465
  ulong *to= (ulong*) to_var, *from= (ulong*) from_var, *dec= (ulong*) dec_var;
 
466
 
 
467
  while (to != end)
 
468
    *(to++)+= *(from++) - *(dec++);
 
469
}
 
470
 
 
471
void Session::awake(Session::killed_state state_to_set)
 
472
{
 
473
  Session_CHECK_SENTRY(this);
 
474
  safe_mutex_assert_owner(&LOCK_delete);
 
475
 
 
476
  killed= state_to_set;
433
477
  if (state_to_set != Session::KILL_QUERY)
434
478
  {
 
479
    scheduler->killSession(this);
435
480
    DRIZZLE_CONNECTION_DONE(thread_id);
436
481
  }
437
 
 
438
482
  if (mysys_var)
439
483
  {
440
 
    boost_unique_lock_t scopedLock(mysys_var->mutex);
 
484
    pthread_mutex_lock(&mysys_var->mutex);
441
485
    /*
442
 
      "
443
486
      This broadcast could be up in the air if the victim thread
444
487
      exits the cond in the time between read and broadcast, but that is
445
488
      ok since all we want to do is to make the victim thread get out
460
503
    */
461
504
    if (mysys_var->current_cond && mysys_var->current_mutex)
462
505
    {
463
 
      mysys_var->current_mutex->lock();
464
 
      mysys_var->current_cond->notify_all();
465
 
      mysys_var->current_mutex->unlock();
 
506
      pthread_mutex_lock(mysys_var->current_mutex);
 
507
      pthread_cond_broadcast(mysys_var->current_cond);
 
508
      pthread_mutex_unlock(mysys_var->current_mutex);
466
509
    }
 
510
    pthread_mutex_unlock(&mysys_var->mutex);
467
511
  }
468
512
}
469
513
 
479
523
  */
480
524
  assert(thread_stack);
481
525
 
482
 
  currentSession().release();
483
 
  currentSession().reset(this);
484
 
 
485
 
  currentMemRoot().release();
486
 
  currentMemRoot().reset(&mem_root);
 
526
  if (pthread_setspecific(THR_Session,  this) ||
 
527
      pthread_setspecific(THR_Mem_root, &mem_root))
 
528
    return true;
487
529
 
488
530
  mysys_var=my_thread_var;
489
531
 
492
534
    This allows us to move Session to different threads if needed.
493
535
  */
494
536
  mysys_var->id= thread_id;
 
537
  real_id= pthread_self();                      // For debugging
495
538
 
496
539
  /*
497
540
    We have to call thr_lock_info_init() again here as Session may have been
498
541
    created in another thread
499
542
  */
500
 
  lock_info.init();
501
 
 
 
543
  thr_lock_info_init(&lock_info);
502
544
  return false;
503
545
}
504
546
 
518
560
  command= COM_SLEEP;
519
561
  set_time();
520
562
 
521
 
  mem_root->reset_root_defaults(variables.query_alloc_block_size,
522
 
                                variables.query_prealloc_size);
 
563
  reset_root_defaults(mem_root, variables.query_alloc_block_size,
 
564
                      variables.query_prealloc_size);
523
565
  transaction.xid_state.xid.null();
524
566
  transaction.xid_state.in_session=1;
525
 
  if (use_usage)
526
 
    resetUsage();
527
567
}
528
568
 
529
569
bool Session::initGlobals()
531
571
  if (storeGlobals())
532
572
  {
533
573
    disconnect(ER_OUT_OF_RESOURCES, true);
534
 
    status_var.aborted_connects++;
 
574
    statistic_increment(aborted_connects, &LOCK_status);
535
575
    return true;
536
576
  }
537
577
  return false;
547
587
 
548
588
  prepareForQueries();
549
589
 
550
 
  while (not client->haveError() && getKilled() != KILL_CONNECTION)
 
590
  while (! client->haveError() && killed != KILL_CONNECTION)
551
591
  {
552
 
    if (not executeStatement())
 
592
    if (! executeStatement())
553
593
      break;
554
594
  }
555
595
 
556
596
  disconnect(0, true);
557
597
}
558
598
 
559
 
bool Session::schedule(Session::shared_ptr &arg)
 
599
bool Session::schedule()
560
600
{
561
 
  arg->scheduler= plugin::Scheduler::getScheduler();
562
 
  assert(arg->scheduler);
 
601
  scheduler= plugin::Scheduler::getScheduler();
 
602
  assert(scheduler);
563
603
 
564
604
  connection_count.increment();
565
605
 
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());
 
606
  if (connection_count > max_used_connections)
 
607
    max_used_connections= connection_count;
 
608
 
 
609
  thread_id= variables.pseudo_thread_id= global_thread_id++;
 
610
 
 
611
  pthread_mutex_lock(&LOCK_thread_count);
 
612
  getSessionList().push_back(this);
 
613
  pthread_mutex_unlock(&LOCK_thread_count);
 
614
 
 
615
  if (scheduler->addSession(this))
 
616
  {
 
617
    DRIZZLE_CONNECTION_START(thread_id);
584
618
    char error_message_buff[DRIZZLE_ERRMSG_SIZE];
585
619
 
586
 
    arg->setKilled(Session::KILL_CONNECTION);
 
620
    killed= Session::KILL_CONNECTION;
587
621
 
588
 
    arg->status_var.aborted_connects++;
 
622
    statistic_increment(aborted_connects, &LOCK_status);
589
623
 
590
624
    /* Can't use my_error() since store_globals has not been called. */
591
625
    /* TODO replace will better error message */
592
626
    snprintf(error_message_buff, sizeof(error_message_buff),
593
627
             ER(ER_CANT_CREATE_THREAD), 1);
594
 
    arg->client->sendError(ER_CANT_CREATE_THREAD, error_message_buff);
595
 
 
 
628
    client->sendError(ER_CANT_CREATE_THREAD, error_message_buff);
596
629
    return true;
597
630
  }
598
631
 
600
633
}
601
634
 
602
635
 
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)
 
636
const char* Session::enter_cond(pthread_cond_t *cond,
 
637
                                pthread_mutex_t* mutex,
 
638
                                const char* msg)
615
639
{
616
640
  const char* old_msg = get_proc_info();
617
641
  safe_mutex_assert_owner(mutex);
618
 
  mysys_var->current_mutex = &mutex;
619
 
  mysys_var->current_cond = &cond;
 
642
  mysys_var->current_mutex = mutex;
 
643
  mysys_var->current_cond = cond;
620
644
  this->set_proc_info(msg);
621
645
  return old_msg;
622
646
}
629
653
    locked (if that would not be the case, you'll get a deadlock if someone
630
654
    does a Session::awake() on you).
631
655
  */
632
 
  mysys_var->current_mutex->unlock();
633
 
  boost_unique_lock_t scopedLock(mysys_var->mutex);
 
656
  pthread_mutex_unlock(mysys_var->current_mutex);
 
657
  pthread_mutex_lock(&mysys_var->mutex);
634
658
  mysys_var->current_mutex = 0;
635
659
  mysys_var->current_cond = 0;
636
660
  this->set_proc_info(old_msg);
 
661
  pthread_mutex_unlock(&mysys_var->mutex);
637
662
}
638
663
 
639
664
bool Session::authenticate()
640
665
{
641
 
  lex->start(this);
 
666
  lex_start(this);
642
667
  if (client->authenticate())
643
668
    return false;
644
669
 
645
 
  status_var.aborted_connects++;
646
 
 
 
670
  statistic_increment(aborted_connects, &LOCK_status);
647
671
  return true;
648
672
}
649
673
 
650
 
bool Session::checkUser(const std::string &passwd_str,
651
 
                        const std::string &in_db)
 
674
bool Session::checkUser(const char *passwd, uint32_t passwd_len, const char *in_db)
652
675
{
 
676
  const string passwd_str(passwd, passwd_len);
653
677
  bool is_authenticated=
654
678
    plugin::Authentication::isAuthenticated(getSecurityContext(),
655
679
                                            passwd_str);
656
680
 
657
681
  if (is_authenticated != true)
658
682
  {
659
 
    status_var.access_denied++;
660
683
    /* isAuthenticated has pushed the error message */
661
684
    return false;
662
685
  }
663
686
 
664
687
  /* Change database if necessary */
665
 
  if (not in_db.empty())
 
688
  if (in_db && in_db[0])
666
689
  {
667
690
    SchemaIdentifier identifier(in_db);
668
691
    if (mysql_change_db(this, identifier))
672
695
    }
673
696
  }
674
697
  my_ok();
675
 
  password= not passwd_str.empty();
 
698
  password= test(passwd_len);          // remember for error messages
676
699
 
677
700
  /* Ready to handle queries */
678
701
  return true;
694
717
  main_da.reset_diagnostics_area();
695
718
 
696
719
  if (client->readCommand(&l_packet, &packet_length) == false)
697
 
  {
698
 
    return false;
699
 
  }
700
 
 
701
 
  if (getKilled() == KILL_CONNECTION)
702
720
    return false;
703
721
 
704
722
  if (packet_length == 0)
705
723
    return true;
706
724
 
707
 
  l_command= static_cast<enum_server_command>(l_packet[0]);
 
725
  l_command= (enum enum_server_command) (unsigned char) l_packet[0];
708
726
 
709
727
  if (command >= COM_END)
710
728
    command= COM_END;                           // Wrong command
711
729
 
712
730
  assert(packet_length);
713
 
  return not dispatch_command(l_command, this, l_packet+1, (uint32_t) (packet_length-1));
 
731
  return ! dispatch_command(l_command, this, l_packet+1, (uint32_t) (packet_length-1));
714
732
}
715
733
 
716
734
bool Session::readAndStoreQuery(const char *in_packet, uint32_t in_packet_length)
722
740
    in_packet_length--;
723
741
  }
724
742
  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])))
 
743
  while (in_packet_length > 0 &&
 
744
         (pos[-1] == ';' || my_isspace(charset() ,pos[-1])))
726
745
  {
727
746
    pos--;
728
747
    in_packet_length--;
729
748
  }
730
749
 
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));
 
750
  query.assign(in_packet, in_packet + in_packet_length);
739
751
 
740
752
  return true;
741
753
}
760
772
       * (Which of course should never happen...)
761
773
       */
762
774
      server_status&= ~SERVER_STATUS_IN_TRANS;
763
 
      if (transaction_services.commitTransaction(this, true))
 
775
      if (transaction_services.ha_commit_trans(this, true))
764
776
        result= false;
765
777
      options&= ~(OPTION_BEGIN);
766
778
      break;
777
789
    case ROLLBACK_AND_CHAIN:
778
790
    {
779
791
      server_status&= ~SERVER_STATUS_IN_TRANS;
780
 
      if (transaction_services.rollbackTransaction(this, true))
 
792
      if (transaction_services.ha_rollback_trans(this, true))
781
793
        result= false;
782
794
      options&= ~(OPTION_BEGIN);
783
795
      if (result == true && (completion == ROLLBACK_AND_CHAIN))
790
802
  }
791
803
 
792
804
  if (result == false)
793
 
  {
794
805
    my_error(killed_errno(), MYF(0));
795
 
  }
796
806
  else if ((result == true) && do_release)
797
 
  {
798
 
    setKilled(Session::KILL_CONNECTION);
799
 
  }
 
807
    killed= Session::KILL_CONNECTION;
800
808
 
801
809
  return result;
802
810
}
814
822
  if (options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
815
823
  {
816
824
    server_status&= ~SERVER_STATUS_IN_TRANS;
817
 
    if (transaction_services.commitTransaction(this, true))
 
825
    if (transaction_services.ha_commit_trans(this, true))
818
826
      result= false;
819
827
  }
820
828
  options&= ~(OPTION_BEGIN);
865
873
  free_items();
866
874
  /* Reset where. */
867
875
  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
876
}
875
877
 
876
878
/**
897
899
  if (allocate_lex_string)
898
900
    if (!(lex_str= (LEX_STRING *)alloc(sizeof(LEX_STRING))))
899
901
      return 0;
900
 
  if (!(lex_str->str= mem_root->strmake_root(str, length)))
 
902
  if (!(lex_str->str= strmake_root(mem_root, str, length)))
901
903
    return 0;
902
904
  lex_str->length= length;
903
905
  return lex_str;
955
957
  my_message(errcode, err, MYF(0));
956
958
  if (file > 0)
957
959
  {
958
 
    (void) cache->end_io_cache();
 
960
    (void) end_io_cache(cache);
959
961
    (void) internal::my_close(file, MYF(0));
960
 
    (void) internal::my_delete(path.file_string().c_str(), MYF(0));             // Delete file on error
 
962
    (void) internal::my_delete(path, MYF(0));           // Delete file on error
961
963
    file= -1;
962
964
  }
963
965
}
965
967
 
966
968
bool select_to_file::send_eof()
967
969
{
968
 
  int error= test(cache->end_io_cache());
 
970
  int error= test(end_io_cache(cache));
969
971
  if (internal::my_close(file, MYF(MY_WME)))
970
972
    error= 1;
971
973
  if (!error)
987
989
  /* In case of error send_eof() may be not called: close the file here. */
988
990
  if (file >= 0)
989
991
  {
990
 
    (void) cache->end_io_cache();
 
992
    (void) end_io_cache(cache);
991
993
    (void) internal::my_close(file, MYF(0));
992
994
    file= -1;
993
995
  }
994
 
  path= "";
 
996
  path[0]= '\0';
995
997
  row_count= 0;
996
998
}
997
999
 
1001
1003
    cache(static_cast<internal::IO_CACHE *>(memory::sql_calloc(sizeof(internal::IO_CACHE)))),
1002
1004
    row_count(0L)
1003
1005
{
1004
 
  path= "";
 
1006
  path[0]=0;
1005
1007
}
1006
1008
 
1007
1009
select_to_file::~select_to_file()
1035
1037
*/
1036
1038
 
1037
1039
 
1038
 
static int create_file(Session *session,
1039
 
                       fs::path &target_path,
1040
 
                       file_exchange *exchange,
1041
 
                       internal::IO_CACHE *cache)
 
1040
static int create_file(Session *session, char *path, file_exchange *exchange, internal::IO_CACHE *cache)
1042
1041
{
1043
 
  fs::path to_file(exchange->file_name);
1044
1042
  int file;
1045
 
 
1046
 
  if (not to_file.has_root_directory())
 
1043
  uint32_t option= MY_UNPACK_FILENAME | MY_RELATIVE_PATH;
 
1044
 
 
1045
#ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS
 
1046
  option|= MY_REPLACE_DIR;                      // Force use of db directory
 
1047
#endif
 
1048
 
 
1049
  if (!internal::dirname_length(exchange->file_name))
1047
1050
  {
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;
 
1051
    strcpy(path, drizzle_real_data_home);
 
1052
    if (! session->db.empty())
 
1053
      strncat(path, session->db.c_str(), FN_REFLEN-strlen(drizzle_real_data_home)-1);
 
1054
    (void) internal::fn_format(path, exchange->file_name, path, "", option);
1064
1055
  }
1065
1056
  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))
 
1057
    (void) internal::fn_format(path, exchange->file_name, drizzle_real_data_home, "", option);
 
1058
 
 
1059
  if (opt_secure_file_priv &&
 
1060
      strncmp(opt_secure_file_priv, path, strlen(opt_secure_file_priv)))
 
1061
  {
 
1062
    /* Write only allowed to dir or subdir specified by secure_file_priv */
 
1063
    my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
 
1064
    return -1;
 
1065
  }
 
1066
 
 
1067
  if (!access(path, F_OK))
1081
1068
  {
1082
1069
    my_error(ER_FILE_EXISTS_ERROR, MYF(0), exchange->file_name);
1083
1070
    return -1;
1084
1071
  }
1085
1072
  /* 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)
 
1073
  if ((file= internal::my_create(path, 0666, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0)
1087
1074
    return file;
1088
1075
  (void) fchmod(file, 0666);                    // Because of umask()
1089
 
  if (cache->init_io_cache(file, 0L, internal::WRITE_CACHE, 0L, 1, MYF(MY_WME)))
 
1076
  if (init_io_cache(cache, file, 0L, internal::WRITE_CACHE, 0L, 1, MYF(MY_WME)))
1090
1077
  {
1091
1078
    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
 
1079
    internal::my_delete(path, MYF(0));  // Delete file on error, it was just created
1093
1080
    return -1;
1094
1081
  }
1095
1082
  return file;
1103
1090
  bool string_results= false, non_string_results= false;
1104
1091
  unit= u;
1105
1092
  if ((uint32_t) strlen(exchange->file_name) + NAME_LEN >= FN_REFLEN)
1106
 
  {
1107
 
    path= exchange->file_name;
1108
 
  }
 
1093
    strncpy(path,exchange->file_name,FN_REFLEN-1);
1109
1094
 
1110
1095
  /* Check if there is any blobs in data */
1111
1096
  {
1115
1100
    {
1116
1101
      if (item->max_length >= MAX_BLOB_WIDTH)
1117
1102
      {
1118
 
        blob_flag=1;
1119
 
        break;
 
1103
        blob_flag=1;
 
1104
        break;
1120
1105
      }
1121
 
 
1122
1106
      if (item->result_type() == STRING_RESULT)
1123
1107
        string_results= true;
1124
1108
      else
1159
1143
  return 0;
1160
1144
}
1161
1145
 
 
1146
 
 
1147
#define NEED_ESCAPING(x) ((int) (unsigned char) (x) == escape_char    || \
 
1148
                          (enclosed ? (int) (unsigned char) (x) == field_sep_char      \
 
1149
                                    : (int) (unsigned char) (x) == field_term_char) || \
 
1150
                          (int) (unsigned char) (x) == line_sep_char  || \
 
1151
                          !(x))
 
1152
 
1162
1153
bool select_export::send_data(List<Item> &items)
1163
1154
{
1164
1155
  char buff[MAX_FIELD_WIDTH],null_buff[2],space[MAX_FIELD_WIDTH];
1169
1160
  if (unit->offset_limit_cnt)
1170
1161
  {                                             // using limit offset,count
1171
1162
    unit->offset_limit_cnt--;
1172
 
    return false;
 
1163
    return(0);
1173
1164
  }
1174
1165
  row_count++;
1175
1166
  Item *item;
1178
1169
 
1179
1170
  if (my_b_write(cache,(unsigned char*) exchange->line_start->ptr(),
1180
1171
                 exchange->line_start->length()))
1181
 
    return true;
1182
 
 
 
1172
    goto err;
1183
1173
  while ((item=li++))
1184
1174
  {
1185
1175
    Item_result result_type=item->result_type();
1190
1180
    {
1191
1181
      if (my_b_write(cache,(unsigned char*) exchange->enclosed->ptr(),
1192
1182
                     exchange->enclosed->length()))
1193
 
        return true;
 
1183
        goto err;
1194
1184
    }
1195
1185
    if (!res)
1196
1186
    {                                           // NULL
1201
1191
          null_buff[0]=escape_char;
1202
1192
          null_buff[1]='N';
1203
1193
          if (my_b_write(cache,(unsigned char*) null_buff,2))
1204
 
            return true;
 
1194
            goto err;
1205
1195
        }
1206
1196
        else if (my_b_write(cache,(unsigned char*) "NULL",4))
1207
 
          return true;
 
1197
          goto err;
1208
1198
      }
1209
1199
      else
1210
1200
      {
1214
1204
    else
1215
1205
    {
1216
1206
      if (fixed_row_size)
1217
 
        used_length= min(res->length(), static_cast<size_t>(item->max_length));
 
1207
        used_length= min(res->length(),item->max_length);
1218
1208
      else
1219
1209
        used_length= res->length();
1220
1210
 
1276
1266
            assert before the loop makes that sure.
1277
1267
          */
1278
1268
 
1279
 
          if ((needs_escaping(*pos, enclosed) ||
 
1269
          if ((NEED_ESCAPING(*pos) ||
1280
1270
               (check_second_byte &&
1281
1271
                my_mbcharlen(character_set_client, (unsigned char) *pos) == 2 &&
1282
1272
                pos + 1 < end &&
1283
 
                needs_escaping(pos[1], enclosed))) &&
 
1273
                NEED_ESCAPING(pos[1]))) &&
1284
1274
              /*
1285
1275
                Don't escape field_term_char by doubling - doubling is only
1286
1276
                valid for ENCLOSED BY characters:
1295
1285
            tmp_buff[1]= *pos ? *pos : '0';
1296
1286
            if (my_b_write(cache,(unsigned char*) start,(uint32_t) (pos-start)) ||
1297
1287
                my_b_write(cache,(unsigned char*) tmp_buff,2))
1298
 
              return true;
 
1288
              goto err;
1299
1289
            start=pos+1;
1300
1290
          }
1301
1291
        }
1302
1292
        if (my_b_write(cache,(unsigned char*) start,(uint32_t) (pos-start)))
1303
 
          return true;
 
1293
          goto err;
1304
1294
      }
1305
1295
      else if (my_b_write(cache,(unsigned char*) res->ptr(),used_length))
1306
 
        return true;
 
1296
        goto err;
1307
1297
    }
1308
1298
    if (fixed_row_size)
1309
1299
    {                                           // Fill with space
1319
1309
        for (; length > sizeof(space) ; length-=sizeof(space))
1320
1310
        {
1321
1311
          if (my_b_write(cache,(unsigned char*) space,sizeof(space)))
1322
 
            return true;
 
1312
            goto err;
1323
1313
        }
1324
1314
        if (my_b_write(cache,(unsigned char*) space,length))
1325
 
          return true;
 
1315
          goto err;
1326
1316
      }
1327
1317
    }
1328
1318
    if (res && enclosed)
1329
1319
    {
1330
1320
      if (my_b_write(cache, (unsigned char*) exchange->enclosed->ptr(),
1331
1321
                     exchange->enclosed->length()))
1332
 
        return true;
 
1322
        goto err;
1333
1323
    }
1334
1324
    if (--items_left)
1335
1325
    {
1336
1326
      if (my_b_write(cache, (unsigned char*) exchange->field_term->ptr(),
1337
1327
                     field_term_length))
1338
 
        return true;
 
1328
        goto err;
1339
1329
    }
1340
1330
  }
1341
1331
  if (my_b_write(cache,(unsigned char*) exchange->line_term->ptr(),
1342
1332
                 exchange->line_term->length()))
1343
 
  {
1344
 
    return true;
1345
 
  }
1346
 
 
1347
 
  return false;
 
1333
    goto err;
 
1334
  return(0);
 
1335
err:
 
1336
  return(1);
1348
1337
}
1349
1338
 
1350
1339
 
1377
1366
  if (row_count++ > 1)
1378
1367
  {
1379
1368
    my_message(ER_TOO_MANY_ROWS, ER(ER_TOO_MANY_ROWS), MYF(0));
1380
 
    return 1;
 
1369
    goto err;
1381
1370
  }
1382
1371
  while ((item=li++))
1383
1372
  {
1385
1374
    if (!res)                                   // If NULL
1386
1375
    {
1387
1376
      if (my_b_write(cache,(unsigned char*) "",1))
1388
 
        return 1;
 
1377
        goto err;
1389
1378
    }
1390
1379
    else if (my_b_write(cache,(unsigned char*) res->ptr(),res->length()))
1391
1380
    {
1392
 
      my_error(ER_ERROR_ON_WRITE, MYF(0), path.file_string().c_str(), errno);
1393
 
      return 1;
 
1381
      my_error(ER_ERROR_ON_WRITE, MYF(0), path, errno);
 
1382
      goto err;
1394
1383
    }
1395
1384
  }
1396
1385
  return(0);
 
1386
err:
 
1387
  return(1);
1397
1388
}
1398
1389
 
1399
1390
 
1451
1442
      switch (val_item->result_type())
1452
1443
      {
1453
1444
      case REAL_RESULT:
1454
 
        op= &select_max_min_finder_subselect::cmp_real;
1455
 
        break;
 
1445
        op= &select_max_min_finder_subselect::cmp_real;
 
1446
        break;
1456
1447
      case INT_RESULT:
1457
 
        op= &select_max_min_finder_subselect::cmp_int;
1458
 
        break;
 
1448
        op= &select_max_min_finder_subselect::cmp_int;
 
1449
        break;
1459
1450
      case STRING_RESULT:
1460
 
        op= &select_max_min_finder_subselect::cmp_str;
1461
 
        break;
 
1451
        op= &select_max_min_finder_subselect::cmp_str;
 
1452
        break;
1462
1453
      case DECIMAL_RESULT:
1463
1454
        op= &select_max_min_finder_subselect::cmp_decimal;
1464
1455
        break;
1465
1456
      case ROW_RESULT:
1466
1457
        // This case should never be choosen
1467
 
        assert(0);
1468
 
        op= 0;
 
1458
        assert(0);
 
1459
        op= 0;
1469
1460
      }
1470
1461
    }
1471
1462
    cache->store(val_item);
1554
1545
void Session::end_statement()
1555
1546
{
1556
1547
  /* Cleanup SQL processing state to reuse this statement in next query. */
1557
 
  lex->end();
1558
 
  query_cache_key= ""; // reset the cache key
1559
 
  resetResultsetMessage();
 
1548
  lex_end(lex);
1560
1549
}
1561
1550
 
1562
1551
bool Session::copy_db_to(char **p_db, size_t *p_db_length)
1563
1552
{
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
 
 
 
1553
  if (db.empty())
 
1554
  {
 
1555
    my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
 
1556
    return true;
 
1557
  }
 
1558
  *p_db= strmake(db.c_str(), db.length());
 
1559
  *p_db_length= db.length();
1580
1560
  return false;
1581
1561
}
1582
1562
 
1616
1596
}
1617
1597
 
1618
1598
 
1619
 
void Session::set_db(const std::string &new_db)
 
1599
/****************************************************************************
 
1600
  Handling of open and locked tables states.
 
1601
 
 
1602
  This is used when we want to open/lock (and then close) some tables when
 
1603
  we already have a set of tables open and locked. We use these methods for
 
1604
  access to mysql.proc table to find definitions of stored routines.
 
1605
****************************************************************************/
 
1606
 
 
1607
void Session::reset_n_backup_open_tables_state(Open_tables_state *backup)
 
1608
{
 
1609
  backup->set_open_tables_state(this);
 
1610
  reset_open_tables_state();
 
1611
  backups_available= false;
 
1612
}
 
1613
 
 
1614
 
 
1615
void Session::restore_backup_open_tables_state(Open_tables_state *backup)
 
1616
{
 
1617
  /*
 
1618
    Before we will throw away current open tables state we want
 
1619
    to be sure that it was properly cleaned up.
 
1620
  */
 
1621
  assert(open_tables == 0 && temporary_tables == 0 &&
 
1622
              derived_tables == 0 &&
 
1623
              lock == 0);
 
1624
  set_open_tables_state(backup);
 
1625
}
 
1626
 
 
1627
bool Session::set_db(const std::string &new_db)
1620
1628
{
1621
1629
  /* Do not reallocate memory if current chunk is big enough. */
1622
1630
  if (new_db.length())
1623
 
  {
1624
 
    _schema.reset(new std::string(new_db));
1625
 
  }
 
1631
    db= new_db;
1626
1632
  else
1627
 
  {
1628
 
    _schema.reset(new std::string(""));
1629
 
  }
1630
 
}
1631
 
 
 
1633
    db.clear();
 
1634
 
 
1635
  return false;
 
1636
}
 
1637
 
 
1638
 
 
1639
 
 
1640
 
 
1641
/**
 
1642
  Check the killed state of a user thread
 
1643
  @param session  user thread
 
1644
  @retval 0 the user thread is active
 
1645
  @retval 1 the user thread has been killed
 
1646
*/
 
1647
extern "C" int session_killed(const Session *session)
 
1648
{
 
1649
  return(session->killed);
 
1650
}
 
1651
 
 
1652
/**
 
1653
  Return the session id of a user session
 
1654
  @param pointer to Session object
 
1655
  @return session's id
 
1656
*/
 
1657
extern "C" unsigned long session_get_thread_id(const Session *session)
 
1658
{
 
1659
  return (unsigned long) session->getSessionId();
 
1660
}
 
1661
 
 
1662
 
 
1663
const struct charset_info_st *session_charset(Session *session)
 
1664
{
 
1665
  return(session->charset());
 
1666
}
 
1667
 
 
1668
int session_non_transactional_update(const Session *session)
 
1669
{
 
1670
  return(session->transaction.all.hasModifiedNonTransData());
 
1671
}
 
1672
 
 
1673
void session_mark_transaction_to_rollback(Session *session, bool all)
 
1674
{
 
1675
  mark_transaction_to_rollback(session, all);
 
1676
}
1632
1677
 
1633
1678
/**
1634
1679
  Mark transaction to rollback and mark error as fatal to a sub-statement.
1651
1696
  plugin_sessionvar_cleanup(this);
1652
1697
 
1653
1698
  /* If necessary, log any aborted or unauthorized connections */
1654
 
  if (getKilled() || client->wasAborted())
1655
 
  {
1656
 
    status_var.aborted_threads++;
1657
 
  }
 
1699
  if (killed || client->wasAborted())
 
1700
    statistic_increment(aborted_threads, &LOCK_status);
1658
1701
 
1659
1702
  if (client->wasAborted())
1660
1703
  {
1661
 
    if (not getKilled() && variables.log_warnings > 1)
 
1704
    if (! killed && variables.log_warnings > 1)
1662
1705
    {
1663
1706
      SecurityContext *sctx= &security_ctx;
1664
1707
 
1665
1708
      errmsg_printf(ERRMSG_LVL_WARN, ER(ER_NEW_ABORTING_CONNECTION)
1666
1709
                  , thread_id
1667
 
                  , (_schema->empty() ? "unconnected" : _schema->c_str())
 
1710
                  , (db.empty() ? "unconnected" : db.c_str())
1668
1711
                  , sctx->getUser().empty() == false ? sctx->getUser().c_str() : "unauthenticated"
1669
1712
                  , sctx->getIp().c_str()
1670
1713
                  , (main_da.is_error() ? main_da.message() : ER(ER_UNKNOWN_ERROR)));
1673
1716
 
1674
1717
  /* Close out our connection to the client */
1675
1718
  if (should_lock)
1676
 
    session::Cache::singleton().mutex().lock();
1677
 
 
1678
 
  setKilled(Session::KILL_CONNECTION);
1679
 
 
 
1719
    (void) pthread_mutex_lock(&LOCK_thread_count);
 
1720
  killed= Session::KILL_CONNECTION;
1680
1721
  if (client->isConnected())
1681
1722
  {
1682
1723
    if (errcode)
1686
1727
    }
1687
1728
    client->close();
1688
1729
  }
1689
 
 
1690
1730
  if (should_lock)
1691
 
  {
1692
 
    session::Cache::singleton().mutex().unlock();
1693
 
  }
 
1731
    (void) pthread_mutex_unlock(&LOCK_thread_count);
1694
1732
}
1695
1733
 
1696
1734
void Session::reset_for_next_command()
1718
1756
  Close all temporary tables created by 'CREATE TEMPORARY TABLE' for thread
1719
1757
*/
1720
1758
 
1721
 
void Open_tables_state::close_temporary_tables()
 
1759
void Session::close_temporary_tables()
1722
1760
{
1723
1761
  Table *table;
1724
1762
  Table *tmp_next;
1728
1766
 
1729
1767
  for (table= temporary_tables; table; table= tmp_next)
1730
1768
  {
1731
 
    tmp_next= table->getNext();
 
1769
    tmp_next= table->next;
1732
1770
    nukeTable(table);
1733
1771
  }
1734
1772
  temporary_tables= NULL;
1738
1776
  unlink from session->temporary tables and close temporary table
1739
1777
*/
1740
1778
 
1741
 
void Open_tables_state::close_temporary_table(Table *table)
 
1779
void Session::close_temporary_table(Table *table)
1742
1780
{
1743
 
  if (table->getPrev())
 
1781
  if (table->prev)
1744
1782
  {
1745
 
    table->getPrev()->setNext(table->getNext());
1746
 
    if (table->getPrev()->getNext())
1747
 
    {
1748
 
      table->getNext()->setPrev(table->getPrev());
1749
 
    }
 
1783
    table->prev->next= table->next;
 
1784
    if (table->prev->next)
 
1785
      table->next->prev= table->prev;
1750
1786
  }
1751
1787
  else
1752
1788
  {
1757
1793
      passing non-zero value to end_slave via rli->save_temporary_tables
1758
1794
      when no temp tables opened, see an invariant below.
1759
1795
    */
1760
 
    temporary_tables= table->getNext();
 
1796
    temporary_tables= table->next;
1761
1797
    if (temporary_tables)
1762
 
    {
1763
 
      table->getNext()->setPrev(NULL);
1764
 
    }
 
1798
      table->next->prev= NULL;
1765
1799
  }
1766
1800
  nukeTable(table);
1767
1801
}
1774
1808
  If this is needed, use close_temporary_table()
1775
1809
*/
1776
1810
 
1777
 
void Open_tables_state::nukeTable(Table *table)
 
1811
void Session::nukeTable(Table *table)
1778
1812
{
1779
 
  plugin::StorageEngine *table_type= table->getShare()->db_type();
 
1813
  plugin::StorageEngine *table_type= table->s->db_type();
1780
1814
 
1781
1815
  table->free_io_cache();
1782
 
  table->delete_table();
 
1816
  table->closefrm(false);
1783
1817
 
1784
 
  TableIdentifier identifier(table->getShare()->getSchemaName(), table->getShare()->getTableName(), table->getShare()->getPath());
 
1818
  TableIdentifier identifier(table->s->getSchemaName(), table->s->table_name.str, table->s->path.str);
1785
1819
  rm_temporary_table(table_type, identifier);
1786
1820
 
1787
 
  delete table->getMutableShare();
 
1821
  table->s->free_table_share();
1788
1822
 
1789
1823
  /* This makes me sad, but we're allocating it via malloc */
1790
 
  delete table;
 
1824
  free(table);
1791
1825
}
1792
1826
 
1793
1827
/** Clear most status variables. */
1794
1828
extern time_t flush_status_time;
 
1829
extern uint32_t max_used_connections;
1795
1830
 
1796
1831
void Session::refresh_status()
1797
1832
{
 
1833
  pthread_mutex_lock(&LOCK_status);
 
1834
 
 
1835
  /* Add thread's status variabes to global status */
 
1836
  add_to_status(&global_status_var, &status_var);
 
1837
 
1798
1838
  /* Reset thread's status variables */
1799
1839
  memset(&status_var, 0, sizeof(status_var));
1800
1840
 
 
1841
  /* Reset some global variables */
 
1842
  reset_status_vars();
 
1843
 
 
1844
  /* Reset the counters of all key caches (default and named). */
 
1845
  reset_key_cache_counters();
1801
1846
  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;
 
1847
  max_used_connections= 1; /* We set it to one, because we know we exist */
 
1848
  pthread_mutex_unlock(&LOCK_status);
1804
1849
}
1805
1850
 
1806
1851
user_var_entry *Session::getVariable(LEX_STRING &name, bool create_if_not_exists)
1807
1852
{
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
1853
  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)
 
1854
 
 
1855
  entry= (user_var_entry*) hash_search(&user_vars, (unsigned char*) name.str, name.length);
 
1856
 
 
1857
  if ((entry == NULL) && create_if_not_exists)
1833
1858
  {
1834
 
    delete entry;
 
1859
    if (!hash_inited(&user_vars))
 
1860
      return NULL;
 
1861
    entry= new (nothrow) user_var_entry(name.str, query_id);
 
1862
 
 
1863
    if (entry == NULL)
 
1864
      return NULL;
 
1865
 
 
1866
    if (my_hash_insert(&user_vars, (unsigned char*) entry))
 
1867
    {
 
1868
      assert(1);
 
1869
      free((char*) entry);
 
1870
      return 0;
 
1871
    }
 
1872
 
1835
1873
  }
1836
1874
 
1837
1875
  return entry;
1838
1876
}
1839
1877
 
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())
 
1878
void Session::mark_temp_tables_as_free_for_reuse()
 
1879
{
 
1880
  for (Table *table= temporary_tables ; table ; table= table->next)
1854
1881
  {
1855
 
    if (table->query_id == getQueryId())
 
1882
    if (table->query_id == query_id)
1856
1883
    {
1857
1884
      table->query_id= 0;
1858
1885
      table->cursor->ha_reset();
1862
1889
 
1863
1890
void Session::mark_used_tables_as_free_for_reuse(Table *table)
1864
1891
{
1865
 
  for (; table ; table= table->getNext())
 
1892
  for (; table ; table= table->next)
1866
1893
  {
1867
 
    if (table->query_id == getQueryId())
 
1894
    if (table->query_id == query_id)
1868
1895
    {
1869
1896
      table->query_id= 0;
1870
1897
      table->cursor->ha_reset();
1883
1910
*/
1884
1911
void Session::close_thread_tables()
1885
1912
{
1886
 
  clearDerivedTables();
 
1913
  Table *table;
 
1914
 
 
1915
  /*
 
1916
    We are assuming here that session->derived_tables contains ONLY derived
 
1917
    tables for this substatement. i.e. instead of approach which uses
 
1918
    query_id matching for determining which of the derived tables belong
 
1919
    to this substatement we rely on the ability of substatements to
 
1920
    save/restore session->derived_tables during their execution.
 
1921
 
 
1922
    TODO: Probably even better approach is to simply associate list of
 
1923
          derived tables with (sub-)statement instead of thread and destroy
 
1924
          them at the end of its execution.
 
1925
  */
 
1926
  if (derived_tables)
 
1927
  {
 
1928
    Table *next;
 
1929
    /*
 
1930
      Close all derived tables generated in queries like
 
1931
      SELECT * FROM (SELECT * FROM t1)
 
1932
    */
 
1933
    for (table= derived_tables ; table ; table= next)
 
1934
    {
 
1935
      next= table->next;
 
1936
      table->free_tmp_table(this);
 
1937
    }
 
1938
    derived_tables= 0;
 
1939
  }
1887
1940
 
1888
1941
  /*
1889
1942
    Mark all temporary tables used by this statement as free for reuse.
1897
1950
    does not belong to statement for which we do close_thread_tables()).
1898
1951
    TODO: This should be fixed in later releases.
1899
1952
   */
 
1953
  if (backups_available == false)
1900
1954
  {
1901
1955
    TransactionServices &transaction_services= TransactionServices::singleton();
1902
1956
    main_da.can_overwrite_status= true;
1903
 
    transaction_services.autocommitOrRollback(this, is_error());
 
1957
    transaction_services.ha_autocommit_or_rollback(this, is_error());
1904
1958
    main_da.can_overwrite_status= false;
1905
1959
    transaction.stmt.reset();
1906
1960
  }
1916
1970
      handled either before writing a query log event (inside
1917
1971
      binlog_query()) or when preparing a pending event.
1918
1972
     */
1919
 
    unlockTables(lock);
 
1973
    mysql_unlock_tables(this, lock);
1920
1974
    lock= 0;
1921
1975
  }
1922
1976
  /*
1923
 
    Note that we need to hold table::Cache::singleton().mutex() while changing the
 
1977
    Note that we need to hold LOCK_open while changing the
1924
1978
    open_tables list. Another thread may work on it.
1925
 
    (See: table::Cache::singleton().removeTable(), mysql_wait_completed_table())
 
1979
    (See: remove_table_from_cache(), mysql_wait_completed_table())
1926
1980
    Closing a MERGE child before the parent would be fatal if the
1927
1981
    other thread tries to abort the MERGE lock in between.
1928
1982
  */
1961
2015
    close_tables_for_reopen(&tables);
1962
2016
  }
1963
2017
  if ((mysql_handle_derived(lex, &mysql_derived_prepare) ||
1964
 
       (
 
2018
       (fill_derived_tables() &&
1965
2019
        mysql_handle_derived(lex, &mysql_derived_filling))))
1966
2020
    return true;
1967
2021
 
1968
2022
  return false;
1969
2023
}
1970
2024
 
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
 
*/
 
2025
bool Session::openTables(TableList *tables, uint32_t flags)
 
2026
{
 
2027
  uint32_t counter;
 
2028
  bool ret= fill_derived_tables();
 
2029
  assert(ret == false);
 
2030
  if (open_tables_from_list(&tables, &counter, flags) ||
 
2031
      mysql_handle_derived(lex, &mysql_derived_prepare))
 
2032
    return true;
 
2033
  return false;
 
2034
}
1976
2035
 
1977
 
bool Open_tables_state::rm_temporary_table(const TableIdentifier &identifier, bool best_effort)
 
2036
bool Session::rm_temporary_table(TableIdentifier &identifier)
1978
2037
{
1979
 
  if (plugin::StorageEngine::dropTable(*static_cast<Session *>(this), identifier))
 
2038
  if (plugin::StorageEngine::dropTable(*this, identifier))
1980
2039
  {
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
 
    }
 
2040
    errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
 
2041
                  identifier.getSQLPath().c_str(), errno);
 
2042
    dumpTemporaryTableNames("rm_temporary_table()");
1988
2043
 
1989
2044
    return true;
1990
2045
  }
1992
2047
  return false;
1993
2048
}
1994
2049
 
1995
 
bool Open_tables_state::rm_temporary_table(plugin::StorageEngine *base, const TableIdentifier &identifier)
 
2050
bool Session::rm_temporary_table(plugin::StorageEngine *base, TableIdentifier &identifier)
1996
2051
{
1997
2052
  assert(base);
1998
2053
 
1999
 
  if (plugin::StorageEngine::dropTable(*static_cast<Session *>(this), *base, identifier))
 
2054
  if (plugin::StorageEngine::dropTable(*this, *base, identifier))
2000
2055
  {
2001
 
    std::string path;
2002
 
    identifier.getSQLPath(path);
2003
2056
    errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
2004
 
                  path.c_str(), errno);
 
2057
                  identifier.getSQLPath().c_str(), errno);
 
2058
    dumpTemporaryTableNames("rm_temporary_table()");
2005
2059
 
2006
2060
    return true;
2007
2061
  }
2013
2067
  @note this will be removed, I am looking through Hudson to see if it is finding
2014
2068
  any tables that are missed during cleanup.
2015
2069
*/
2016
 
void Open_tables_state::dumpTemporaryTableNames(const char *foo)
 
2070
void Session::dumpTemporaryTableNames(const char *foo)
2017
2071
{
2018
2072
  Table *table;
2019
2073
 
2021
2075
    return;
2022
2076
 
2023
2077
  cerr << "Begin Run: " << foo << "\n";
2024
 
  for (table= temporary_tables; table; table= table->getNext())
 
2078
  for (table= temporary_tables; table; table= table->next)
2025
2079
  {
2026
2080
    bool have_proto= false;
2027
2081
 
2028
 
    message::Table *proto= table->getShare()->getTableProto();
2029
 
    if (table->getShare()->getTableProto())
 
2082
    message::Table *proto= table->s->getTableProto();
 
2083
    if (table->s->getTableProto())
2030
2084
      have_proto= true;
2031
2085
 
2032
2086
    const char *answer= have_proto ? "true" : "false";
2033
2087
 
2034
2088
    if (have_proto)
2035
2089
    {
2036
 
      cerr << "\tTable Name " << table->getShare()->getSchemaName() << "." << table->getShare()->getTableName() << " : " << answer << "\n";
 
2090
      cerr << "\tTable Name " << table->s->getSchemaName() << "." << table->s->table_name.str << " : " << answer << "\n";
2037
2091
      cerr << "\t\t Proto " << proto->schema() << " " << proto->name() << "\n";
2038
2092
    }
2039
2093
    else
2040
 
    {
2041
 
      cerr << "\tTabl;e Name " << table->getShare()->getSchemaName() << "." << table->getShare()->getTableName() << " : " << answer << "\n";
2042
 
    }
 
2094
      cerr << "\tTabl;e Name " << table->s->getSchemaName() << "." << table->s->table_name.str << " : " << answer << "\n";
2043
2095
  }
2044
2096
}
2045
2097
 
2046
 
bool Session::TableMessages::storeTableMessage(const TableIdentifier &identifier, message::Table &table_message)
 
2098
bool Session::storeTableMessage(TableIdentifier &identifier, message::Table &table_message)
2047
2099
{
2048
2100
  table_message_cache.insert(make_pair(identifier.getPath(), table_message));
2049
2101
 
2050
2102
  return true;
2051
2103
}
2052
2104
 
2053
 
bool Session::TableMessages::removeTableMessage(const TableIdentifier &identifier)
 
2105
bool Session::removeTableMessage(TableIdentifier &identifier)
2054
2106
{
2055
2107
  TableMessageCache::iterator iter;
2056
2108
 
2064
2116
  return true;
2065
2117
}
2066
2118
 
2067
 
bool Session::TableMessages::getTableMessage(const TableIdentifier &identifier, message::Table &table_message)
 
2119
bool Session::getTableMessage(TableIdentifier &identifier, message::Table &table_message)
2068
2120
{
2069
2121
  TableMessageCache::iterator iter;
2070
2122
 
2078
2130
  return true;
2079
2131
}
2080
2132
 
2081
 
bool Session::TableMessages::doesTableMessageExist(const TableIdentifier &identifier)
 
2133
bool Session::doesTableMessageExist(TableIdentifier &identifier)
2082
2134
{
2083
2135
  TableMessageCache::iterator iter;
2084
2136
 
2092
2144
  return true;
2093
2145
}
2094
2146
 
2095
 
bool Session::TableMessages::renameTableMessage(const TableIdentifier &from, const TableIdentifier &to)
 
2147
bool Session::renameTableMessage(TableIdentifier &from, TableIdentifier &to)
2096
2148
{
2097
2149
  TableMessageCache::iterator iter;
2098
2150
 
2111
2163
  return true;
2112
2164
}
2113
2165
 
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
2166
} /* namespace drizzled */