~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/session.cc

  • Committer: Brian Aker
  • Date: 2010-11-08 18:54:26 UTC
  • mto: (1921.1.1 trunk)
  • mto: This revision was merged to the branch mainline in revision 1916.
  • Revision ID: brian@tangent.org-20101108185426-fymkf2xnelupf11x
Rename lock methods to be style + well make sense.

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>
 
25
#include "drizzled/session.h"
26
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"
46
46
#include "drizzled/db.h"
47
47
#include "drizzled/pthread_globals.h"
48
48
#include "drizzled/transaction_services.h"
 
49
#include "drizzled/drizzled.h"
 
50
 
 
51
#include "drizzled/table/instance.h"
49
52
 
50
53
#include "plugin/myisam/myisam.h"
51
54
#include "drizzled/internal/iocache.h"
 
55
#include "drizzled/internal/thread_var.h"
 
56
#include "drizzled/plugin/event_observer.h"
 
57
 
 
58
#include "drizzled/util/functors.h"
52
59
 
53
60
#include <fcntl.h>
54
61
#include <algorithm>
55
62
#include <climits>
 
63
#include <boost/filesystem.hpp>
56
64
 
57
65
using namespace std;
 
66
 
 
67
namespace fs=boost::filesystem;
58
68
namespace drizzled
59
69
{
60
70
 
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
 
 
67
71
/*
68
72
  The following is used to initialise Table_ident with a internal
69
73
  table name
72
76
char empty_c_string[1]= {0};    /* used for not defined db */
73
77
 
74
78
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
 
}
94
79
 
95
80
bool Key_part_spec::operator==(const Key_part_spec& other) const
96
81
{
99
84
         !strcmp(field_name.str, other.field_name.str);
100
85
}
101
86
 
102
 
Open_tables_state::Open_tables_state(uint64_t version_arg)
103
 
  :version(version_arg), backups_available(false)
 
87
Open_tables_state::Open_tables_state(uint64_t version_arg) :
 
88
  version(version_arg)
104
89
{
105
 
  reset_open_tables_state();
 
90
  open_tables= temporary_tables= derived_tables= NULL;
 
91
  extra_lock= lock= NULL;
106
92
}
107
93
 
108
94
/*
109
95
  The following functions form part of the C plugin API
110
96
*/
111
 
extern "C" int mysql_tmpfile(const char *prefix)
 
97
int mysql_tmpfile(const char *prefix)
112
98
{
113
99
  char filename[FN_REFLEN];
114
 
  int fd = internal::create_temp_file(filename, drizzle_tmpdir, prefix, MYF(MY_WME));
 
100
  int fd = internal::create_temp_file(filename, drizzle_tmpdir.c_str(), prefix, MYF(MY_WME));
115
101
  if (fd >= 0) {
116
102
    unlink(filename);
117
103
  }
119
105
  return fd;
120
106
}
121
107
 
122
 
extern "C"
123
108
int session_tablespace_op(const Session *session)
124
109
{
125
110
  return test(session->tablespace_op);
133
118
 
134
119
   @see Session::set_proc_info
135
120
 */
136
 
extern "C" void
137
 
set_session_proc_info(Session *session, const char *info)
 
121
void set_session_proc_info(Session *session, const char *info)
138
122
{
139
123
  session->set_proc_info(info);
140
124
}
141
125
 
142
 
extern "C"
143
126
const char *get_session_proc_info(Session *session)
144
127
{
145
128
  return session->get_proc_info();
156
139
  return &ha_data[monitored->getId()].resource_context[index];
157
140
}
158
141
 
159
 
extern "C"
160
142
int64_t session_test_options(const Session *session, int64_t test_options)
161
143
{
162
144
  return session->options & test_options;
163
145
}
164
146
 
165
 
extern "C"
166
147
int session_sql_command(const Session *session)
167
148
{
168
149
  return (int) session->lex->sql_command;
169
150
}
170
151
 
171
 
extern "C"
172
 
int session_tx_isolation(const Session *session)
 
152
enum_tx_isolation session_tx_isolation(const Session *session)
173
153
{
174
 
  return (int) session->variables.tx_isolation;
 
154
  return (enum_tx_isolation)session->variables.tx_isolation;
175
155
}
176
156
 
177
 
Session::Session(plugin::Client *client_arg)
178
 
  :
 
157
Session::Session(plugin::Client *client_arg) :
179
158
  Open_tables_state(refresh_version),
180
159
  mem_root(&main_mem_root),
 
160
  xa_id(0),
181
161
  lex(&main_lex),
182
 
  query(),
 
162
  catalog("LOCAL"),
183
163
  client(client_arg),
184
164
  scheduler(NULL),
185
165
  scheduler_arg(NULL),
190
170
  first_successful_insert_id_in_prev_stmt(0),
191
171
  first_successful_insert_id_in_cur_stmt(0),
192
172
  limit_found_rows(0),
193
 
  global_read_lock(0),
 
173
  _global_read_lock(NONE),
194
174
  some_tables_deleted(false),
195
175
  no_errors(false),
196
176
  password(false),
202
182
  m_lip(NULL),
203
183
  cached_table(0),
204
184
  transaction_message(NULL),
205
 
  statement_message(NULL)
 
185
  statement_message(NULL),
 
186
  session_event_observers(NULL),
 
187
  use_usage(false)
206
188
{
207
189
  memset(process_list_info, 0, PROCESS_LIST_WIDTH);
208
190
  client->setSession(this);
214
196
  */
215
197
  memory::init_sql_alloc(&main_mem_root, memory::ROOT_MIN_BLOCK_SIZE, 0);
216
198
  thread_stack= NULL;
217
 
  count_cuted_fields= CHECK_FIELD_IGNORE;
 
199
  count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;
218
200
  killed= NOT_KILLED;
219
201
  col_access= 0;
220
202
  tmp_table= 0;
233
215
  query_id= 0;
234
216
  warn_query_id= 0;
235
217
  mysys_var= 0;
 
218
  scoreboard_index= -1;
236
219
  dbug_sentry=Session_SENTRY_MAGIC;
237
 
  cleanup_done= abort_on_warning= no_warnings_for_error= false;
238
 
  pthread_mutex_init(&LOCK_delete, MY_MUTEX_INIT_FAST);
 
220
  cleanup_done= abort_on_warning= no_warnings_for_error= false;  
 
221
 
 
222
  /* query_cache init */
 
223
  query_cache_key= "";
 
224
  resultset= NULL;
239
225
 
240
226
  /* Variables with default values */
241
227
  proc_info="login";
267
253
 
268
254
  /* Initialize sub structures */
269
255
  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);
273
256
 
274
257
  substitute_null_with_insert_id = false;
275
 
  thr_lock_info_init(&lock_info); /* safety: will be reset after start */
 
258
  lock_info.init(); /* safety: will be reset after start */
276
259
  thr_lock_owner_init(&main_lock_id, &lock_info);
277
260
 
278
261
  m_internal_handler= NULL;
 
262
  
 
263
  plugin::EventObserver::registerSessionEvents(*this); 
279
264
}
280
265
 
281
266
void Session::free_items()
310
295
  return false;                                 // 'false', as per coding style
311
296
}
312
297
 
 
298
void Session::setAbort(bool arg)
 
299
{
 
300
  mysys_var->abort= arg;
 
301
}
 
302
 
 
303
void Session::lockOnSys()
 
304
{
 
305
  if (not mysys_var)
 
306
    return;
 
307
 
 
308
  setAbort(true);
 
309
  boost_unique_lock_t scopedLock(mysys_var->mutex);
 
310
  if (mysys_var->current_cond)
 
311
  {
 
312
    mysys_var->current_mutex->lock();
 
313
    mysys_var->current_cond->notify_all();
 
314
    mysys_var->current_mutex->unlock();
 
315
  }
 
316
}
 
317
 
313
318
void Session::pop_internal_handler()
314
319
{
315
320
  assert(m_internal_handler != NULL);
316
321
  m_internal_handler= NULL;
317
322
}
318
323
 
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
 
324
void Session::get_xid(DRIZZLE_XID *xid)
 
325
{
 
326
  *xid = *(DRIZZLE_XID *) &transaction.xid_state.xid;
 
327
}
356
328
 
357
329
/* Do operations that may take a long time */
358
330
 
369
341
#endif
370
342
  {
371
343
    TransactionServices &transaction_services= TransactionServices::singleton();
372
 
    transaction_services.ha_rollback_trans(this, true);
 
344
    transaction_services.rollbackTransaction(this, true);
373
345
    xid_cache_delete(&transaction.xid_state);
374
346
  }
375
 
  hash_free(&user_vars);
 
347
 
 
348
  for (UserVars::iterator iter= user_vars.begin();
 
349
       iter != user_vars.end();
 
350
       iter++)
 
351
  {
 
352
    user_var_entry *entry= (*iter).second;
 
353
    delete entry;
 
354
  }
 
355
  user_vars.clear();
 
356
 
 
357
 
376
358
  close_temporary_tables();
377
359
 
378
360
  if (global_read_lock)
379
 
    unlock_global_read_lock(this);
 
361
  {
 
362
    unlockGlobalReadLock();
 
363
  }
380
364
 
381
365
  cleanup_done= true;
382
366
}
384
368
Session::~Session()
385
369
{
386
370
  this->checkSentry();
387
 
  add_to_status(&global_status_var, &status_var);
388
371
 
389
372
  if (client->isConnected())
390
373
  {
406
389
  plugin::StorageEngine::closeConnection(this);
407
390
  plugin_sessionvar_cleanup(this);
408
391
 
409
 
  free_root(&warn_root,MYF(0));
 
392
  warn_root.free_root(MYF(0));
410
393
  mysys_var=0;                                  // Safety (shouldn't be needed)
411
394
  dbug_sentry= Session_SENTRY_GONE;
412
395
 
413
 
  free_root(&main_mem_root, MYF(0));
414
 
  pthread_setspecific(THR_Session,  0);
 
396
  main_mem_root.free_root(MYF(0));
 
397
  currentMemRoot().release();
 
398
  currentSession().release();
415
399
 
416
400
  plugin::Logging::postEndDo(this);
 
401
  plugin::EventObserver::deregisterSessionEvents(*this); 
 
402
 
 
403
  for (PropertyMap::iterator iter= life_properties.begin(); iter != life_properties.end(); iter++)
 
404
  {
 
405
    delete (*iter).second;
 
406
  }
 
407
  life_properties.clear();
417
408
 
418
409
  /* 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++);
 
410
  LOCK_delete.unlock();
469
411
}
470
412
 
471
413
void Session::awake(Session::killed_state state_to_set)
481
423
  }
482
424
  if (mysys_var)
483
425
  {
484
 
    pthread_mutex_lock(&mysys_var->mutex);
 
426
    boost_unique_lock_t scopedLock(mysys_var->mutex);
485
427
    /*
 
428
      "
486
429
      This broadcast could be up in the air if the victim thread
487
430
      exits the cond in the time between read and broadcast, but that is
488
431
      ok since all we want to do is to make the victim thread get out
503
446
    */
504
447
    if (mysys_var->current_cond && mysys_var->current_mutex)
505
448
    {
506
 
      pthread_mutex_lock(mysys_var->current_mutex);
507
 
      pthread_cond_broadcast(mysys_var->current_cond);
508
 
      pthread_mutex_unlock(mysys_var->current_mutex);
 
449
      mysys_var->current_mutex->lock();
 
450
      mysys_var->current_cond->notify_all();
 
451
      mysys_var->current_mutex->unlock();
509
452
    }
510
 
    pthread_mutex_unlock(&mysys_var->mutex);
511
453
  }
512
454
}
513
455
 
523
465
  */
524
466
  assert(thread_stack);
525
467
 
526
 
  if (pthread_setspecific(THR_Session,  this) ||
527
 
      pthread_setspecific(THR_Mem_root, &mem_root))
528
 
    return true;
 
468
  currentSession().release();
 
469
  currentSession().reset(this);
 
470
 
 
471
  currentMemRoot().release();
 
472
  currentMemRoot().reset(&mem_root);
529
473
 
530
474
  mysys_var=my_thread_var;
531
475
 
534
478
    This allows us to move Session to different threads if needed.
535
479
  */
536
480
  mysys_var->id= thread_id;
537
 
  real_id= pthread_self();                      // For debugging
538
481
 
539
482
  /*
540
483
    We have to call thr_lock_info_init() again here as Session may have been
541
484
    created in another thread
542
485
  */
543
 
  thr_lock_info_init(&lock_info);
 
486
  lock_info.init();
 
487
 
544
488
  return false;
545
489
}
546
490
 
560
504
  command= COM_SLEEP;
561
505
  set_time();
562
506
 
563
 
  reset_root_defaults(mem_root, variables.query_alloc_block_size,
564
 
                      variables.query_prealloc_size);
 
507
  mem_root->reset_root_defaults(variables.query_alloc_block_size,
 
508
                                variables.query_prealloc_size);
565
509
  transaction.xid_state.xid.null();
566
510
  transaction.xid_state.in_session=1;
 
511
  if (use_usage)
 
512
    resetUsage();
567
513
}
568
514
 
569
515
bool Session::initGlobals()
571
517
  if (storeGlobals())
572
518
  {
573
519
    disconnect(ER_OUT_OF_RESOURCES, true);
574
 
    statistic_increment(aborted_connects, &LOCK_status);
 
520
    status_var.aborted_connects++;
575
521
    return true;
576
522
  }
577
523
  return false;
603
549
 
604
550
  connection_count.increment();
605
551
 
606
 
  if (connection_count > max_used_connections)
607
 
    max_used_connections= connection_count;
 
552
  if (connection_count > current_global_counters.max_used_connections)
 
553
  {
 
554
    current_global_counters.max_used_connections= connection_count;
 
555
  }
608
556
 
 
557
  current_global_counters.connections++;
609
558
  thread_id= variables.pseudo_thread_id= global_thread_id++;
610
559
 
611
 
  pthread_mutex_lock(&LOCK_thread_count);
612
 
  getSessionList().push_back(this);
613
 
  pthread_mutex_unlock(&LOCK_thread_count);
 
560
  {
 
561
    boost::mutex::scoped_lock scoped(LOCK_thread_count);
 
562
    getSessionList().push_back(this);
 
563
  }
 
564
 
 
565
  if (unlikely(plugin::EventObserver::connectSession(*this)))
 
566
  {
 
567
    // We should do something about an error...
 
568
  }
 
569
 
 
570
  if (unlikely(plugin::EventObserver::connectSession(*this)))
 
571
  {
 
572
    // We should do something about an error...
 
573
  }
614
574
 
615
575
  if (scheduler->addSession(this))
616
576
  {
619
579
 
620
580
    killed= Session::KILL_CONNECTION;
621
581
 
622
 
    statistic_increment(aborted_connects, &LOCK_status);
 
582
    status_var.aborted_connects++;
623
583
 
624
584
    /* Can't use my_error() since store_globals has not been called. */
625
585
    /* TODO replace will better error message */
633
593
}
634
594
 
635
595
 
636
 
const char* Session::enter_cond(pthread_cond_t *cond,
637
 
                                pthread_mutex_t* mutex,
638
 
                                const char* msg)
 
596
const char* Session::enter_cond(boost::condition_variable_any &cond, boost::mutex &mutex, const char* msg)
639
597
{
640
598
  const char* old_msg = get_proc_info();
641
599
  safe_mutex_assert_owner(mutex);
642
 
  mysys_var->current_mutex = mutex;
643
 
  mysys_var->current_cond = cond;
 
600
  mysys_var->current_mutex = &mutex;
 
601
  mysys_var->current_cond = &cond;
644
602
  this->set_proc_info(msg);
645
603
  return old_msg;
646
604
}
653
611
    locked (if that would not be the case, you'll get a deadlock if someone
654
612
    does a Session::awake() on you).
655
613
  */
656
 
  pthread_mutex_unlock(mysys_var->current_mutex);
657
 
  pthread_mutex_lock(&mysys_var->mutex);
 
614
  mysys_var->current_mutex->unlock();
 
615
  boost_unique_lock_t scopedLock(mysys_var->mutex);
658
616
  mysys_var->current_mutex = 0;
659
617
  mysys_var->current_cond = 0;
660
618
  this->set_proc_info(old_msg);
661
 
  pthread_mutex_unlock(&mysys_var->mutex);
662
619
}
663
620
 
664
621
bool Session::authenticate()
665
622
{
666
 
  lex_start(this);
 
623
  lex->start(this);
667
624
  if (client->authenticate())
668
625
    return false;
669
626
 
670
 
  statistic_increment(aborted_connects, &LOCK_status);
 
627
  status_var.aborted_connects++;
 
628
 
671
629
  return true;
672
630
}
673
631
 
674
 
bool Session::checkUser(const char *passwd, uint32_t passwd_len, const char *in_db)
 
632
bool Session::checkUser(const std::string &passwd_str,
 
633
                        const std::string &in_db)
675
634
{
676
 
  const string passwd_str(passwd, passwd_len);
677
635
  bool is_authenticated=
678
636
    plugin::Authentication::isAuthenticated(getSecurityContext(),
679
637
                                            passwd_str);
680
638
 
681
639
  if (is_authenticated != true)
682
640
  {
 
641
    status_var.access_denied++;
683
642
    /* isAuthenticated has pushed the error message */
684
643
    return false;
685
644
  }
686
645
 
687
646
  /* Change database if necessary */
688
 
  if (in_db && in_db[0])
 
647
  if (not in_db.empty())
689
648
  {
690
649
    SchemaIdentifier identifier(in_db);
691
650
    if (mysql_change_db(this, identifier))
695
654
    }
696
655
  }
697
656
  my_ok();
698
 
  password= test(passwd_len);          // remember for error messages
 
657
  password= not passwd_str.empty();
699
658
 
700
659
  /* Ready to handle queries */
701
660
  return true;
719
678
  if (client->readCommand(&l_packet, &packet_length) == false)
720
679
    return false;
721
680
 
 
681
  if (killed == KILL_CONNECTION)
 
682
    return false;
 
683
 
722
684
  if (packet_length == 0)
723
685
    return true;
724
686
 
772
734
       * (Which of course should never happen...)
773
735
       */
774
736
      server_status&= ~SERVER_STATUS_IN_TRANS;
775
 
      if (transaction_services.ha_commit_trans(this, true))
 
737
      if (transaction_services.commitTransaction(this, true))
776
738
        result= false;
777
739
      options&= ~(OPTION_BEGIN);
778
740
      break;
789
751
    case ROLLBACK_AND_CHAIN:
790
752
    {
791
753
      server_status&= ~SERVER_STATUS_IN_TRANS;
792
 
      if (transaction_services.ha_rollback_trans(this, true))
 
754
      if (transaction_services.rollbackTransaction(this, true))
793
755
        result= false;
794
756
      options&= ~(OPTION_BEGIN);
795
757
      if (result == true && (completion == ROLLBACK_AND_CHAIN))
822
784
  if (options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
823
785
  {
824
786
    server_status&= ~SERVER_STATUS_IN_TRANS;
825
 
    if (transaction_services.ha_commit_trans(this, true))
 
787
    if (transaction_services.commitTransaction(this, true))
826
788
      result= false;
827
789
  }
828
790
  options&= ~(OPTION_BEGIN);
873
835
  free_items();
874
836
  /* Reset where. */
875
837
  where= Session::DEFAULT_WHERE;
 
838
 
 
839
  /* Reset the temporary shares we built */
 
840
  for_each(temporary_shares.begin(),
 
841
           temporary_shares.end(),
 
842
           DeletePtr());
 
843
  temporary_shares.clear();
876
844
}
877
845
 
878
846
/**
899
867
  if (allocate_lex_string)
900
868
    if (!(lex_str= (LEX_STRING *)alloc(sizeof(LEX_STRING))))
901
869
      return 0;
902
 
  if (!(lex_str->str= strmake_root(mem_root, str, length)))
 
870
  if (!(lex_str->str= mem_root->strmake_root(str, length)))
903
871
    return 0;
904
872
  lex_str->length= length;
905
873
  return lex_str;
957
925
  my_message(errcode, err, MYF(0));
958
926
  if (file > 0)
959
927
  {
960
 
    (void) end_io_cache(cache);
 
928
    (void) cache->end_io_cache();
961
929
    (void) internal::my_close(file, MYF(0));
962
 
    (void) internal::my_delete(path, MYF(0));           // Delete file on error
 
930
    (void) internal::my_delete(path.file_string().c_str(), MYF(0));             // Delete file on error
963
931
    file= -1;
964
932
  }
965
933
}
967
935
 
968
936
bool select_to_file::send_eof()
969
937
{
970
 
  int error= test(end_io_cache(cache));
 
938
  int error= test(cache->end_io_cache());
971
939
  if (internal::my_close(file, MYF(MY_WME)))
972
940
    error= 1;
973
941
  if (!error)
989
957
  /* In case of error send_eof() may be not called: close the file here. */
990
958
  if (file >= 0)
991
959
  {
992
 
    (void) end_io_cache(cache);
 
960
    (void) cache->end_io_cache();
993
961
    (void) internal::my_close(file, MYF(0));
994
962
    file= -1;
995
963
  }
996
 
  path[0]= '\0';
 
964
  path= "";
997
965
  row_count= 0;
998
966
}
999
967
 
1003
971
    cache(static_cast<internal::IO_CACHE *>(memory::sql_calloc(sizeof(internal::IO_CACHE)))),
1004
972
    row_count(0L)
1005
973
{
1006
 
  path[0]=0;
 
974
  path= "";
1007
975
}
1008
976
 
1009
977
select_to_file::~select_to_file()
1037
1005
*/
1038
1006
 
1039
1007
 
1040
 
static int create_file(Session *session, char *path, file_exchange *exchange, internal::IO_CACHE *cache)
 
1008
static int create_file(Session *session,
 
1009
                       fs::path &target_path,
 
1010
                       file_exchange *exchange,
 
1011
                       internal::IO_CACHE *cache)
1041
1012
{
 
1013
  fs::path to_file(exchange->file_name);
1042
1014
  int file;
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))
 
1015
 
 
1016
  if (not to_file.has_root_directory())
1050
1017
  {
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);
 
1018
    target_path= fs::system_complete(getDataHomeCatalog());
 
1019
    if (not session->db.empty())
 
1020
    {
 
1021
      int count_elements= 0;
 
1022
      for (fs::path::iterator iter= to_file.begin();
 
1023
           iter != to_file.end();
 
1024
           ++iter, ++count_elements)
 
1025
      { }
 
1026
 
 
1027
      if (count_elements == 1)
 
1028
      {
 
1029
        target_path /= session->db;
 
1030
      }
 
1031
    }
 
1032
    target_path /= to_file;
1055
1033
  }
1056
1034
  else
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))
 
1035
  {
 
1036
    target_path = exchange->file_name;
 
1037
  }
 
1038
 
 
1039
  if (not secure_file_priv.string().empty())
 
1040
  {
 
1041
    if (target_path.file_string().substr(0, secure_file_priv.file_string().size()) != secure_file_priv.file_string())
 
1042
    {
 
1043
      /* Write only allowed to dir or subdir specified by secure_file_priv */
 
1044
      my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
 
1045
      return -1;
 
1046
    }
 
1047
  }
 
1048
 
 
1049
  if (!access(target_path.file_string().c_str(), F_OK))
1068
1050
  {
1069
1051
    my_error(ER_FILE_EXISTS_ERROR, MYF(0), exchange->file_name);
1070
1052
    return -1;
1071
1053
  }
1072
1054
  /* Create the file world readable */
1073
 
  if ((file= internal::my_create(path, 0666, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0)
 
1055
  if ((file= internal::my_create(target_path.file_string().c_str(), 0666, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0)
1074
1056
    return file;
1075
1057
  (void) fchmod(file, 0666);                    // Because of umask()
1076
 
  if (init_io_cache(cache, file, 0L, internal::WRITE_CACHE, 0L, 1, MYF(MY_WME)))
 
1058
  if (cache->init_io_cache(file, 0L, internal::WRITE_CACHE, 0L, 1, MYF(MY_WME)))
1077
1059
  {
1078
1060
    internal::my_close(file, MYF(0));
1079
 
    internal::my_delete(path, MYF(0));  // Delete file on error, it was just created
 
1061
    internal::my_delete(target_path.file_string().c_str(), MYF(0));  // Delete file on error, it was just created
1080
1062
    return -1;
1081
1063
  }
1082
1064
  return file;
1090
1072
  bool string_results= false, non_string_results= false;
1091
1073
  unit= u;
1092
1074
  if ((uint32_t) strlen(exchange->file_name) + NAME_LEN >= FN_REFLEN)
1093
 
    strncpy(path,exchange->file_name,FN_REFLEN-1);
 
1075
  {
 
1076
    path= exchange->file_name;
 
1077
  }
1094
1078
 
1095
1079
  /* Check if there is any blobs in data */
1096
1080
  {
1153
1137
  if (unit->offset_limit_cnt)
1154
1138
  {                                             // using limit offset,count
1155
1139
    unit->offset_limit_cnt--;
1156
 
    return(0);
 
1140
    return false;
1157
1141
  }
1158
1142
  row_count++;
1159
1143
  Item *item;
1162
1146
 
1163
1147
  if (my_b_write(cache,(unsigned char*) exchange->line_start->ptr(),
1164
1148
                 exchange->line_start->length()))
1165
 
    goto err;
 
1149
    return true;
 
1150
 
1166
1151
  while ((item=li++))
1167
1152
  {
1168
1153
    Item_result result_type=item->result_type();
1173
1158
    {
1174
1159
      if (my_b_write(cache,(unsigned char*) exchange->enclosed->ptr(),
1175
1160
                     exchange->enclosed->length()))
1176
 
        goto err;
 
1161
        return true;
1177
1162
    }
1178
1163
    if (!res)
1179
1164
    {                                           // NULL
1184
1169
          null_buff[0]=escape_char;
1185
1170
          null_buff[1]='N';
1186
1171
          if (my_b_write(cache,(unsigned char*) null_buff,2))
1187
 
            goto err;
 
1172
            return true;
1188
1173
        }
1189
1174
        else if (my_b_write(cache,(unsigned char*) "NULL",4))
1190
 
          goto err;
 
1175
          return true;
1191
1176
      }
1192
1177
      else
1193
1178
      {
1197
1182
    else
1198
1183
    {
1199
1184
      if (fixed_row_size)
1200
 
        used_length= min(res->length(),item->max_length);
 
1185
        used_length= min(res->length(), static_cast<size_t>(item->max_length));
1201
1186
      else
1202
1187
        used_length= res->length();
1203
1188
 
1278
1263
            tmp_buff[1]= *pos ? *pos : '0';
1279
1264
            if (my_b_write(cache,(unsigned char*) start,(uint32_t) (pos-start)) ||
1280
1265
                my_b_write(cache,(unsigned char*) tmp_buff,2))
1281
 
              goto err;
 
1266
              return true;
1282
1267
            start=pos+1;
1283
1268
          }
1284
1269
        }
1285
1270
        if (my_b_write(cache,(unsigned char*) start,(uint32_t) (pos-start)))
1286
 
          goto err;
 
1271
          return true;
1287
1272
      }
1288
1273
      else if (my_b_write(cache,(unsigned char*) res->ptr(),used_length))
1289
 
        goto err;
 
1274
        return true;
1290
1275
    }
1291
1276
    if (fixed_row_size)
1292
1277
    {                                           // Fill with space
1302
1287
        for (; length > sizeof(space) ; length-=sizeof(space))
1303
1288
        {
1304
1289
          if (my_b_write(cache,(unsigned char*) space,sizeof(space)))
1305
 
            goto err;
 
1290
            return true;
1306
1291
        }
1307
1292
        if (my_b_write(cache,(unsigned char*) space,length))
1308
 
          goto err;
 
1293
          return true;
1309
1294
      }
1310
1295
    }
1311
1296
    if (res && enclosed)
1312
1297
    {
1313
1298
      if (my_b_write(cache, (unsigned char*) exchange->enclosed->ptr(),
1314
1299
                     exchange->enclosed->length()))
1315
 
        goto err;
 
1300
        return true;
1316
1301
    }
1317
1302
    if (--items_left)
1318
1303
    {
1319
1304
      if (my_b_write(cache, (unsigned char*) exchange->field_term->ptr(),
1320
1305
                     field_term_length))
1321
 
        goto err;
 
1306
        return true;
1322
1307
    }
1323
1308
  }
1324
1309
  if (my_b_write(cache,(unsigned char*) exchange->line_term->ptr(),
1325
1310
                 exchange->line_term->length()))
1326
 
    goto err;
1327
 
  return(0);
1328
 
err:
1329
 
  return(1);
 
1311
  {
 
1312
    return true;
 
1313
  }
 
1314
 
 
1315
  return false;
1330
1316
}
1331
1317
 
1332
1318
 
1359
1345
  if (row_count++ > 1)
1360
1346
  {
1361
1347
    my_message(ER_TOO_MANY_ROWS, ER(ER_TOO_MANY_ROWS), MYF(0));
1362
 
    goto err;
 
1348
    return 1;
1363
1349
  }
1364
1350
  while ((item=li++))
1365
1351
  {
1367
1353
    if (!res)                                   // If NULL
1368
1354
    {
1369
1355
      if (my_b_write(cache,(unsigned char*) "",1))
1370
 
        goto err;
 
1356
        return 1;
1371
1357
    }
1372
1358
    else if (my_b_write(cache,(unsigned char*) res->ptr(),res->length()))
1373
1359
    {
1374
 
      my_error(ER_ERROR_ON_WRITE, MYF(0), path, errno);
1375
 
      goto err;
 
1360
      my_error(ER_ERROR_ON_WRITE, MYF(0), path.file_string().c_str(), errno);
 
1361
      return 1;
1376
1362
    }
1377
1363
  }
1378
1364
  return(0);
1379
 
err:
1380
 
  return(1);
1381
1365
}
1382
1366
 
1383
1367
 
1435
1419
      switch (val_item->result_type())
1436
1420
      {
1437
1421
      case REAL_RESULT:
1438
 
        op= &select_max_min_finder_subselect::cmp_real;
1439
 
        break;
 
1422
        op= &select_max_min_finder_subselect::cmp_real;
 
1423
        break;
1440
1424
      case INT_RESULT:
1441
 
        op= &select_max_min_finder_subselect::cmp_int;
1442
 
        break;
 
1425
        op= &select_max_min_finder_subselect::cmp_int;
 
1426
        break;
1443
1427
      case STRING_RESULT:
1444
 
        op= &select_max_min_finder_subselect::cmp_str;
1445
 
        break;
 
1428
        op= &select_max_min_finder_subselect::cmp_str;
 
1429
        break;
1446
1430
      case DECIMAL_RESULT:
1447
1431
        op= &select_max_min_finder_subselect::cmp_decimal;
1448
1432
        break;
1449
1433
      case ROW_RESULT:
1450
1434
        // This case should never be choosen
1451
 
        assert(0);
1452
 
        op= 0;
 
1435
        assert(0);
 
1436
        op= 0;
1453
1437
      }
1454
1438
    }
1455
1439
    cache->store(val_item);
1538
1522
void Session::end_statement()
1539
1523
{
1540
1524
  /* Cleanup SQL processing state to reuse this statement in next query. */
1541
 
  lex_end(lex);
 
1525
  lex->end();
 
1526
  query_cache_key= ""; // reset the cache key
 
1527
  resetResultsetMessage();
1542
1528
}
1543
1529
 
1544
1530
bool Session::copy_db_to(char **p_db, size_t *p_db_length)
1589
1575
}
1590
1576
 
1591
1577
 
1592
 
/****************************************************************************
1593
 
  Handling of open and locked tables states.
1594
 
 
1595
 
  This is used when we want to open/lock (and then close) some tables when
1596
 
  we already have a set of tables open and locked. We use these methods for
1597
 
  access to mysql.proc table to find definitions of stored routines.
1598
 
****************************************************************************/
1599
 
 
1600
 
void Session::reset_n_backup_open_tables_state(Open_tables_state *backup)
1601
 
{
1602
 
  backup->set_open_tables_state(this);
1603
 
  reset_open_tables_state();
1604
 
  backups_available= false;
1605
 
}
1606
 
 
1607
 
 
1608
 
void Session::restore_backup_open_tables_state(Open_tables_state *backup)
1609
 
{
1610
 
  /*
1611
 
    Before we will throw away current open tables state we want
1612
 
    to be sure that it was properly cleaned up.
1613
 
  */
1614
 
  assert(open_tables == 0 && temporary_tables == 0 &&
1615
 
              derived_tables == 0 &&
1616
 
              lock == 0);
1617
 
  set_open_tables_state(backup);
1618
 
}
1619
 
 
1620
1578
bool Session::set_db(const std::string &new_db)
1621
1579
{
1622
1580
  /* Do not reallocate memory if current chunk is big enough. */
1629
1587
}
1630
1588
 
1631
1589
 
1632
 
 
1633
 
 
1634
 
/**
1635
 
  Check the killed state of a user thread
1636
 
  @param session  user thread
1637
 
  @retval 0 the user thread is active
1638
 
  @retval 1 the user thread has been killed
1639
 
*/
1640
 
extern "C" int session_killed(const Session *session)
1641
 
{
1642
 
  return(session->killed);
1643
 
}
1644
 
 
1645
 
/**
1646
 
  Return the session id of a user session
1647
 
  @param pointer to Session object
1648
 
  @return session's id
1649
 
*/
1650
 
extern "C" unsigned long session_get_thread_id(const Session *session)
1651
 
{
1652
 
  return (unsigned long) session->getSessionId();
1653
 
}
1654
 
 
1655
 
 
1656
 
const struct charset_info_st *session_charset(Session *session)
1657
 
{
1658
 
  return(session->charset());
1659
 
}
1660
 
 
1661
 
int session_non_transactional_update(const Session *session)
1662
 
{
1663
 
  return(session->transaction.all.hasModifiedNonTransData());
1664
 
}
1665
 
 
1666
 
void session_mark_transaction_to_rollback(Session *session, bool all)
1667
 
{
1668
 
  mark_transaction_to_rollback(session, all);
1669
 
}
1670
 
 
1671
1590
/**
1672
1591
  Mark transaction to rollback and mark error as fatal to a sub-statement.
1673
1592
 
1690
1609
 
1691
1610
  /* If necessary, log any aborted or unauthorized connections */
1692
1611
  if (killed || client->wasAborted())
1693
 
    statistic_increment(aborted_threads, &LOCK_status);
 
1612
  {
 
1613
    status_var.aborted_threads++;
 
1614
  }
1694
1615
 
1695
1616
  if (client->wasAborted())
1696
1617
  {
1709
1630
 
1710
1631
  /* Close out our connection to the client */
1711
1632
  if (should_lock)
1712
 
    (void) pthread_mutex_lock(&LOCK_thread_count);
 
1633
    LOCK_thread_count.lock();
1713
1634
  killed= Session::KILL_CONNECTION;
1714
1635
  if (client->isConnected())
1715
1636
  {
1721
1642
    client->close();
1722
1643
  }
1723
1644
  if (should_lock)
1724
 
    (void) pthread_mutex_unlock(&LOCK_thread_count);
 
1645
    (void) LOCK_thread_count.unlock();
1725
1646
}
1726
1647
 
1727
1648
void Session::reset_for_next_command()
1759
1680
 
1760
1681
  for (table= temporary_tables; table; table= tmp_next)
1761
1682
  {
1762
 
    tmp_next= table->next;
 
1683
    tmp_next= table->getNext();
1763
1684
    nukeTable(table);
1764
1685
  }
1765
1686
  temporary_tables= NULL;
1771
1692
 
1772
1693
void Session::close_temporary_table(Table *table)
1773
1694
{
1774
 
  if (table->prev)
 
1695
  if (table->getPrev())
1775
1696
  {
1776
 
    table->prev->next= table->next;
1777
 
    if (table->prev->next)
1778
 
      table->next->prev= table->prev;
 
1697
    table->getPrev()->setNext(table->getNext());
 
1698
    if (table->getPrev()->getNext())
 
1699
    {
 
1700
      table->getNext()->setPrev(table->getPrev());
 
1701
    }
1779
1702
  }
1780
1703
  else
1781
1704
  {
1786
1709
      passing non-zero value to end_slave via rli->save_temporary_tables
1787
1710
      when no temp tables opened, see an invariant below.
1788
1711
    */
1789
 
    temporary_tables= table->next;
 
1712
    temporary_tables= table->getNext();
1790
1713
    if (temporary_tables)
1791
 
      table->next->prev= NULL;
 
1714
    {
 
1715
      table->getNext()->setPrev(NULL);
 
1716
    }
1792
1717
  }
1793
1718
  nukeTable(table);
1794
1719
}
1803
1728
 
1804
1729
void Session::nukeTable(Table *table)
1805
1730
{
1806
 
  plugin::StorageEngine *table_type= table->s->db_type();
 
1731
  plugin::StorageEngine *table_type= table->getShare()->db_type();
1807
1732
 
1808
1733
  table->free_io_cache();
1809
 
  table->closefrm(false);
 
1734
  table->delete_table();
1810
1735
 
1811
 
  TableIdentifier identifier(table->s->getSchemaName(), table->s->table_name.str, table->s->path.str);
 
1736
  TableIdentifier identifier(table->getShare()->getSchemaName(), table->getShare()->getTableName(), table->getShare()->getPath());
1812
1737
  rm_temporary_table(table_type, identifier);
1813
1738
 
1814
 
  table->s->free_table_share();
 
1739
  delete table->getMutableShare();
1815
1740
 
1816
1741
  /* This makes me sad, but we're allocating it via malloc */
1817
 
  free(table);
 
1742
  delete table;
1818
1743
}
1819
1744
 
1820
1745
/** Clear most status variables. */
1821
1746
extern time_t flush_status_time;
1822
 
extern uint32_t max_used_connections;
1823
1747
 
1824
1748
void Session::refresh_status()
1825
1749
{
1826
 
  pthread_mutex_lock(&LOCK_status);
1827
 
 
1828
 
  /* Add thread's status variabes to global status */
1829
 
  add_to_status(&global_status_var, &status_var);
1830
 
 
1831
1750
  /* Reset thread's status variables */
1832
1751
  memset(&status_var, 0, sizeof(status_var));
1833
1752
 
1834
 
  /* Reset some global variables */
1835
 
  reset_status_vars();
1836
 
 
1837
 
  /* Reset the counters of all key caches (default and named). */
1838
 
  reset_key_cache_counters();
1839
1753
  flush_status_time= time((time_t*) 0);
1840
 
  max_used_connections= 1; /* We set it to one, because we know we exist */
1841
 
  pthread_mutex_unlock(&LOCK_status);
 
1754
  current_global_counters.max_used_connections= 1; /* We set it to one, because we know we exist */
 
1755
  current_global_counters.connections= 0;
1842
1756
}
1843
1757
 
1844
1758
user_var_entry *Session::getVariable(LEX_STRING &name, bool create_if_not_exists)
1845
1759
{
 
1760
  return getVariable(std::string(name.str, name.length), create_if_not_exists);
 
1761
}
 
1762
 
 
1763
user_var_entry *Session::getVariable(const std::string  &name, bool create_if_not_exists)
 
1764
{
 
1765
  UserVarsRange ppp= user_vars.equal_range(name);
 
1766
 
 
1767
  for (UserVars::iterator iter= ppp.first;
 
1768
       iter != ppp.second; ++iter)
 
1769
  {
 
1770
    return (*iter).second;
 
1771
  }
 
1772
 
 
1773
  if (not create_if_not_exists)
 
1774
    return NULL;
 
1775
 
1846
1776
  user_var_entry *entry= NULL;
1847
 
 
1848
 
  entry= (user_var_entry*) hash_search(&user_vars, (unsigned char*) name.str, name.length);
1849
 
 
1850
 
  if ((entry == NULL) && create_if_not_exists)
 
1777
  entry= new (nothrow) user_var_entry(name.c_str(), query_id);
 
1778
 
 
1779
  if (entry == NULL)
 
1780
    return NULL;
 
1781
 
 
1782
  std::pair<UserVars::iterator, bool> returnable= user_vars.insert(make_pair(name, entry));
 
1783
 
 
1784
  if (not returnable.second)
1851
1785
  {
1852
 
    if (!hash_inited(&user_vars))
1853
 
      return NULL;
1854
 
    entry= new (nothrow) user_var_entry(name.str, query_id);
1855
 
 
1856
 
    if (entry == NULL)
1857
 
      return NULL;
1858
 
 
1859
 
    if (my_hash_insert(&user_vars, (unsigned char*) entry))
1860
 
    {
1861
 
      assert(1);
1862
 
      free((char*) entry);
1863
 
      return 0;
1864
 
    }
1865
 
 
 
1786
    delete entry;
1866
1787
  }
1867
1788
 
1868
1789
  return entry;
1869
1790
}
1870
1791
 
 
1792
void Session::setVariable(const std::string &name, const std::string &value)
 
1793
{
 
1794
  user_var_entry *updateable_var= getVariable(name.c_str(), true);
 
1795
 
 
1796
  updateable_var->update_hash(false,
 
1797
                              (void*)value.c_str(),
 
1798
                              static_cast<uint32_t>(value.length()), STRING_RESULT,
 
1799
                              &my_charset_bin,
 
1800
                              DERIVATION_IMPLICIT, false);
 
1801
}
 
1802
 
1871
1803
void Session::mark_temp_tables_as_free_for_reuse()
1872
1804
{
1873
 
  for (Table *table= temporary_tables ; table ; table= table->next)
 
1805
  for (Table *table= temporary_tables ; table ; table= table->getNext())
1874
1806
  {
1875
1807
    if (table->query_id == query_id)
1876
1808
    {
1882
1814
 
1883
1815
void Session::mark_used_tables_as_free_for_reuse(Table *table)
1884
1816
{
1885
 
  for (; table ; table= table->next)
 
1817
  for (; table ; table= table->getNext())
1886
1818
  {
1887
1819
    if (table->query_id == query_id)
1888
1820
    {
1903
1835
*/
1904
1836
void Session::close_thread_tables()
1905
1837
{
1906
 
  Table *table;
1907
 
 
1908
 
  /*
1909
 
    We are assuming here that session->derived_tables contains ONLY derived
1910
 
    tables for this substatement. i.e. instead of approach which uses
1911
 
    query_id matching for determining which of the derived tables belong
1912
 
    to this substatement we rely on the ability of substatements to
1913
 
    save/restore session->derived_tables during their execution.
1914
 
 
1915
 
    TODO: Probably even better approach is to simply associate list of
1916
 
          derived tables with (sub-)statement instead of thread and destroy
1917
 
          them at the end of its execution.
1918
 
  */
1919
1838
  if (derived_tables)
1920
 
  {
1921
 
    Table *next;
1922
 
    /*
1923
 
      Close all derived tables generated in queries like
1924
 
      SELECT * FROM (SELECT * FROM t1)
1925
 
    */
1926
 
    for (table= derived_tables ; table ; table= next)
1927
 
    {
1928
 
      next= table->next;
1929
 
      table->free_tmp_table(this);
1930
 
    }
1931
 
    derived_tables= 0;
1932
 
  }
 
1839
    derived_tables= NULL; // They should all be invalid by this point
1933
1840
 
1934
1841
  /*
1935
1842
    Mark all temporary tables used by this statement as free for reuse.
1943
1850
    does not belong to statement for which we do close_thread_tables()).
1944
1851
    TODO: This should be fixed in later releases.
1945
1852
   */
1946
 
  if (backups_available == false)
1947
1853
  {
1948
1854
    TransactionServices &transaction_services= TransactionServices::singleton();
1949
1855
    main_da.can_overwrite_status= true;
1950
 
    transaction_services.ha_autocommit_or_rollback(this, is_error());
 
1856
    transaction_services.autocommitOrRollback(this, is_error());
1951
1857
    main_da.can_overwrite_status= false;
1952
1858
    transaction.stmt.reset();
1953
1859
  }
1963
1869
      handled either before writing a query log event (inside
1964
1870
      binlog_query()) or when preparing a pending event.
1965
1871
     */
1966
 
    mysql_unlock_tables(this, lock);
 
1872
    unlockTables(lock);
1967
1873
    lock= 0;
1968
1874
  }
1969
1875
  /*
1970
1876
    Note that we need to hold LOCK_open while changing the
1971
1877
    open_tables list. Another thread may work on it.
1972
 
    (See: remove_table_from_cache(), mysql_wait_completed_table())
 
1878
    (See: table::Cache::singleton().removeTable(), mysql_wait_completed_table())
1973
1879
    Closing a MERGE child before the parent would be fatal if the
1974
1880
    other thread tries to abort the MERGE lock in between.
1975
1881
  */
2008
1914
    close_tables_for_reopen(&tables);
2009
1915
  }
2010
1916
  if ((mysql_handle_derived(lex, &mysql_derived_prepare) ||
2011
 
       (fill_derived_tables() &&
 
1917
       (
2012
1918
        mysql_handle_derived(lex, &mysql_derived_filling))))
2013
1919
    return true;
2014
1920
 
2015
1921
  return false;
2016
1922
}
2017
1923
 
2018
 
bool Session::openTables(TableList *tables, uint32_t flags)
2019
 
{
2020
 
  uint32_t counter;
2021
 
  bool ret= fill_derived_tables();
2022
 
  assert(ret == false);
2023
 
  if (open_tables_from_list(&tables, &counter, flags) ||
2024
 
      mysql_handle_derived(lex, &mysql_derived_prepare))
2025
 
    return true;
2026
 
  return false;
2027
 
}
 
1924
/*
 
1925
  @note "best_effort" is used in cases were if a failure occurred on this
 
1926
  operation it would not be surprising because we are only removing because there
 
1927
  might be an issue (lame engines).
 
1928
*/
2028
1929
 
2029
 
bool Session::rm_temporary_table(TableIdentifier &identifier)
 
1930
bool Session::rm_temporary_table(TableIdentifier &identifier, bool best_effort)
2030
1931
{
2031
1932
  if (plugin::StorageEngine::dropTable(*this, identifier))
2032
1933
  {
2033
 
    errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
2034
 
                  identifier.getSQLPath().c_str(), errno);
2035
 
    dumpTemporaryTableNames("rm_temporary_table()");
 
1934
    if (not best_effort)
 
1935
    {
 
1936
      errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
 
1937
                    identifier.getSQLPath().c_str(), errno);
 
1938
    }
2036
1939
 
2037
1940
    return true;
2038
1941
  }
2048
1951
  {
2049
1952
    errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
2050
1953
                  identifier.getSQLPath().c_str(), errno);
2051
 
    dumpTemporaryTableNames("rm_temporary_table()");
2052
1954
 
2053
1955
    return true;
2054
1956
  }
2068
1970
    return;
2069
1971
 
2070
1972
  cerr << "Begin Run: " << foo << "\n";
2071
 
  for (table= temporary_tables; table; table= table->next)
 
1973
  for (table= temporary_tables; table; table= table->getNext())
2072
1974
  {
2073
1975
    bool have_proto= false;
2074
1976
 
2075
 
    message::Table *proto= table->s->getTableProto();
2076
 
    if (table->s->getTableProto())
 
1977
    message::Table *proto= table->getShare()->getTableProto();
 
1978
    if (table->getShare()->getTableProto())
2077
1979
      have_proto= true;
2078
1980
 
2079
1981
    const char *answer= have_proto ? "true" : "false";
2080
1982
 
2081
1983
    if (have_proto)
2082
1984
    {
2083
 
      cerr << "\tTable Name " << table->s->getSchemaName() << "." << table->s->table_name.str << " : " << answer << "\n";
 
1985
      cerr << "\tTable Name " << table->getShare()->getSchemaName() << "." << table->getShare()->getTableName() << " : " << answer << "\n";
2084
1986
      cerr << "\t\t Proto " << proto->schema() << " " << proto->name() << "\n";
2085
1987
    }
2086
1988
    else
2087
 
      cerr << "\tTabl;e Name " << table->s->getSchemaName() << "." << table->s->table_name.str << " : " << answer << "\n";
 
1989
      cerr << "\tTabl;e Name " << table->getShare()->getSchemaName() << "." << table->getShare()->getTableName() << " : " << answer << "\n";
2088
1990
  }
2089
1991
}
2090
1992
 
2091
 
bool Session::storeTableMessage(TableIdentifier &identifier, message::Table &table_message)
 
1993
bool Session::storeTableMessage(const TableIdentifier &identifier, message::Table &table_message)
2092
1994
{
2093
1995
  table_message_cache.insert(make_pair(identifier.getPath(), table_message));
2094
1996
 
2095
1997
  return true;
2096
1998
}
2097
1999
 
2098
 
bool Session::removeTableMessage(TableIdentifier &identifier)
 
2000
bool Session::removeTableMessage(const TableIdentifier &identifier)
2099
2001
{
2100
2002
  TableMessageCache::iterator iter;
2101
2003
 
2109
2011
  return true;
2110
2012
}
2111
2013
 
2112
 
bool Session::getTableMessage(TableIdentifier &identifier, message::Table &table_message)
 
2014
bool Session::getTableMessage(const TableIdentifier &identifier, message::Table &table_message)
2113
2015
{
2114
2016
  TableMessageCache::iterator iter;
2115
2017
 
2123
2025
  return true;
2124
2026
}
2125
2027
 
2126
 
bool Session::doesTableMessageExist(TableIdentifier &identifier)
 
2028
bool Session::doesTableMessageExist(const TableIdentifier &identifier)
2127
2029
{
2128
2030
  TableMessageCache::iterator iter;
2129
2031
 
2137
2039
  return true;
2138
2040
}
2139
2041
 
2140
 
bool Session::renameTableMessage(TableIdentifier &from, TableIdentifier &to)
 
2042
bool Session::renameTableMessage(const TableIdentifier &from, const TableIdentifier &to)
2141
2043
{
2142
2044
  TableMessageCache::iterator iter;
2143
2045
 
2156
2058
  return true;
2157
2059
}
2158
2060
 
 
2061
table::Instance *Session::getInstanceTable()
 
2062
{
 
2063
  temporary_shares.push_back(new table::Instance()); // This will not go into the tableshare cache, so no key is used.
 
2064
 
 
2065
  table::Instance *tmp_share= temporary_shares.back();
 
2066
 
 
2067
  assert(tmp_share);
 
2068
 
 
2069
  return tmp_share;
 
2070
}
 
2071
 
 
2072
 
 
2073
/**
 
2074
  Create a reduced Table object with properly set up Field list from a
 
2075
  list of field definitions.
 
2076
 
 
2077
    The created table doesn't have a table Cursor associated with
 
2078
    it, has no keys, no group/distinct, no copy_funcs array.
 
2079
    The sole purpose of this Table object is to use the power of Field
 
2080
    class to read/write data to/from table->getInsertRecord(). Then one can store
 
2081
    the record in any container (RB tree, hash, etc).
 
2082
    The table is created in Session mem_root, so are the table's fields.
 
2083
    Consequently, if you don't BLOB fields, you don't need to free it.
 
2084
 
 
2085
  @param session         connection handle
 
2086
  @param field_list  list of column definitions
 
2087
 
 
2088
  @return
 
2089
    0 if out of memory, Table object in case of success
 
2090
*/
 
2091
table::Instance *Session::getInstanceTable(List<CreateField> &field_list)
 
2092
{
 
2093
  temporary_shares.push_back(new table::Instance(this, field_list)); // This will not go into the tableshare cache, so no key is used.
 
2094
 
 
2095
  table::Instance *tmp_share= temporary_shares.back();
 
2096
 
 
2097
  assert(tmp_share);
 
2098
 
 
2099
  return tmp_share;
 
2100
}
 
2101
 
2159
2102
} /* namespace drizzled */