~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/session.cc

  • Committer: Monty Taylor
  • Date: 2010-06-18 00:34:51 UTC
  • mto: (1627.2.5 build)
  • mto: This revision was merged to the branch mainline in revision 1628.
  • Revision ID: mordred@inaugust.com-20100618003451-2b3fs2m2hvpch91r
Add function pointer hook for plugins to register program_options.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
3
 *
4
 
 *  Copyright (C) 2008 Sun Microsystems, Inc.
 
4
 *  Copyright (C) 2008 Sun Microsystems
5
5
 *
6
6
 *  This program is free software; you can redistribute it and/or modify
7
7
 *  it under the terms of the GNU General Public License as published by
21
21
 * @file Implementation of the Session class and API
22
22
 */
23
23
 
24
 
#include <config.h>
25
 
 
26
 
#include <drizzled/copy_field.h>
27
 
#include <drizzled/data_home.h>
28
 
#include <drizzled/display.h>
29
 
#include <drizzled/drizzled.h>
 
24
#include "config.h"
 
25
#include <drizzled/session.h>
 
26
#include "drizzled/session_list.h"
 
27
#include <sys/stat.h>
30
28
#include <drizzled/error.h>
31
29
#include <drizzled/gettext.h>
32
 
#include <drizzled/identifier.h>
33
 
#include <drizzled/internal/iocache.h>
34
 
#include <drizzled/internal/thread_var.h>
35
 
#include <drizzled/internal_error_handler.h>
 
30
#include <drizzled/query_id.h>
 
31
#include <drizzled/data_home.h>
 
32
#include <drizzled/sql_base.h>
 
33
#include <drizzled/lock.h>
36
34
#include <drizzled/item/cache.h>
37
 
#include <drizzled/item/empty_string.h>
38
35
#include <drizzled/item/float.h>
39
36
#include <drizzled/item/return_int.h>
40
 
#include <drizzled/lock.h>
41
 
#include <drizzled/plugin/authentication.h>
 
37
#include <drizzled/item/empty_string.h>
 
38
#include <drizzled/show.h>
42
39
#include <drizzled/plugin/client.h>
43
 
#include <drizzled/plugin/event_observer.h>
44
 
#include <drizzled/plugin/logging.h>
45
 
#include <drizzled/plugin/query_rewrite.h>
46
 
#include <drizzled/plugin/scheduler.h>
47
 
#include <drizzled/plugin/transactional_storage_engine.h>
48
 
#include <drizzled/probes.h>
49
 
#include <drizzled/pthread_globals.h>
50
 
#include <drizzled/query_id.h>
51
 
#include <drizzled/refresh_version.h>
52
 
#include <drizzled/select_dump.h>
53
 
#include <drizzled/select_exists_subselect.h>
54
 
#include <drizzled/select_export.h>
55
 
#include <drizzled/select_max_min_finder_subselect.h>
56
 
#include <drizzled/select_singlerow_subselect.h>
57
 
#include <drizzled/select_subselect.h>
58
 
#include <drizzled/select_to_file.h>
59
 
#include <drizzled/session.h>
60
 
#include <drizzled/session/cache.h>
61
 
#include <drizzled/show.h>
62
 
#include <drizzled/sql_base.h>
63
 
#include <drizzled/table/singular.h>
64
 
#include <drizzled/table_proto.h>
65
 
#include <drizzled/tmp_table_param.h>
66
 
#include <drizzled/transaction_services.h>
67
 
#include <drizzled/user_var_entry.h>
68
 
#include <drizzled/util/functors.h>
69
 
#include <plugin/myisam/myisam.h>
70
 
 
 
40
#include "drizzled/plugin/scheduler.h"
 
41
#include "drizzled/plugin/authentication.h"
 
42
#include "drizzled/plugin/logging.h"
 
43
#include "drizzled/plugin/transactional_storage_engine.h"
 
44
#include "drizzled/probes.h"
 
45
#include "drizzled/table_proto.h"
 
46
#include "drizzled/db.h"
 
47
#include "drizzled/pthread_globals.h"
 
48
#include "drizzled/transaction_services.h"
 
49
#include "drizzled/drizzled.h"
 
50
 
 
51
#include "drizzled/table_share_instance.h"
 
52
 
 
53
#include "plugin/myisam/myisam.h"
 
54
#include "drizzled/internal/iocache.h"
 
55
#include "drizzled/plugin/event_observer.h"
 
56
 
 
57
#include <fcntl.h>
71
58
#include <algorithm>
72
59
#include <climits>
73
 
#include <fcntl.h>
74
 
#include <sys/stat.h>
75
 
 
76
 
#include <boost/filesystem.hpp>
77
 
#include <boost/checked_delete.hpp>
78
 
 
79
 
#include <drizzled/util/backtrace.h>
80
 
 
81
 
#include <drizzled/schema.h>
82
60
 
83
61
using namespace std;
84
 
 
85
 
namespace fs=boost::filesystem;
86
62
namespace drizzled
87
63
{
88
64
 
94
70
char empty_c_string[1]= {0};    /* used for not defined db */
95
71
 
96
72
const char * const Session::DEFAULT_WHERE= "field list";
 
73
extern pthread_key_t THR_Session;
 
74
extern pthread_key_t THR_Mem_root;
 
75
 
 
76
 
 
77
/****************************************************************************
 
78
** User variables
 
79
****************************************************************************/
 
80
static unsigned char *get_var_key(user_var_entry *entry, size_t *length, bool)
 
81
{
 
82
  *length= entry->name.length;
 
83
  return (unsigned char*) entry->name.str;
 
84
}
 
85
 
 
86
static void free_user_var(user_var_entry *entry)
 
87
{
 
88
  delete entry;
 
89
}
97
90
 
98
91
bool Key_part_spec::operator==(const Key_part_spec& other) const
99
92
{
100
93
  return length == other.length &&
101
94
         field_name.length == other.field_name.length &&
102
 
    !my_strcasecmp(system_charset_info, field_name.str, other.field_name.str);
 
95
         !strcmp(field_name.str, other.field_name.str);
103
96
}
104
97
 
105
98
Open_tables_state::Open_tables_state(uint64_t version_arg) :
112
105
/*
113
106
  The following functions form part of the C plugin API
114
107
*/
115
 
int tmpfile(const char *prefix)
 
108
int mysql_tmpfile(const char *prefix)
116
109
{
117
110
  char filename[FN_REFLEN];
118
111
  int fd = internal::create_temp_file(filename, drizzle_tmpdir.c_str(), prefix, MYF(MY_WME));
123
116
  return fd;
124
117
}
125
118
 
 
119
int session_tablespace_op(const Session *session)
 
120
{
 
121
  return test(session->tablespace_op);
 
122
}
 
123
 
 
124
/**
 
125
   Set the process info field of the Session structure.
 
126
 
 
127
   This function is used by plug-ins. Internally, the
 
128
   Session::set_proc_info() function should be used.
 
129
 
 
130
   @see Session::set_proc_info
 
131
 */
 
132
void set_session_proc_info(Session *session, const char *info)
 
133
{
 
134
  session->set_proc_info(info);
 
135
}
 
136
 
 
137
const char *get_session_proc_info(Session *session)
 
138
{
 
139
  return session->get_proc_info();
 
140
}
 
141
 
126
142
void **Session::getEngineData(const plugin::MonitoredInTransaction *monitored)
127
143
{
128
144
  return static_cast<void **>(&ha_data[monitored->getId()].ha_ptr);
139
155
  return session->options & test_options;
140
156
}
141
157
 
142
 
Session::Session(plugin::Client *client_arg, catalog::Instance::shared_ptr catalog_arg) :
 
158
int session_sql_command(const Session *session)
 
159
{
 
160
  return (int) session->lex->sql_command;
 
161
}
 
162
 
 
163
int session_tx_isolation(const Session *session)
 
164
{
 
165
  return (int) session->variables.tx_isolation;
 
166
}
 
167
 
 
168
Session::Session(plugin::Client *client_arg) :
143
169
  Open_tables_state(refresh_version),
144
170
  mem_root(&main_mem_root),
145
 
  xa_id(0),
146
171
  lex(&main_lex),
147
 
  query(new std::string),
148
 
  _schema(new std::string("")),
 
172
  query(),
149
173
  client(client_arg),
150
174
  scheduler(NULL),
151
175
  scheduler_arg(NULL),
152
176
  lock_id(&main_lock_id),
153
 
  thread_stack(NULL),
154
 
  security_ctx(identifier::User::make_shared()),
155
 
  _where(Session::DEFAULT_WHERE),
156
 
  dbug_sentry(Session_SENTRY_MAGIC),
157
 
  mysys_var(0),
158
 
  command(COM_CONNECT),
159
 
  file_id(0),
160
 
  _epoch(boost::gregorian::date(1970,1,1)),
161
 
  _connect_time(boost::posix_time::microsec_clock::universal_time()),
162
 
  utime_after_lock(0),
 
177
  user_time(0),
163
178
  ha_data(plugin::num_trx_monitored_objects),
164
 
  query_id(0),
165
 
  warn_query_id(0),
166
 
  concurrent_execute_allowed(true),
167
179
  arg_of_last_insert_id_function(false),
168
180
  first_successful_insert_id_in_prev_stmt(0),
169
181
  first_successful_insert_id_in_cur_stmt(0),
170
182
  limit_found_rows(0),
171
 
  options(session_startup_options),
172
 
  row_count_func(-1),
173
 
  sent_row_count(0),
174
 
  examined_row_count(0),
175
 
  used_tables(0),
176
 
  total_warn_count(0),
177
 
  col_access(0),
178
 
  statement_id_counter(0),
179
 
  row_count(0),
180
 
  thread_id(0),
181
 
  tmp_table(0),
182
 
  _global_read_lock(NONE),
183
 
  count_cuted_fields(CHECK_FIELD_ERROR_FOR_NULL),
184
 
  _killed(NOT_KILLED),
 
183
  global_read_lock(0),
185
184
  some_tables_deleted(false),
186
185
  no_errors(false),
187
186
  password(false),
188
187
  is_fatal_error(false),
189
188
  transaction_rollback_request(false),
190
189
  is_fatal_sub_stmt_error(0),
 
190
  derived_tables_processing(false),
191
191
  tablespace_op(false),
192
 
  derived_tables_processing(false),
193
192
  m_lip(NULL),
194
193
  cached_table(0),
195
194
  transaction_message(NULL),
196
195
  statement_message(NULL),
197
 
  session_event_observers(NULL),
198
 
  _catalog(catalog_arg),
199
 
  use_usage(false)
 
196
  session_event_observers(NULL)
200
197
{
 
198
  memset(process_list_info, 0, PROCESS_LIST_WIDTH);
201
199
  client->setSession(this);
202
200
 
203
201
  /*
206
204
    will be re-initialized in init_for_queries().
207
205
  */
208
206
  memory::init_sql_alloc(&main_mem_root, memory::ROOT_MIN_BLOCK_SIZE, 0);
 
207
  thread_stack= NULL;
 
208
  count_cuted_fields= CHECK_FIELD_IGNORE;
 
209
  killed= NOT_KILLED;
 
210
  col_access= 0;
 
211
  tmp_table= 0;
 
212
  used_tables= 0;
209
213
  cuted_fields= sent_row_count= row_count= 0L;
 
214
  row_count_func= -1;
 
215
  statement_id_counter= 0UL;
210
216
  // Must be reset to handle error with Session's created for init of mysqld
211
217
  lex->current_select= 0;
 
218
  start_time=(time_t) 0;
 
219
  start_utime= 0L;
 
220
  utime_after_lock= 0L;
212
221
  memset(&variables, 0, sizeof(variables));
 
222
  thread_id= 0;
 
223
  file_id = 0;
 
224
  query_id= 0;
 
225
  warn_query_id= 0;
 
226
  mysys_var= 0;
213
227
  scoreboard_index= -1;
214
 
  cleanup_done= abort_on_warning= no_warnings_for_error= false;  
215
 
 
216
 
  /* query_cache init */
217
 
  query_cache_key= "";
218
 
  resultset= NULL;
 
228
  dbug_sentry=Session_SENTRY_MAGIC;
 
229
  cleanup_done= abort_on_warning= no_warnings_for_error= false;
 
230
  pthread_mutex_init(&LOCK_delete, MY_MUTEX_INIT_FAST);
219
231
 
220
232
  /* Variables with default values */
221
233
  proc_info="login";
 
234
  where= Session::DEFAULT_WHERE;
 
235
  command= COM_CONNECT;
222
236
 
223
237
  plugin_sessionvar_init(this);
224
238
  /*
228
242
  */
229
243
  variables.pseudo_thread_id= thread_id;
230
244
  server_status= SERVER_STATUS_AUTOCOMMIT;
 
245
  options= session_startup_options;
231
246
 
232
247
  if (variables.max_join_size == HA_POS_ERROR)
233
248
    options |= OPTION_BIG_SELECTS;
237
252
  open_options=ha_open_options;
238
253
  update_lock_default= TL_WRITE;
239
254
  session_tx_isolation= (enum_tx_isolation) variables.tx_isolation;
240
 
  warn_list.clear();
 
255
  warn_list.empty();
241
256
  memset(warn_count, 0, sizeof(warn_count));
 
257
  total_warn_count= 0;
242
258
  memset(&status_var, 0, sizeof(status_var));
243
259
 
244
260
  /* Initialize sub structures */
245
261
  memory::init_sql_alloc(&warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE);
 
262
  hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0,
 
263
            (hash_get_key) get_var_key,
 
264
            (hash_free_key) free_user_var, 0);
246
265
 
247
266
  substitute_null_with_insert_id = false;
248
 
  lock_info.init(); /* safety: will be reset after start */
 
267
  thr_lock_info_init(&lock_info); /* safety: will be reset after start */
249
268
  thr_lock_owner_init(&main_lock_id, &lock_info);
250
269
 
251
270
  m_internal_handler= NULL;
274
293
  m_internal_handler= handler;
275
294
}
276
295
 
277
 
bool Session::handle_error(drizzled::error_t sql_errno, const char *message,
278
 
                           DRIZZLE_ERROR::enum_warning_level level)
 
296
bool Session::handle_error(uint32_t sql_errno, const char *message,
 
297
                       DRIZZLE_ERROR::enum_warning_level level)
279
298
{
280
299
  if (m_internal_handler)
281
300
  {
285
304
  return false;                                 // 'false', as per coding style
286
305
}
287
306
 
288
 
void Session::setAbort(bool arg)
289
 
{
290
 
  mysys_var->abort= arg;
291
 
}
292
 
 
293
 
void Session::lockOnSys()
294
 
{
295
 
  if (not mysys_var)
296
 
    return;
297
 
 
298
 
  setAbort(true);
299
 
  boost_unique_lock_t scopedLock(mysys_var->mutex);
300
 
  if (mysys_var->current_cond)
301
 
  {
302
 
    mysys_var->current_mutex->lock();
303
 
    mysys_var->current_cond->notify_all();
304
 
    mysys_var->current_mutex->unlock();
305
 
  }
306
 
}
307
 
 
308
307
void Session::pop_internal_handler()
309
308
{
310
309
  assert(m_internal_handler != NULL);
311
310
  m_internal_handler= NULL;
312
311
}
313
312
 
314
 
void Session::get_xid(DrizzleXid *xid)
 
313
void Session::get_xid(DRIZZLE_XID *xid)
315
314
{
316
 
  *xid = *(DrizzleXid *) &transaction.xid_state.xid;
 
315
  *xid = *(DRIZZLE_XID *) &transaction.xid_state.xid;
317
316
}
318
317
 
319
318
/* Do operations that may take a long time */
322
321
{
323
322
  assert(cleanup_done == false);
324
323
 
325
 
  setKilled(KILL_CONNECTION);
 
324
  killed= KILL_CONNECTION;
326
325
#ifdef ENABLE_WHEN_BINLOG_WILL_BE_ABLE_TO_PREPARE
327
326
  if (transaction.xid_state.xa_state == XA_PREPARED)
328
327
  {
331
330
#endif
332
331
  {
333
332
    TransactionServices &transaction_services= TransactionServices::singleton();
334
 
    transaction_services.rollbackTransaction(*this, true);
 
333
    transaction_services.rollbackTransaction(this, true);
335
334
    xid_cache_delete(&transaction.xid_state);
336
335
  }
337
 
 
338
 
  for (UserVars::iterator iter= user_vars.begin();
339
 
       iter != user_vars.end();
340
 
       iter++)
341
 
  {
342
 
    user_var_entry *entry= (*iter).second;
343
 
    boost::checked_delete(entry);
344
 
  }
345
 
  user_vars.clear();
346
 
 
347
 
 
 
336
  hash_free(&user_vars);
348
337
  close_temporary_tables();
349
338
 
350
339
  if (global_read_lock)
351
 
  {
352
 
    unlockGlobalReadLock();
353
 
  }
 
340
    unlock_global_read_lock(this);
354
341
 
355
342
  cleanup_done= true;
356
343
}
359
346
{
360
347
  this->checkSentry();
361
348
 
362
 
  if (client and client->isConnected())
 
349
  if (client->isConnected())
363
350
  {
364
 
    assert(security_ctx);
365
351
    if (global_system_variables.log_warnings)
366
 
    {
367
 
      errmsg_printf(error::WARN, ER(ER_FORCING_CLOSE),
368
 
                    internal::my_progname,
369
 
                    thread_id,
370
 
                    security_ctx->username().c_str());
371
 
    }
372
 
 
373
 
    disconnect();
 
352
        errmsg_printf(ERRMSG_LVL_WARN, ER(ER_FORCING_CLOSE),internal::my_progname,
 
353
                      thread_id,
 
354
                      (getSecurityContext().getUser().c_str() ?
 
355
                       getSecurityContext().getUser().c_str() : ""));
 
356
    disconnect(0, false);
374
357
  }
375
358
 
376
359
  /* Close connection */
377
 
  if (client)
378
 
  {
379
 
    client->close();
380
 
    boost::checked_delete(client);
381
 
    client= NULL;
382
 
  }
 
360
  client->close();
 
361
  delete client;
383
362
 
384
363
  if (cleanup_done == false)
385
364
    cleanup();
392
371
  dbug_sentry= Session_SENTRY_GONE;
393
372
 
394
373
  main_mem_root.free_root(MYF(0));
395
 
  currentMemRoot().release();
396
 
  currentSession().release();
 
374
  pthread_setspecific(THR_Session,  0);
397
375
 
398
376
  plugin::Logging::postEndDo(this);
399
377
  plugin::EventObserver::deregisterSessionEvents(*this); 
400
 
}
401
 
 
402
 
void Session::setClient(plugin::Client *client_arg)
403
 
{
404
 
  client= client_arg;
405
 
  client->setSession(this);
406
 
}
407
 
 
408
 
void Session::awake(Session::killed_state_t state_to_set)
409
 
{
410
 
  if ((state_to_set == Session::KILL_QUERY) and (command == COM_SLEEP))
411
 
    return;
412
 
 
 
378
 
 
379
  /* Ensure that no one is using Session */
 
380
  pthread_mutex_unlock(&LOCK_delete);
 
381
  pthread_mutex_destroy(&LOCK_delete);
 
382
}
 
383
 
 
384
void Session::awake(Session::killed_state state_to_set)
 
385
{
413
386
  this->checkSentry();
414
 
 
415
 
  setKilled(state_to_set);
416
 
  scheduler->killSession(this);
417
 
 
 
387
  safe_mutex_assert_owner(&LOCK_delete);
 
388
 
 
389
  killed= state_to_set;
418
390
  if (state_to_set != Session::KILL_QUERY)
419
391
  {
 
392
    scheduler->killSession(this);
420
393
    DRIZZLE_CONNECTION_DONE(thread_id);
421
394
  }
422
 
 
423
395
  if (mysys_var)
424
396
  {
425
 
    boost_unique_lock_t scopedLock(mysys_var->mutex);
 
397
    pthread_mutex_lock(&mysys_var->mutex);
426
398
    /*
427
 
      "
428
399
      This broadcast could be up in the air if the victim thread
429
400
      exits the cond in the time between read and broadcast, but that is
430
401
      ok since all we want to do is to make the victim thread get out
445
416
    */
446
417
    if (mysys_var->current_cond && mysys_var->current_mutex)
447
418
    {
448
 
      mysys_var->current_mutex->lock();
449
 
      mysys_var->current_cond->notify_all();
450
 
      mysys_var->current_mutex->unlock();
 
419
      pthread_mutex_lock(mysys_var->current_mutex);
 
420
      pthread_cond_broadcast(mysys_var->current_cond);
 
421
      pthread_mutex_unlock(mysys_var->current_mutex);
451
422
    }
 
423
    pthread_mutex_unlock(&mysys_var->mutex);
452
424
  }
453
425
}
454
426
 
464
436
  */
465
437
  assert(thread_stack);
466
438
 
467
 
  currentSession().release();
468
 
  currentSession().reset(this);
469
 
 
470
 
  currentMemRoot().release();
471
 
  currentMemRoot().reset(&mem_root);
 
439
  if (pthread_setspecific(THR_Session,  this) ||
 
440
      pthread_setspecific(THR_Mem_root, &mem_root))
 
441
    return true;
472
442
 
473
443
  mysys_var=my_thread_var;
474
444
 
477
447
    This allows us to move Session to different threads if needed.
478
448
  */
479
449
  mysys_var->id= thread_id;
 
450
  real_id= pthread_self();                      // For debugging
480
451
 
481
452
  /*
482
453
    We have to call thr_lock_info_init() again here as Session may have been
483
454
    created in another thread
484
455
  */
485
 
  lock_info.init();
486
 
 
 
456
  thr_lock_info_init(&lock_info);
487
457
  return false;
488
458
}
489
459
 
507
477
                                variables.query_prealloc_size);
508
478
  transaction.xid_state.xid.null();
509
479
  transaction.xid_state.in_session=1;
510
 
  if (use_usage)
511
 
    resetUsage();
512
480
}
513
481
 
514
482
bool Session::initGlobals()
515
483
{
516
484
  if (storeGlobals())
517
485
  {
518
 
    disconnect(ER_OUT_OF_RESOURCES);
519
 
    status_var.aborted_connects++;
 
486
    disconnect(ER_OUT_OF_RESOURCES, true);
 
487
    status_var_increment(current_global_counters.aborted_connects);
520
488
    return true;
521
489
  }
522
490
  return false;
526
494
{
527
495
  if (initGlobals() || authenticate())
528
496
  {
529
 
    disconnect();
 
497
    disconnect(0, true);
530
498
    return;
531
499
  }
532
500
 
533
501
  prepareForQueries();
534
502
 
535
 
  while (not client->haveError() && getKilled() != KILL_CONNECTION)
 
503
  while (! client->haveError() && killed != KILL_CONNECTION)
536
504
  {
537
 
    if (not executeStatement())
 
505
    if (! executeStatement())
538
506
      break;
539
507
  }
540
508
 
541
 
  disconnect();
 
509
  disconnect(0, true);
542
510
}
543
511
 
544
 
bool Session::schedule(Session::shared_ptr &arg)
 
512
bool Session::schedule()
545
513
{
546
 
  arg->scheduler= plugin::Scheduler::getScheduler();
547
 
  assert(arg->scheduler);
548
 
 
549
 
  ++connection_count;
550
 
 
551
 
  long current_connections= connection_count;
552
 
 
553
 
  if (current_connections > 0 and static_cast<uint64_t>(current_connections) > current_global_counters.max_used_connections)
554
 
  {
555
 
    current_global_counters.max_used_connections= static_cast<uint64_t>(connection_count);
556
 
  }
557
 
 
558
 
  current_global_counters.connections++;
559
 
  arg->thread_id= arg->variables.pseudo_thread_id= global_thread_id++;
560
 
 
561
 
  session::Cache::singleton().insert(arg);
562
 
 
563
 
  if (unlikely(plugin::EventObserver::connectSession(*arg)))
564
 
  {
565
 
    // We should do something about an error...
566
 
  }
567
 
 
568
 
  if (plugin::Scheduler::getScheduler()->addSession(arg))
569
 
  {
570
 
    DRIZZLE_CONNECTION_START(arg->getSessionId());
 
514
  scheduler= plugin::Scheduler::getScheduler();
 
515
  assert(scheduler);
 
516
 
 
517
  connection_count.increment();
 
518
 
 
519
  if (connection_count > current_global_counters.max_used_connections)
 
520
  {
 
521
    current_global_counters.max_used_connections= connection_count;
 
522
  }
 
523
 
 
524
  thread_id= variables.pseudo_thread_id= global_thread_id++;
 
525
 
 
526
  pthread_mutex_lock(&LOCK_thread_count);
 
527
  getSessionList().push_back(this);
 
528
  pthread_mutex_unlock(&LOCK_thread_count);
 
529
 
 
530
  if (scheduler->addSession(this))
 
531
  {
 
532
    DRIZZLE_CONNECTION_START(thread_id);
571
533
    char error_message_buff[DRIZZLE_ERRMSG_SIZE];
572
534
 
573
 
    arg->setKilled(Session::KILL_CONNECTION);
 
535
    killed= Session::KILL_CONNECTION;
574
536
 
575
 
    arg->status_var.aborted_connects++;
 
537
    status_var_increment(current_global_counters.aborted_connects);
576
538
 
577
539
    /* Can't use my_error() since store_globals has not been called. */
578
540
    /* TODO replace will better error message */
579
541
    snprintf(error_message_buff, sizeof(error_message_buff),
580
542
             ER(ER_CANT_CREATE_THREAD), 1);
581
 
    arg->client->sendError(ER_CANT_CREATE_THREAD, error_message_buff);
582
 
 
 
543
    client->sendError(ER_CANT_CREATE_THREAD, error_message_buff);
583
544
    return true;
584
545
  }
585
546
 
587
548
}
588
549
 
589
550
 
590
 
/*
591
 
  Is this session viewable by the current user?
592
 
*/
593
 
bool Session::isViewable(identifier::User::const_reference user_arg) const
594
 
{
595
 
  return plugin::Authorization::isAuthorized(user_arg, *this, false);
596
 
}
597
 
 
598
 
 
599
 
const char* Session::enter_cond(boost::condition_variable_any &cond, boost::mutex &mutex, const char* msg)
 
551
const char* Session::enter_cond(pthread_cond_t *cond,
 
552
                                pthread_mutex_t* mutex,
 
553
                                const char* msg)
600
554
{
601
555
  const char* old_msg = get_proc_info();
602
556
  safe_mutex_assert_owner(mutex);
603
 
  mysys_var->current_mutex = &mutex;
604
 
  mysys_var->current_cond = &cond;
 
557
  mysys_var->current_mutex = mutex;
 
558
  mysys_var->current_cond = cond;
605
559
  this->set_proc_info(msg);
606
560
  return old_msg;
607
561
}
614
568
    locked (if that would not be the case, you'll get a deadlock if someone
615
569
    does a Session::awake() on you).
616
570
  */
617
 
  mysys_var->current_mutex->unlock();
618
 
  boost_unique_lock_t scopedLock(mysys_var->mutex);
 
571
  pthread_mutex_unlock(mysys_var->current_mutex);
 
572
  pthread_mutex_lock(&mysys_var->mutex);
619
573
  mysys_var->current_mutex = 0;
620
574
  mysys_var->current_cond = 0;
621
575
  this->set_proc_info(old_msg);
 
576
  pthread_mutex_unlock(&mysys_var->mutex);
622
577
}
623
578
 
624
579
bool Session::authenticate()
625
580
{
 
581
  lex_start(this);
626
582
  if (client->authenticate())
627
583
    return false;
628
584
 
629
 
  status_var.aborted_connects++;
630
 
 
 
585
  status_var_increment(current_global_counters.aborted_connects);
631
586
  return true;
632
587
}
633
588
 
634
 
bool Session::checkUser(const std::string &passwd_str,
635
 
                        const std::string &in_db)
 
589
bool Session::checkUser(const char *passwd, uint32_t passwd_len, const char *in_db)
636
590
{
 
591
  const string passwd_str(passwd, passwd_len);
637
592
  bool is_authenticated=
638
 
    plugin::Authentication::isAuthenticated(*user(), passwd_str);
 
593
    plugin::Authentication::isAuthenticated(getSecurityContext(),
 
594
                                            passwd_str);
639
595
 
640
596
  if (is_authenticated != true)
641
597
  {
642
 
    status_var.access_denied++;
643
598
    /* isAuthenticated has pushed the error message */
644
599
    return false;
645
600
  }
646
601
 
647
602
  /* Change database if necessary */
648
 
  if (not in_db.empty())
 
603
  if (in_db && in_db[0])
649
604
  {
650
 
    identifier::Schema identifier(in_db);
651
 
    if (schema::change(*this, identifier))
 
605
    SchemaIdentifier identifier(in_db);
 
606
    if (mysql_change_db(this, identifier))
652
607
    {
653
 
      /* change_db() has pushed the error message. */
 
608
      /* mysql_change_db() has pushed the error message. */
654
609
      return false;
655
610
    }
656
611
  }
657
612
  my_ok();
658
 
  password= not passwd_str.empty();
 
613
  password= test(passwd_len);          // remember for error messages
659
614
 
660
615
  /* Ready to handle queries */
661
616
  return true;
677
632
  main_da.reset_diagnostics_area();
678
633
 
679
634
  if (client->readCommand(&l_packet, &packet_length) == false)
680
 
  {
681
 
    return false;
682
 
  }
683
 
 
684
 
  if (getKilled() == KILL_CONNECTION)
685
635
    return false;
686
636
 
687
637
  if (packet_length == 0)
688
638
    return true;
689
639
 
690
 
  l_command= static_cast<enum_server_command>(l_packet[0]);
 
640
  l_command= (enum enum_server_command) (unsigned char) l_packet[0];
691
641
 
692
642
  if (command >= COM_END)
693
643
    command= COM_END;                           // Wrong command
694
644
 
695
645
  assert(packet_length);
696
 
  return not dispatch_command(l_command, this, l_packet+1, (uint32_t) (packet_length-1));
 
646
  return ! dispatch_command(l_command, this, l_packet+1, (uint32_t) (packet_length-1));
697
647
}
698
648
 
699
649
bool Session::readAndStoreQuery(const char *in_packet, uint32_t in_packet_length)
705
655
    in_packet_length--;
706
656
  }
707
657
  const char *pos= in_packet + in_packet_length; /* Point at end null */
708
 
  while (in_packet_length > 0 && (pos[-1] == ';' || my_isspace(charset() ,pos[-1])))
 
658
  while (in_packet_length > 0 &&
 
659
         (pos[-1] == ';' || my_isspace(charset() ,pos[-1])))
709
660
  {
710
661
    pos--;
711
662
    in_packet_length--;
712
663
  }
713
664
 
714
 
  std::string *new_query= new std::string(in_packet, in_packet + in_packet_length);
715
 
  // We can not be entirely sure _schema has a value
716
 
  if (_schema)
717
 
  {
718
 
    plugin::QueryRewriter::rewriteQuery(*_schema, *new_query);
719
 
  }
720
 
  query.reset(new_query);
721
 
  _state.reset(new session::State(in_packet, in_packet_length));
 
665
  query.assign(in_packet, in_packet + in_packet_length);
722
666
 
723
667
  return true;
724
668
}
743
687
       * (Which of course should never happen...)
744
688
       */
745
689
      server_status&= ~SERVER_STATUS_IN_TRANS;
746
 
      if (transaction_services.commitTransaction(*this, true))
 
690
      if (transaction_services.commitTransaction(this, true))
747
691
        result= false;
748
692
      options&= ~(OPTION_BEGIN);
749
693
      break;
760
704
    case ROLLBACK_AND_CHAIN:
761
705
    {
762
706
      server_status&= ~SERVER_STATUS_IN_TRANS;
763
 
      if (transaction_services.rollbackTransaction(*this, true))
 
707
      if (transaction_services.rollbackTransaction(this, true))
764
708
        result= false;
765
709
      options&= ~(OPTION_BEGIN);
766
710
      if (result == true && (completion == ROLLBACK_AND_CHAIN))
773
717
  }
774
718
 
775
719
  if (result == false)
776
 
  {
777
 
    my_error(static_cast<drizzled::error_t>(killed_errno()), MYF(0));
778
 
  }
 
720
    my_error(killed_errno(), MYF(0));
779
721
  else if ((result == true) && do_release)
780
 
  {
781
 
    setKilled(Session::KILL_CONNECTION);
782
 
  }
 
722
    killed= Session::KILL_CONNECTION;
783
723
 
784
724
  return result;
785
725
}
797
737
  if (options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
798
738
  {
799
739
    server_status&= ~SERVER_STATUS_IN_TRANS;
800
 
    if (transaction_services.commitTransaction(*this, true))
 
740
    if (transaction_services.commitTransaction(this, true))
801
741
      result= false;
802
742
  }
803
743
  options&= ~(OPTION_BEGIN);
808
748
{
809
749
  bool result= true;
810
750
 
811
 
  assert(! inTransaction());
812
 
 
813
 
  options|= OPTION_BEGIN;
814
 
  server_status|= SERVER_STATUS_IN_TRANS;
815
 
 
816
 
  if (plugin::TransactionalStorageEngine::notifyStartTransaction(this, opt))
 
751
  if (! endActiveTransaction())
817
752
  {
818
753
    result= false;
819
754
  }
 
755
  else
 
756
  {
 
757
    options|= OPTION_BEGIN;
 
758
    server_status|= SERVER_STATUS_IN_TRANS;
 
759
 
 
760
    if (plugin::TransactionalStorageEngine::notifyStartTransaction(this, opt))
 
761
    {
 
762
      result= false;
 
763
    }
 
764
  }
820
765
 
821
766
  return result;
822
767
}
838
783
    first_successful_insert_id_in_cur_stmt= 0;
839
784
    substitute_null_with_insert_id= true;
840
785
  }
841
 
 
842
786
  arg_of_last_insert_id_function= false;
843
 
 
844
787
  /* Free Items that were created during this execution */
845
788
  free_items();
846
 
 
847
 
  /* Reset _where. */
848
 
  _where= Session::DEFAULT_WHERE;
 
789
  /* Reset where. */
 
790
  where= Session::DEFAULT_WHERE;
849
791
 
850
792
  /* Reset the temporary shares we built */
851
 
  for_each(temporary_shares.begin(),
852
 
           temporary_shares.end(),
853
 
           DeletePtr());
 
793
  for (std::vector<TableShareInstance *>::iterator iter= temporary_shares.begin();
 
794
       iter != temporary_shares.end(); iter++)
 
795
  {
 
796
    delete *iter;
 
797
  }
854
798
  temporary_shares.clear();
855
799
}
856
800
 
876
820
                                     bool allocate_lex_string)
877
821
{
878
822
  if (allocate_lex_string)
879
 
    if (!(lex_str= (LEX_STRING *)getMemRoot()->allocate(sizeof(LEX_STRING))))
 
823
    if (!(lex_str= (LEX_STRING *)alloc(sizeof(LEX_STRING))))
880
824
      return 0;
881
825
  if (!(lex_str->str= mem_root->strmake_root(str, length)))
882
826
    return 0;
922
866
  return (result->send_fields(field_list));
923
867
}
924
868
 
925
 
void select_result::send_error(drizzled::error_t errcode, const char *err)
 
869
void select_result::send_error(uint32_t errcode, const char *err)
926
870
{
927
871
  my_message(errcode, err, MYF(0));
928
872
}
931
875
  Handling writing to file
932
876
************************************************************************/
933
877
 
934
 
void select_to_file::send_error(drizzled::error_t errcode,const char *err)
 
878
void select_to_file::send_error(uint32_t errcode,const char *err)
935
879
{
936
880
  my_message(errcode, err, MYF(0));
937
881
  if (file > 0)
938
882
  {
939
 
    (void) cache->end_io_cache();
 
883
    (void) end_io_cache(cache);
940
884
    (void) internal::my_close(file, MYF(0));
941
 
    (void) internal::my_delete(path.file_string().c_str(), MYF(0));             // Delete file on error
 
885
    (void) internal::my_delete(path, MYF(0));           // Delete file on error
942
886
    file= -1;
943
887
  }
944
888
}
946
890
 
947
891
bool select_to_file::send_eof()
948
892
{
949
 
  int error= test(cache->end_io_cache());
 
893
  int error= test(end_io_cache(cache));
950
894
  if (internal::my_close(file, MYF(MY_WME)))
951
895
    error= 1;
952
896
  if (!error)
968
912
  /* In case of error send_eof() may be not called: close the file here. */
969
913
  if (file >= 0)
970
914
  {
971
 
    (void) cache->end_io_cache();
 
915
    (void) end_io_cache(cache);
972
916
    (void) internal::my_close(file, MYF(0));
973
917
    file= -1;
974
918
  }
975
 
  path= "";
 
919
  path[0]= '\0';
976
920
  row_count= 0;
977
921
}
978
922
 
982
926
    cache(static_cast<internal::IO_CACHE *>(memory::sql_calloc(sizeof(internal::IO_CACHE)))),
983
927
    row_count(0L)
984
928
{
985
 
  path= "";
 
929
  path[0]=0;
986
930
}
987
931
 
988
932
select_to_file::~select_to_file()
1016
960
*/
1017
961
 
1018
962
 
1019
 
static int create_file(Session *session,
1020
 
                       fs::path &target_path,
1021
 
                       file_exchange *exchange,
1022
 
                       internal::IO_CACHE *cache)
 
963
static int create_file(Session *session, char *path, file_exchange *exchange, internal::IO_CACHE *cache)
1023
964
{
1024
 
  fs::path to_file(exchange->file_name);
1025
965
  int file;
1026
 
 
1027
 
  if (not to_file.has_root_directory())
 
966
  uint32_t option= MY_UNPACK_FILENAME | MY_RELATIVE_PATH;
 
967
 
 
968
#ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS
 
969
  option|= MY_REPLACE_DIR;                      // Force use of db directory
 
970
#endif
 
971
 
 
972
  if (!internal::dirname_length(exchange->file_name))
1028
973
  {
1029
 
    target_path= fs::system_complete(getDataHomeCatalog());
1030
 
    util::string::const_shared_ptr schema(session->schema());
1031
 
    if (schema and not schema->empty())
1032
 
    {
1033
 
      int count_elements= 0;
1034
 
      for (fs::path::iterator iter= to_file.begin();
1035
 
           iter != to_file.end();
1036
 
           ++iter, ++count_elements)
1037
 
      { }
1038
 
 
1039
 
      if (count_elements == 1)
1040
 
      {
1041
 
        target_path /= *schema;
1042
 
      }
1043
 
    }
1044
 
    target_path /= to_file;
 
974
    strcpy(path, data_home_real);
 
975
    if (! session->db.empty())
 
976
      strncat(path, session->db.c_str(), FN_REFLEN-strlen(data_home_real)-1);
 
977
    (void) internal::fn_format(path, exchange->file_name, path, "", option);
1045
978
  }
1046
979
  else
1047
 
  {
1048
 
    target_path = exchange->file_name;
1049
 
  }
1050
 
 
1051
 
  if (not secure_file_priv.string().empty())
1052
 
  {
1053
 
    if (target_path.file_string().substr(0, secure_file_priv.file_string().size()) != secure_file_priv.file_string())
1054
 
    {
1055
 
      /* Write only allowed to dir or subdir specified by secure_file_priv */
1056
 
      my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
1057
 
      return -1;
1058
 
    }
1059
 
  }
1060
 
 
1061
 
  if (!access(target_path.file_string().c_str(), F_OK))
 
980
    (void) internal::fn_format(path, exchange->file_name, data_home_real, "", option);
 
981
 
 
982
  if (opt_secure_file_priv &&
 
983
      strncmp(opt_secure_file_priv, path, strlen(opt_secure_file_priv)))
 
984
  {
 
985
    /* Write only allowed to dir or subdir specified by secure_file_priv */
 
986
    my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
 
987
    return -1;
 
988
  }
 
989
 
 
990
  if (!access(path, F_OK))
1062
991
  {
1063
992
    my_error(ER_FILE_EXISTS_ERROR, MYF(0), exchange->file_name);
1064
993
    return -1;
1065
994
  }
1066
995
  /* Create the file world readable */
1067
 
  if ((file= internal::my_create(target_path.file_string().c_str(), 0666, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0)
 
996
  if ((file= internal::my_create(path, 0666, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0)
1068
997
    return file;
1069
998
  (void) fchmod(file, 0666);                    // Because of umask()
1070
 
  if (cache->init_io_cache(file, 0L, internal::WRITE_CACHE, 0L, 1, MYF(MY_WME)))
 
999
  if (init_io_cache(cache, file, 0L, internal::WRITE_CACHE, 0L, 1, MYF(MY_WME)))
1071
1000
  {
1072
1001
    internal::my_close(file, MYF(0));
1073
 
    internal::my_delete(target_path.file_string().c_str(), MYF(0));  // Delete file on error, it was just created
 
1002
    internal::my_delete(path, MYF(0));  // Delete file on error, it was just created
1074
1003
    return -1;
1075
1004
  }
1076
1005
  return file;
1084
1013
  bool string_results= false, non_string_results= false;
1085
1014
  unit= u;
1086
1015
  if ((uint32_t) strlen(exchange->file_name) + NAME_LEN >= FN_REFLEN)
1087
 
  {
1088
 
    path= exchange->file_name;
1089
 
  }
 
1016
    strncpy(path,exchange->file_name,FN_REFLEN-1);
1090
1017
 
1091
1018
  /* Check if there is any blobs in data */
1092
1019
  {
1093
 
    List<Item>::iterator li(list.begin());
 
1020
    List_iterator_fast<Item> li(list);
1094
1021
    Item *item;
1095
1022
    while ((item=li++))
1096
1023
    {
1097
1024
      if (item->max_length >= MAX_BLOB_WIDTH)
1098
1025
      {
1099
 
        blob_flag=1;
1100
 
        break;
 
1026
        blob_flag=1;
 
1027
        break;
1101
1028
      }
1102
 
 
1103
1029
      if (item->result_type() == STRING_RESULT)
1104
1030
        string_results= true;
1105
1031
      else
1150
1076
  if (unit->offset_limit_cnt)
1151
1077
  {                                             // using limit offset,count
1152
1078
    unit->offset_limit_cnt--;
1153
 
    return false;
 
1079
    return(0);
1154
1080
  }
1155
1081
  row_count++;
1156
1082
  Item *item;
1157
1083
  uint32_t used_length=0,items_left=items.elements;
1158
 
  List<Item>::iterator li(items.begin());
 
1084
  List_iterator_fast<Item> li(items);
1159
1085
 
1160
1086
  if (my_b_write(cache,(unsigned char*) exchange->line_start->ptr(),
1161
1087
                 exchange->line_start->length()))
1162
 
    return true;
1163
 
 
 
1088
    goto err;
1164
1089
  while ((item=li++))
1165
1090
  {
1166
1091
    Item_result result_type=item->result_type();
1171
1096
    {
1172
1097
      if (my_b_write(cache,(unsigned char*) exchange->enclosed->ptr(),
1173
1098
                     exchange->enclosed->length()))
1174
 
        return true;
 
1099
        goto err;
1175
1100
    }
1176
1101
    if (!res)
1177
1102
    {                                           // NULL
1182
1107
          null_buff[0]=escape_char;
1183
1108
          null_buff[1]='N';
1184
1109
          if (my_b_write(cache,(unsigned char*) null_buff,2))
1185
 
            return true;
 
1110
            goto err;
1186
1111
        }
1187
1112
        else if (my_b_write(cache,(unsigned char*) "NULL",4))
1188
 
          return true;
 
1113
          goto err;
1189
1114
      }
1190
1115
      else
1191
1116
      {
1195
1120
    else
1196
1121
    {
1197
1122
      if (fixed_row_size)
1198
 
        used_length= min(res->length(), static_cast<size_t>(item->max_length));
 
1123
        used_length= min(res->length(),item->max_length);
1199
1124
      else
1200
1125
        used_length= res->length();
1201
1126
 
1276
1201
            tmp_buff[1]= *pos ? *pos : '0';
1277
1202
            if (my_b_write(cache,(unsigned char*) start,(uint32_t) (pos-start)) ||
1278
1203
                my_b_write(cache,(unsigned char*) tmp_buff,2))
1279
 
              return true;
 
1204
              goto err;
1280
1205
            start=pos+1;
1281
1206
          }
1282
1207
        }
1283
1208
        if (my_b_write(cache,(unsigned char*) start,(uint32_t) (pos-start)))
1284
 
          return true;
 
1209
          goto err;
1285
1210
      }
1286
1211
      else if (my_b_write(cache,(unsigned char*) res->ptr(),used_length))
1287
 
        return true;
 
1212
        goto err;
1288
1213
    }
1289
1214
    if (fixed_row_size)
1290
1215
    {                                           // Fill with space
1300
1225
        for (; length > sizeof(space) ; length-=sizeof(space))
1301
1226
        {
1302
1227
          if (my_b_write(cache,(unsigned char*) space,sizeof(space)))
1303
 
            return true;
 
1228
            goto err;
1304
1229
        }
1305
1230
        if (my_b_write(cache,(unsigned char*) space,length))
1306
 
          return true;
 
1231
          goto err;
1307
1232
      }
1308
1233
    }
1309
1234
    if (res && enclosed)
1310
1235
    {
1311
1236
      if (my_b_write(cache, (unsigned char*) exchange->enclosed->ptr(),
1312
1237
                     exchange->enclosed->length()))
1313
 
        return true;
 
1238
        goto err;
1314
1239
    }
1315
1240
    if (--items_left)
1316
1241
    {
1317
1242
      if (my_b_write(cache, (unsigned char*) exchange->field_term->ptr(),
1318
1243
                     field_term_length))
1319
 
        return true;
 
1244
        goto err;
1320
1245
    }
1321
1246
  }
1322
1247
  if (my_b_write(cache,(unsigned char*) exchange->line_term->ptr(),
1323
1248
                 exchange->line_term->length()))
1324
 
  {
1325
 
    return true;
1326
 
  }
1327
 
 
1328
 
  return false;
 
1249
    goto err;
 
1250
  return(0);
 
1251
err:
 
1252
  return(1);
1329
1253
}
1330
1254
 
1331
1255
 
1344
1268
 
1345
1269
bool select_dump::send_data(List<Item> &items)
1346
1270
{
1347
 
  List<Item>::iterator li(items.begin());
 
1271
  List_iterator_fast<Item> li(items);
1348
1272
  char buff[MAX_FIELD_WIDTH];
1349
1273
  String tmp(buff,sizeof(buff),&my_charset_bin),*res;
1350
1274
  tmp.length(0);
1358
1282
  if (row_count++ > 1)
1359
1283
  {
1360
1284
    my_message(ER_TOO_MANY_ROWS, ER(ER_TOO_MANY_ROWS), MYF(0));
1361
 
    return 1;
 
1285
    goto err;
1362
1286
  }
1363
1287
  while ((item=li++))
1364
1288
  {
1366
1290
    if (!res)                                   // If NULL
1367
1291
    {
1368
1292
      if (my_b_write(cache,(unsigned char*) "",1))
1369
 
        return 1;
 
1293
        goto err;
1370
1294
    }
1371
1295
    else if (my_b_write(cache,(unsigned char*) res->ptr(),res->length()))
1372
1296
    {
1373
 
      my_error(ER_ERROR_ON_WRITE, MYF(0), path.file_string().c_str(), errno);
1374
 
      return 1;
 
1297
      my_error(ER_ERROR_ON_WRITE, MYF(0), path, errno);
 
1298
      goto err;
1375
1299
    }
1376
1300
  }
1377
1301
  return(0);
 
1302
err:
 
1303
  return(1);
1378
1304
}
1379
1305
 
1380
1306
 
1397
1323
    unit->offset_limit_cnt--;
1398
1324
    return(0);
1399
1325
  }
1400
 
  List<Item>::iterator li(items.begin());
 
1326
  List_iterator_fast<Item> li(items);
1401
1327
  Item *val_item;
1402
1328
  for (uint32_t i= 0; (val_item= li++); i++)
1403
1329
    it->store(i, val_item);
1415
1341
bool select_max_min_finder_subselect::send_data(List<Item> &items)
1416
1342
{
1417
1343
  Item_maxmin_subselect *it= (Item_maxmin_subselect *)item;
1418
 
  List<Item>::iterator li(items.begin());
 
1344
  List_iterator_fast<Item> li(items);
1419
1345
  Item *val_item= li++;
1420
1346
  it->register_value();
1421
1347
  if (it->assigned())
1432
1358
      switch (val_item->result_type())
1433
1359
      {
1434
1360
      case REAL_RESULT:
1435
 
        op= &select_max_min_finder_subselect::cmp_real;
1436
 
        break;
 
1361
        op= &select_max_min_finder_subselect::cmp_real;
 
1362
        break;
1437
1363
      case INT_RESULT:
1438
 
        op= &select_max_min_finder_subselect::cmp_int;
1439
 
        break;
 
1364
        op= &select_max_min_finder_subselect::cmp_int;
 
1365
        break;
1440
1366
      case STRING_RESULT:
1441
 
        op= &select_max_min_finder_subselect::cmp_str;
1442
 
        break;
 
1367
        op= &select_max_min_finder_subselect::cmp_str;
 
1368
        break;
1443
1369
      case DECIMAL_RESULT:
1444
1370
        op= &select_max_min_finder_subselect::cmp_decimal;
1445
1371
        break;
1446
1372
      case ROW_RESULT:
1447
1373
        // This case should never be choosen
1448
 
        assert(0);
1449
 
        op= 0;
 
1374
        assert(0);
 
1375
        op= 0;
1450
1376
      }
1451
1377
    }
1452
1378
    cache->store(val_item);
1485
1411
bool select_max_min_finder_subselect::cmp_decimal()
1486
1412
{
1487
1413
  Item *maxmin= ((Item_singlerow_subselect *)item)->element_index(0);
1488
 
  type::Decimal cval, *cvalue= cache->val_decimal(&cval);
1489
 
  type::Decimal mval, *mvalue= maxmin->val_decimal(&mval);
 
1414
  my_decimal cval, *cvalue= cache->val_decimal(&cval);
 
1415
  my_decimal mval, *mvalue= maxmin->val_decimal(&mval);
1490
1416
  if (fmax)
1491
1417
    return (cache->null_value && !maxmin->null_value) ||
1492
1418
      (!cache->null_value && !maxmin->null_value &&
1493
 
       class_decimal_cmp(cvalue, mvalue) > 0) ;
 
1419
       my_decimal_cmp(cvalue, mvalue) > 0) ;
1494
1420
  return (maxmin->null_value && !cache->null_value) ||
1495
1421
    (!cache->null_value && !maxmin->null_value &&
1496
 
     class_decimal_cmp(cvalue,mvalue) < 0);
 
1422
     my_decimal_cmp(cvalue,mvalue) < 0);
1497
1423
}
1498
1424
 
1499
1425
bool select_max_min_finder_subselect::cmp_str()
1535
1461
void Session::end_statement()
1536
1462
{
1537
1463
  /* Cleanup SQL processing state to reuse this statement in next query. */
1538
 
  lex->end();
1539
 
  query_cache_key= ""; // reset the cache key
1540
 
  resetResultsetMessage();
 
1464
  lex_end(lex);
1541
1465
}
1542
1466
 
1543
1467
bool Session::copy_db_to(char **p_db, size_t *p_db_length)
1544
1468
{
1545
 
  assert(_schema);
1546
 
  if (_schema and _schema->empty())
1547
 
  {
1548
 
    my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
1549
 
    return true;
1550
 
  }
1551
 
  else if (not _schema)
1552
 
  {
1553
 
    my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
1554
 
    return true;
1555
 
  }
1556
 
  assert(_schema);
1557
 
 
1558
 
  *p_db= strmake(_schema->c_str(), _schema->size());
1559
 
  *p_db_length= _schema->size();
1560
 
 
 
1469
  if (db.empty())
 
1470
  {
 
1471
    my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
 
1472
    return true;
 
1473
  }
 
1474
  *p_db= strmake(db.c_str(), db.length());
 
1475
  *p_db_length= db.length();
1561
1476
  return false;
1562
1477
}
1563
1478
 
1579
1494
  /* Fix for Intel compiler */
1580
1495
  if (copy_field)
1581
1496
  {
1582
 
    boost::checked_array_delete(copy_field);
1583
 
    save_copy_field= save_copy_field_end= copy_field= copy_field_end= 0;
 
1497
    delete [] copy_field;
 
1498
    save_copy_field= copy_field= 0;
1584
1499
  }
1585
1500
}
1586
1501
 
1587
1502
void Session::send_kill_message() const
1588
1503
{
1589
 
  drizzled::error_t err= static_cast<drizzled::error_t>(killed_errno());
1590
 
  if (err != EE_OK)
 
1504
  int err= killed_errno();
 
1505
  if (err)
1591
1506
    my_message(err, ER(err), MYF(0));
1592
1507
}
1593
1508
 
1597
1512
}
1598
1513
 
1599
1514
 
1600
 
void Session::set_db(const std::string &new_db)
 
1515
bool Session::set_db(const std::string &new_db)
1601
1516
{
1602
1517
  /* Do not reallocate memory if current chunk is big enough. */
1603
1518
  if (new_db.length())
1604
 
  {
1605
 
    _schema.reset(new std::string(new_db));
1606
 
  }
 
1519
    db= new_db;
1607
1520
  else
1608
 
  {
1609
 
    _schema.reset(new std::string(""));
1610
 
  }
1611
 
}
1612
 
 
 
1521
    db.clear();
 
1522
 
 
1523
  return false;
 
1524
}
 
1525
 
 
1526
 
 
1527
 
 
1528
 
 
1529
/**
 
1530
  Check the killed state of a user thread
 
1531
  @param session  user thread
 
1532
  @retval 0 the user thread is active
 
1533
  @retval 1 the user thread has been killed
 
1534
*/
 
1535
int session_killed(const Session *session)
 
1536
{
 
1537
  return(session->killed);
 
1538
}
 
1539
 
 
1540
 
 
1541
const struct charset_info_st *session_charset(Session *session)
 
1542
{
 
1543
  return(session->charset());
 
1544
}
1613
1545
 
1614
1546
/**
1615
1547
  Mark transaction to rollback and mark error as fatal to a sub-statement.
1617
1549
  @param  session   Thread handle
1618
1550
  @param  all   true <=> rollback main transaction.
1619
1551
*/
1620
 
void Session::markTransactionForRollback(bool all)
 
1552
void mark_transaction_to_rollback(Session *session, bool all)
1621
1553
{
1622
 
  is_fatal_sub_stmt_error= true;
1623
 
  transaction_rollback_request= all;
 
1554
  if (session)
 
1555
  {
 
1556
    session->is_fatal_sub_stmt_error= true;
 
1557
    session->transaction_rollback_request= all;
 
1558
  }
1624
1559
}
1625
1560
 
1626
 
void Session::disconnect(enum error_t errcode)
 
1561
void Session::disconnect(uint32_t errcode, bool should_lock)
1627
1562
{
1628
1563
  /* Allow any plugins to cleanup their session variables */
1629
1564
  plugin_sessionvar_cleanup(this);
1630
1565
 
1631
1566
  /* If necessary, log any aborted or unauthorized connections */
1632
 
  if (getKilled() || client->wasAborted())
 
1567
  if (killed || client->wasAborted())
1633
1568
  {
1634
 
    status_var.aborted_threads++;
 
1569
    status_var_increment(current_global_counters.aborted_threads);
1635
1570
  }
1636
1571
 
1637
1572
  if (client->wasAborted())
1638
1573
  {
1639
 
    if (not getKilled() && variables.log_warnings > 1)
 
1574
    if (! killed && variables.log_warnings > 1)
1640
1575
    {
1641
 
      errmsg_printf(error::WARN, ER(ER_NEW_ABORTING_CONNECTION)
 
1576
      SecurityContext *sctx= &security_ctx;
 
1577
 
 
1578
      errmsg_printf(ERRMSG_LVL_WARN, ER(ER_NEW_ABORTING_CONNECTION)
1642
1579
                  , thread_id
1643
 
                  , (_schema->empty() ? "unconnected" : _schema->c_str())
1644
 
                  , security_ctx->username().empty() == false ? security_ctx->username().c_str() : "unauthenticated"
1645
 
                  , security_ctx->address().c_str()
 
1580
                  , (db.empty() ? "unconnected" : db.c_str())
 
1581
                  , sctx->getUser().empty() == false ? sctx->getUser().c_str() : "unauthenticated"
 
1582
                  , sctx->getIp().c_str()
1646
1583
                  , (main_da.is_error() ? main_da.message() : ER(ER_UNKNOWN_ERROR)));
1647
1584
    }
1648
1585
  }
1649
1586
 
1650
 
  setKilled(Session::KILL_CONNECTION);
1651
 
 
 
1587
  /* Close out our connection to the client */
 
1588
  if (should_lock)
 
1589
    (void) pthread_mutex_lock(&LOCK_thread_count);
 
1590
  killed= Session::KILL_CONNECTION;
1652
1591
  if (client->isConnected())
1653
1592
  {
1654
 
    if (errcode != EE_OK)
 
1593
    if (errcode)
1655
1594
    {
1656
1595
      /*my_error(errcode, ER(errcode));*/
1657
1596
      client->sendError(errcode, ER(errcode));
1658
1597
    }
1659
1598
    client->close();
1660
1599
  }
 
1600
  if (should_lock)
 
1601
    (void) pthread_mutex_unlock(&LOCK_thread_count);
1661
1602
}
1662
1603
 
1663
1604
void Session::reset_for_next_command()
1685
1626
  Close all temporary tables created by 'CREATE TEMPORARY TABLE' for thread
1686
1627
*/
1687
1628
 
1688
 
void Open_tables_state::close_temporary_tables()
 
1629
void Session::close_temporary_tables()
1689
1630
{
1690
1631
  Table *table;
1691
1632
  Table *tmp_next;
1705
1646
  unlink from session->temporary tables and close temporary table
1706
1647
*/
1707
1648
 
1708
 
void Open_tables_state::close_temporary_table(Table *table)
 
1649
void Session::close_temporary_table(Table *table)
1709
1650
{
1710
1651
  if (table->getPrev())
1711
1652
  {
1741
1682
  If this is needed, use close_temporary_table()
1742
1683
*/
1743
1684
 
1744
 
void Open_tables_state::nukeTable(Table *table)
 
1685
void Session::nukeTable(Table *table)
1745
1686
{
1746
1687
  plugin::StorageEngine *table_type= table->getShare()->db_type();
1747
1688
 
1748
1689
  table->free_io_cache();
1749
 
  table->delete_table();
 
1690
  table->delete_table(false);
1750
1691
 
1751
 
  identifier::Table identifier(table->getShare()->getSchemaName(), table->getShare()->getTableName(), table->getShare()->getPath());
 
1692
  TableIdentifier identifier(table->getShare()->getSchemaName(), table->getShare()->getTableName(), table->getShare()->getPath());
1752
1693
  rm_temporary_table(table_type, identifier);
1753
1694
 
1754
 
  boost::checked_delete(table->getMutableShare());
 
1695
  delete table->getMutableShare();
1755
1696
 
1756
 
  boost::checked_delete(table);
 
1697
  /* This makes me sad, but we're allocating it via malloc */
 
1698
  free(table);
1757
1699
}
1758
1700
 
1759
1701
/** Clear most status variables. */
1761
1703
 
1762
1704
void Session::refresh_status()
1763
1705
{
 
1706
  pthread_mutex_lock(&LOCK_status);
 
1707
 
1764
1708
  /* Reset thread's status variables */
1765
1709
  memset(&status_var, 0, sizeof(status_var));
1766
1710
 
 
1711
  /* Reset the counters of all key caches (default and named). */
 
1712
  reset_key_cache_counters();
1767
1713
  flush_status_time= time((time_t*) 0);
1768
1714
  current_global_counters.max_used_connections= 1; /* We set it to one, because we know we exist */
1769
 
  current_global_counters.connections= 0;
 
1715
  pthread_mutex_unlock(&LOCK_status);
1770
1716
}
1771
1717
 
1772
1718
user_var_entry *Session::getVariable(LEX_STRING &name, bool create_if_not_exists)
1773
1719
{
1774
 
  return getVariable(std::string(name.str, name.length), create_if_not_exists);
1775
 
}
1776
 
 
1777
 
user_var_entry *Session::getVariable(const std::string  &name, bool create_if_not_exists)
1778
 
{
1779
 
  if (cleanup_done)
1780
 
    return NULL;
1781
 
 
1782
 
  UserVars::iterator iter= user_vars.find(name);
1783
 
  if (iter != user_vars.end())
1784
 
    return (*iter).second;
1785
 
 
1786
 
  if (not create_if_not_exists)
1787
 
    return NULL;
1788
 
 
1789
1720
  user_var_entry *entry= NULL;
1790
 
  entry= new (nothrow) user_var_entry(name.c_str(), query_id);
1791
 
 
1792
 
  if (entry == NULL)
1793
 
    return NULL;
1794
 
 
1795
 
  std::pair<UserVars::iterator, bool> returnable= user_vars.insert(make_pair(name, entry));
1796
 
 
1797
 
  if (not returnable.second)
 
1721
 
 
1722
  entry= (user_var_entry*) hash_search(&user_vars, (unsigned char*) name.str, name.length);
 
1723
 
 
1724
  if ((entry == NULL) && create_if_not_exists)
1798
1725
  {
1799
 
    boost::checked_delete(entry);
 
1726
    if (!hash_inited(&user_vars))
 
1727
      return NULL;
 
1728
    entry= new (nothrow) user_var_entry(name.str, query_id);
 
1729
 
 
1730
    if (entry == NULL)
 
1731
      return NULL;
 
1732
 
 
1733
    if (my_hash_insert(&user_vars, (unsigned char*) entry))
 
1734
    {
 
1735
      assert(1);
 
1736
      delete entry;
 
1737
      return 0;
 
1738
    }
 
1739
 
1800
1740
  }
1801
1741
 
1802
1742
  return entry;
1803
1743
}
1804
1744
 
1805
 
void Session::setVariable(const std::string &name, const std::string &value)
1806
 
{
1807
 
  user_var_entry *updateable_var= getVariable(name.c_str(), true);
1808
 
  if (updateable_var)
1809
 
  {
1810
 
    updateable_var->update_hash(false,
1811
 
                                (void*)value.c_str(),
1812
 
                                static_cast<uint32_t>(value.length()), STRING_RESULT,
1813
 
                                &my_charset_bin,
1814
 
                                DERIVATION_IMPLICIT, false);
1815
 
  }
1816
 
}
1817
 
 
1818
 
void Open_tables_state::mark_temp_tables_as_free_for_reuse()
 
1745
void Session::mark_temp_tables_as_free_for_reuse()
1819
1746
{
1820
1747
  for (Table *table= temporary_tables ; table ; table= table->getNext())
1821
1748
  {
1822
 
    if (table->query_id == getQueryId())
 
1749
    if (table->query_id == query_id)
1823
1750
    {
1824
1751
      table->query_id= 0;
1825
1752
      table->cursor->ha_reset();
1831
1758
{
1832
1759
  for (; table ; table= table->getNext())
1833
1760
  {
1834
 
    if (table->query_id == getQueryId())
 
1761
    if (table->query_id == query_id)
1835
1762
    {
1836
1763
      table->query_id= 0;
1837
1764
      table->cursor->ha_reset();
1850
1777
*/
1851
1778
void Session::close_thread_tables()
1852
1779
{
1853
 
  clearDerivedTables();
 
1780
  if (derived_tables)
 
1781
    derived_tables= NULL; // They should all be invalid by this point
1854
1782
 
1855
1783
  /*
1856
1784
    Mark all temporary tables used by this statement as free for reuse.
1867
1795
  {
1868
1796
    TransactionServices &transaction_services= TransactionServices::singleton();
1869
1797
    main_da.can_overwrite_status= true;
1870
 
    transaction_services.autocommitOrRollback(*this, is_error());
 
1798
    transaction_services.autocommitOrRollback(this, is_error());
1871
1799
    main_da.can_overwrite_status= false;
1872
1800
    transaction.stmt.reset();
1873
1801
  }
1883
1811
      handled either before writing a query log event (inside
1884
1812
      binlog_query()) or when preparing a pending event.
1885
1813
     */
1886
 
    unlockTables(lock);
 
1814
    mysql_unlock_tables(this, lock);
1887
1815
    lock= 0;
1888
1816
  }
1889
1817
  /*
1890
 
    Note that we need to hold table::Cache::singleton().mutex() while changing the
 
1818
    Note that we need to hold LOCK_open while changing the
1891
1819
    open_tables list. Another thread may work on it.
1892
 
    (See: table::Cache::singleton().removeTable(), wait_completed_table())
 
1820
    (See: remove_table_from_cache(), mysql_wait_completed_table())
1893
1821
    Closing a MERGE child before the parent would be fatal if the
1894
1822
    other thread tries to abort the MERGE lock in between.
1895
1823
  */
1923
1851
 
1924
1852
    if (not lock_tables(tables, counter, &need_reopen))
1925
1853
      break;
1926
 
 
1927
1854
    if (not need_reopen)
1928
1855
      return true;
1929
 
 
1930
1856
    close_tables_for_reopen(&tables);
1931
1857
  }
1932
 
 
1933
 
  if ((handle_derived(lex, &derived_prepare) || (handle_derived(lex, &derived_filling))))
1934
 
    return true;
1935
 
 
 
1858
  if ((mysql_handle_derived(lex, &mysql_derived_prepare) ||
 
1859
       (fill_derived_tables() &&
 
1860
        mysql_handle_derived(lex, &mysql_derived_filling))))
 
1861
    return true;
 
1862
 
 
1863
  return false;
 
1864
}
 
1865
 
 
1866
bool Session::openTables(TableList *tables, uint32_t flags)
 
1867
{
 
1868
  uint32_t counter;
 
1869
  bool ret= fill_derived_tables();
 
1870
  assert(ret == false);
 
1871
  if (open_tables_from_list(&tables, &counter, flags) ||
 
1872
      mysql_handle_derived(lex, &mysql_derived_prepare))
 
1873
  {
 
1874
    return true;
 
1875
  }
1936
1876
  return false;
1937
1877
}
1938
1878
 
1942
1882
  might be an issue (lame engines).
1943
1883
*/
1944
1884
 
1945
 
bool Open_tables_state::rm_temporary_table(const identifier::Table &identifier, bool best_effort)
 
1885
bool Session::rm_temporary_table(TableIdentifier &identifier, bool best_effort)
1946
1886
{
1947
 
  if (not plugin::StorageEngine::dropTable(*static_cast<Session *>(this), identifier))
 
1887
  if (plugin::StorageEngine::dropTable(*this, identifier))
1948
1888
  {
1949
1889
    if (not best_effort)
1950
1890
    {
1951
 
      std::string path;
1952
 
      identifier.getSQLPath(path);
1953
 
      errmsg_printf(error::WARN, _("Could not remove temporary table: '%s', error: %d"),
1954
 
                    path.c_str(), errno);
 
1891
      errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
 
1892
                    identifier.getSQLPath().c_str(), errno);
1955
1893
    }
1956
1894
 
1957
1895
    return true;
1960
1898
  return false;
1961
1899
}
1962
1900
 
1963
 
bool Open_tables_state::rm_temporary_table(plugin::StorageEngine *base, const identifier::Table &identifier)
 
1901
bool Session::rm_temporary_table(plugin::StorageEngine *base, TableIdentifier &identifier)
1964
1902
{
1965
 
  drizzled::error_t error;
1966
1903
  assert(base);
1967
1904
 
1968
 
  if (not plugin::StorageEngine::dropTable(*static_cast<Session *>(this), *base, identifier, error))
 
1905
  if (plugin::StorageEngine::dropTable(*this, *base, identifier))
1969
1906
  {
1970
 
    std::string path;
1971
 
    identifier.getSQLPath(path);
1972
 
    errmsg_printf(error::WARN, _("Could not remove temporary table: '%s', error: %d"),
1973
 
                  path.c_str(), error);
 
1907
    errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
 
1908
                  identifier.getSQLPath().c_str(), errno);
1974
1909
 
1975
1910
    return true;
1976
1911
  }
1982
1917
  @note this will be removed, I am looking through Hudson to see if it is finding
1983
1918
  any tables that are missed during cleanup.
1984
1919
*/
1985
 
void Open_tables_state::dumpTemporaryTableNames(const char *foo)
 
1920
void Session::dumpTemporaryTableNames(const char *foo)
1986
1921
{
1987
1922
  Table *table;
1988
1923
 
1994
1929
  {
1995
1930
    bool have_proto= false;
1996
1931
 
1997
 
    message::Table *proto= table->getShare()->getTableMessage();
1998
 
    if (table->getShare()->getTableMessage())
 
1932
    message::Table *proto= table->getShare()->getTableProto();
 
1933
    if (table->getShare()->getTableProto())
1999
1934
      have_proto= true;
2000
1935
 
2001
1936
    const char *answer= have_proto ? "true" : "false";
2006
1941
      cerr << "\t\t Proto " << proto->schema() << " " << proto->name() << "\n";
2007
1942
    }
2008
1943
    else
2009
 
    {
2010
1944
      cerr << "\tTabl;e Name " << table->getShare()->getSchemaName() << "." << table->getShare()->getTableName() << " : " << answer << "\n";
2011
 
    }
2012
 
  }
2013
 
}
2014
 
 
2015
 
table::Singular *Session::getInstanceTable()
2016
 
{
2017
 
  temporary_shares.push_back(new table::Singular()); // This will not go into the tableshare cache, so no key is used.
2018
 
 
2019
 
  table::Singular *tmp_share= temporary_shares.back();
2020
 
 
2021
 
  assert(tmp_share);
2022
 
 
2023
 
  return tmp_share;
2024
 
}
2025
 
 
2026
 
 
2027
 
/**
2028
 
  Create a reduced Table object with properly set up Field list from a
2029
 
  list of field definitions.
2030
 
 
2031
 
    The created table doesn't have a table Cursor associated with
2032
 
    it, has no keys, no group/distinct, no copy_funcs array.
2033
 
    The sole purpose of this Table object is to use the power of Field
2034
 
    class to read/write data to/from table->getInsertRecord(). Then one can store
2035
 
    the record in any container (RB tree, hash, etc).
2036
 
    The table is created in Session mem_root, so are the table's fields.
2037
 
    Consequently, if you don't BLOB fields, you don't need to free it.
2038
 
 
2039
 
  @param session         connection handle
2040
 
  @param field_list  list of column definitions
2041
 
 
2042
 
  @return
2043
 
    0 if out of memory, Table object in case of success
2044
 
*/
2045
 
table::Singular *Session::getInstanceTable(List<CreateField> &field_list)
2046
 
{
2047
 
  temporary_shares.push_back(new table::Singular(this, field_list)); // This will not go into the tableshare cache, so no key is used.
2048
 
 
2049
 
  table::Singular *tmp_share= temporary_shares.back();
2050
 
 
2051
 
  assert(tmp_share);
2052
 
 
2053
 
  return tmp_share;
2054
 
}
2055
 
 
2056
 
namespace display  {
2057
 
 
2058
 
static const std::string NONE= "NONE";
2059
 
static const std::string GOT_GLOBAL_READ_LOCK= "HAS GLOBAL READ LOCK";
2060
 
static const std::string MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT= "HAS GLOBAL READ LOCK WITH BLOCKING COMMIT";
2061
 
 
2062
 
const std::string &type(drizzled::Session::global_read_lock_t type)
2063
 
{
2064
 
  switch (type) {
2065
 
    default:
2066
 
    case Session::NONE:
2067
 
      return NONE;
2068
 
    case Session::GOT_GLOBAL_READ_LOCK:
2069
 
      return GOT_GLOBAL_READ_LOCK;
2070
 
    case Session::MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT:
2071
 
      return MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT;
2072
 
  }
2073
 
}
2074
 
 
2075
 
size_t max_string_length(drizzled::Session::global_read_lock_t)
2076
 
{
2077
 
  return MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT.size();
2078
 
}
2079
 
 
2080
 
} /* namespace display */
 
1945
  }
 
1946
}
 
1947
 
 
1948
bool Session::storeTableMessage(TableIdentifier &identifier, message::Table &table_message)
 
1949
{
 
1950
  table_message_cache.insert(make_pair(identifier.getPath(), table_message));
 
1951
 
 
1952
  return true;
 
1953
}
 
1954
 
 
1955
bool Session::removeTableMessage(TableIdentifier &identifier)
 
1956
{
 
1957
  TableMessageCache::iterator iter;
 
1958
 
 
1959
  iter= table_message_cache.find(identifier.getPath());
 
1960
 
 
1961
  if (iter == table_message_cache.end())
 
1962
    return false;
 
1963
 
 
1964
  table_message_cache.erase(iter);
 
1965
 
 
1966
  return true;
 
1967
}
 
1968
 
 
1969
bool Session::getTableMessage(TableIdentifier &identifier, message::Table &table_message)
 
1970
{
 
1971
  TableMessageCache::iterator iter;
 
1972
 
 
1973
  iter= table_message_cache.find(identifier.getPath());
 
1974
 
 
1975
  if (iter == table_message_cache.end())
 
1976
    return false;
 
1977
 
 
1978
  table_message.CopyFrom(((*iter).second));
 
1979
 
 
1980
  return true;
 
1981
}
 
1982
 
 
1983
bool Session::doesTableMessageExist(TableIdentifier &identifier)
 
1984
{
 
1985
  TableMessageCache::iterator iter;
 
1986
 
 
1987
  iter= table_message_cache.find(identifier.getPath());
 
1988
 
 
1989
  if (iter == table_message_cache.end())
 
1990
  {
 
1991
    return false;
 
1992
  }
 
1993
 
 
1994
  return true;
 
1995
}
 
1996
 
 
1997
bool Session::renameTableMessage(TableIdentifier &from, TableIdentifier &to)
 
1998
{
 
1999
  TableMessageCache::iterator iter;
 
2000
 
 
2001
  table_message_cache[to.getPath()]= table_message_cache[from.getPath()];
 
2002
 
 
2003
  iter= table_message_cache.find(to.getPath());
 
2004
 
 
2005
  if (iter == table_message_cache.end())
 
2006
  {
 
2007
    return false;
 
2008
  }
 
2009
 
 
2010
  (*iter).second.set_schema(to.getSchemaName());
 
2011
  (*iter).second.set_name(to.getTableName());
 
2012
 
 
2013
  return true;
 
2014
}
 
2015
 
 
2016
TableShareInstance *Session::getTemporaryShare(TableIdentifier::Type type_arg)
 
2017
{
 
2018
  temporary_shares.push_back(new TableShareInstance(type_arg)); // This will not go into the tableshare cache, so no key is used.
 
2019
 
 
2020
  TableShareInstance *tmp_share= temporary_shares.back();
 
2021
 
 
2022
  assert(tmp_share);
 
2023
 
 
2024
  return tmp_share;
 
2025
}
2081
2026
 
2082
2027
} /* namespace drizzled */