~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/session.cc

  • Committer: Andrew Hutchings
  • Date: 2011-01-21 11:23:19 UTC
  • mto: (2100.1.1 build)
  • mto: This revision was merged to the branch mainline in revision 2101.
  • Revision ID: andrew@linuxjedi.co.uk-20110121112319-nj1cvg0yt3nnf2rr
Add errors page to drizzle client docs
Add link to specific error in migration docs
Minor changes to migration docs

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
 
4
 *  Copyright (C) 2008 Sun Microsystems, Inc.
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
22
22
 */
23
23
 
24
24
#include "config.h"
25
 
#include <drizzled/session.h>
26
 
#include "drizzled/session_list.h"
 
25
#include "drizzled/session.h"
 
26
#include "drizzled/session/cache.h"
27
27
#include <sys/stat.h>
28
 
#include <drizzled/error.h>
29
 
#include <drizzled/gettext.h>
30
 
#include <drizzled/query_id.h>
31
 
#include <drizzled/data_home.h>
32
 
#include <drizzled/sql_base.h>
33
 
#include <drizzled/lock.h>
34
 
#include <drizzled/item/cache.h>
35
 
#include <drizzled/item/float.h>
36
 
#include <drizzled/item/return_int.h>
37
 
#include <drizzled/item/empty_string.h>
38
 
#include <drizzled/show.h>
39
 
#include <drizzled/plugin/client.h>
 
28
#include "drizzled/error.h"
 
29
#include "drizzled/gettext.h"
 
30
#include "drizzled/query_id.h"
 
31
#include "drizzled/data_home.h"
 
32
#include "drizzled/sql_base.h"
 
33
#include "drizzled/lock.h"
 
34
#include "drizzled/item/cache.h"
 
35
#include "drizzled/item/float.h"
 
36
#include "drizzled/item/return_int.h"
 
37
#include "drizzled/item/empty_string.h"
 
38
#include "drizzled/show.h"
 
39
#include "drizzled/plugin/client.h"
40
40
#include "drizzled/plugin/scheduler.h"
41
41
#include "drizzled/plugin/authentication.h"
42
42
#include "drizzled/plugin/logging.h"
43
43
#include "drizzled/plugin/transactional_storage_engine.h"
 
44
#include "drizzled/plugin/query_rewrite.h"
44
45
#include "drizzled/probes.h"
45
46
#include "drizzled/table_proto.h"
46
47
#include "drizzled/db.h"
47
48
#include "drizzled/pthread_globals.h"
48
49
#include "drizzled/transaction_services.h"
 
50
#include "drizzled/drizzled.h"
 
51
 
 
52
#include "drizzled/identifier.h"
 
53
 
 
54
#include "drizzled/table/singular.h"
49
55
 
50
56
#include "plugin/myisam/myisam.h"
51
57
#include "drizzled/internal/iocache.h"
 
58
#include "drizzled/internal/thread_var.h"
 
59
#include "drizzled/plugin/event_observer.h"
 
60
 
 
61
#include "drizzled/util/functors.h"
 
62
 
 
63
#include "drizzled/display.h"
52
64
 
53
65
#include <fcntl.h>
54
66
#include <algorithm>
55
67
#include <climits>
56
68
 
 
69
#include <boost/filesystem.hpp>
 
70
#include <boost/checked_delete.hpp>
 
71
 
 
72
#include "drizzled/util/backtrace.h"
 
73
 
57
74
using namespace std;
 
75
 
 
76
namespace fs=boost::filesystem;
58
77
namespace drizzled
59
78
{
60
79
 
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
80
/*
68
81
  The following is used to initialise Table_ident with a internal
69
82
  table name
72
85
char empty_c_string[1]= {0};    /* used for not defined db */
73
86
 
74
87
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
88
 
95
89
bool Key_part_spec::operator==(const Key_part_spec& other) const
96
90
{
97
91
  return length == other.length &&
98
92
         field_name.length == other.field_name.length &&
99
 
         !strcmp(field_name.str, other.field_name.str);
 
93
    !my_strcasecmp(system_charset_info, field_name.str, other.field_name.str);
100
94
}
101
95
 
102
 
Open_tables_state::Open_tables_state(uint64_t version_arg)
103
 
  :version(version_arg), backups_available(false)
 
96
Open_tables_state::Open_tables_state(uint64_t version_arg) :
 
97
  version(version_arg)
104
98
{
105
 
  reset_open_tables_state();
 
99
  open_tables= temporary_tables= derived_tables= NULL;
 
100
  extra_lock= lock= NULL;
106
101
}
107
102
 
108
103
/*
109
104
  The following functions form part of the C plugin API
110
105
*/
111
 
extern "C" int mysql_tmpfile(const char *prefix)
 
106
int tmpfile(const char *prefix)
112
107
{
113
108
  char filename[FN_REFLEN];
114
 
  int fd = internal::create_temp_file(filename, drizzle_tmpdir, prefix, MYF(MY_WME));
 
109
  int fd = internal::create_temp_file(filename, drizzle_tmpdir.c_str(), prefix, MYF(MY_WME));
115
110
  if (fd >= 0) {
116
111
    unlink(filename);
117
112
  }
119
114
  return fd;
120
115
}
121
116
 
122
 
extern "C"
123
117
int session_tablespace_op(const Session *session)
124
118
{
125
119
  return test(session->tablespace_op);
133
127
 
134
128
   @see Session::set_proc_info
135
129
 */
136
 
extern "C" void
137
 
set_session_proc_info(Session *session, const char *info)
 
130
void set_session_proc_info(Session *session, const char *info)
138
131
{
139
132
  session->set_proc_info(info);
140
133
}
141
134
 
142
 
extern "C"
143
135
const char *get_session_proc_info(Session *session)
144
136
{
145
137
  return session->get_proc_info();
156
148
  return &ha_data[monitored->getId()].resource_context[index];
157
149
}
158
150
 
159
 
extern "C"
160
151
int64_t session_test_options(const Session *session, int64_t test_options)
161
152
{
162
153
  return session->options & test_options;
163
154
}
164
155
 
165
 
extern "C"
166
156
int session_sql_command(const Session *session)
167
157
{
168
158
  return (int) session->lex->sql_command;
169
159
}
170
160
 
171
 
extern "C"
172
 
int session_tx_isolation(const Session *session)
 
161
enum_tx_isolation session_tx_isolation(const Session *session)
173
162
{
174
 
  return (int) session->variables.tx_isolation;
 
163
  return (enum_tx_isolation)session->variables.tx_isolation;
175
164
}
176
165
 
177
 
Session::Session(plugin::Client *client_arg)
178
 
  :
 
166
Session::Session(plugin::Client *client_arg, catalog::Instance::shared_ptr catalog_arg) :
179
167
  Open_tables_state(refresh_version),
180
168
  mem_root(&main_mem_root),
 
169
  xa_id(0),
181
170
  lex(&main_lex),
182
 
  query(),
 
171
  query(new std::string),
 
172
  _schema(new std::string("")),
183
173
  client(client_arg),
184
174
  scheduler(NULL),
185
175
  scheduler_arg(NULL),
186
176
  lock_id(&main_lock_id),
187
 
  user_time(0),
 
177
  thread_stack(NULL),
 
178
  security_ctx(identifier::User::make_shared()),
 
179
  where(Session::DEFAULT_WHERE),
 
180
  dbug_sentry(Session_SENTRY_MAGIC),
 
181
  mysys_var(0),
 
182
  command(COM_CONNECT),
 
183
  file_id(0),
 
184
  _epoch(boost::gregorian::date(1970,1,1)),
 
185
  _connect_time(boost::posix_time::microsec_clock::universal_time()),
 
186
  utime_after_lock(0),
188
187
  ha_data(plugin::num_trx_monitored_objects),
 
188
  query_id(0),
 
189
  warn_query_id(0),
 
190
  concurrent_execute_allowed(true),
189
191
  arg_of_last_insert_id_function(false),
190
192
  first_successful_insert_id_in_prev_stmt(0),
191
193
  first_successful_insert_id_in_cur_stmt(0),
192
194
  limit_found_rows(0),
193
 
  global_read_lock(0),
 
195
  options(session_startup_options),
 
196
  row_count_func(-1),
 
197
  sent_row_count(0),
 
198
  examined_row_count(0),
 
199
  used_tables(0),
 
200
  total_warn_count(0),
 
201
  col_access(0),
 
202
  statement_id_counter(0),
 
203
  row_count(0),
 
204
  thread_id(0),
 
205
  tmp_table(0),
 
206
  _global_read_lock(NONE),
 
207
  count_cuted_fields(CHECK_FIELD_ERROR_FOR_NULL),
 
208
  _killed(NOT_KILLED),
194
209
  some_tables_deleted(false),
195
210
  no_errors(false),
196
211
  password(false),
202
217
  m_lip(NULL),
203
218
  cached_table(0),
204
219
  transaction_message(NULL),
205
 
  statement_message(NULL)
 
220
  statement_message(NULL),
 
221
  session_event_observers(NULL),
 
222
  _catalog(catalog_arg),
 
223
  use_usage(false)
206
224
{
207
 
  memset(process_list_info, 0, PROCESS_LIST_WIDTH);
208
225
  client->setSession(this);
209
226
 
210
227
  /*
213
230
    will be re-initialized in init_for_queries().
214
231
  */
215
232
  memory::init_sql_alloc(&main_mem_root, memory::ROOT_MIN_BLOCK_SIZE, 0);
216
 
  thread_stack= NULL;
217
 
  count_cuted_fields= CHECK_FIELD_IGNORE;
218
 
  killed= NOT_KILLED;
219
 
  col_access= 0;
220
 
  tmp_table= 0;
221
 
  used_tables= 0;
222
233
  cuted_fields= sent_row_count= row_count= 0L;
223
 
  row_count_func= -1;
224
 
  statement_id_counter= 0UL;
225
234
  // Must be reset to handle error with Session's created for init of mysqld
226
235
  lex->current_select= 0;
227
 
  start_time=(time_t) 0;
228
 
  start_utime= 0L;
229
 
  utime_after_lock= 0L;
230
236
  memset(&variables, 0, sizeof(variables));
231
 
  thread_id= 0;
232
 
  file_id = 0;
233
 
  query_id= 0;
234
 
  warn_query_id= 0;
235
 
  mysys_var= 0;
236
 
  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);
 
237
  scoreboard_index= -1;
 
238
  cleanup_done= abort_on_warning= no_warnings_for_error= false;  
 
239
 
 
240
  /* query_cache init */
 
241
  query_cache_key= "";
 
242
  resultset= NULL;
239
243
 
240
244
  /* Variables with default values */
241
245
  proc_info="login";
242
 
  where= Session::DEFAULT_WHERE;
243
 
  command= COM_CONNECT;
244
246
 
245
247
  plugin_sessionvar_init(this);
246
248
  /*
250
252
  */
251
253
  variables.pseudo_thread_id= thread_id;
252
254
  server_status= SERVER_STATUS_AUTOCOMMIT;
253
 
  options= session_startup_options;
254
255
 
255
256
  if (variables.max_join_size == HA_POS_ERROR)
256
257
    options |= OPTION_BIG_SELECTS;
262
263
  session_tx_isolation= (enum_tx_isolation) variables.tx_isolation;
263
264
  warn_list.empty();
264
265
  memset(warn_count, 0, sizeof(warn_count));
265
 
  total_warn_count= 0;
266
266
  memset(&status_var, 0, sizeof(status_var));
267
267
 
268
268
  /* Initialize sub structures */
269
269
  memory::init_sql_alloc(&warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE);
270
 
  hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0,
271
 
            (hash_get_key) get_var_key,
272
 
            (hash_free_key) free_user_var, 0);
273
270
 
274
271
  substitute_null_with_insert_id = false;
275
 
  thr_lock_info_init(&lock_info); /* safety: will be reset after start */
 
272
  lock_info.init(); /* safety: will be reset after start */
276
273
  thr_lock_owner_init(&main_lock_id, &lock_info);
277
274
 
278
275
  m_internal_handler= NULL;
 
276
  
 
277
  plugin::EventObserver::registerSessionEvents(*this); 
279
278
}
280
279
 
281
280
void Session::free_items()
299
298
  m_internal_handler= handler;
300
299
}
301
300
 
302
 
bool Session::handle_error(uint32_t sql_errno, const char *message,
303
 
                       DRIZZLE_ERROR::enum_warning_level level)
 
301
bool Session::handle_error(drizzled::error_t sql_errno, const char *message,
 
302
                           DRIZZLE_ERROR::enum_warning_level level)
304
303
{
305
304
  if (m_internal_handler)
306
305
  {
310
309
  return false;                                 // 'false', as per coding style
311
310
}
312
311
 
 
312
void Session::setAbort(bool arg)
 
313
{
 
314
  mysys_var->abort= arg;
 
315
}
 
316
 
 
317
void Session::lockOnSys()
 
318
{
 
319
  if (not mysys_var)
 
320
    return;
 
321
 
 
322
  setAbort(true);
 
323
  boost_unique_lock_t scopedLock(mysys_var->mutex);
 
324
  if (mysys_var->current_cond)
 
325
  {
 
326
    mysys_var->current_mutex->lock();
 
327
    mysys_var->current_cond->notify_all();
 
328
    mysys_var->current_mutex->unlock();
 
329
  }
 
330
}
 
331
 
313
332
void Session::pop_internal_handler()
314
333
{
315
334
  assert(m_internal_handler != NULL);
316
335
  m_internal_handler= NULL;
317
336
}
318
337
 
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
 
338
void Session::get_xid(DRIZZLE_XID *xid)
 
339
{
 
340
  *xid = *(DRIZZLE_XID *) &transaction.xid_state.xid;
 
341
}
356
342
 
357
343
/* Do operations that may take a long time */
358
344
 
360
346
{
361
347
  assert(cleanup_done == false);
362
348
 
363
 
  killed= KILL_CONNECTION;
 
349
  setKilled(KILL_CONNECTION);
364
350
#ifdef ENABLE_WHEN_BINLOG_WILL_BE_ABLE_TO_PREPARE
365
351
  if (transaction.xid_state.xa_state == XA_PREPARED)
366
352
  {
369
355
#endif
370
356
  {
371
357
    TransactionServices &transaction_services= TransactionServices::singleton();
372
 
    transaction_services.ha_rollback_trans(this, true);
 
358
    transaction_services.rollbackTransaction(this, true);
373
359
    xid_cache_delete(&transaction.xid_state);
374
360
  }
375
 
  hash_free(&user_vars);
 
361
 
 
362
  for (UserVars::iterator iter= user_vars.begin();
 
363
       iter != user_vars.end();
 
364
       iter++)
 
365
  {
 
366
    user_var_entry *entry= (*iter).second;
 
367
    boost::checked_delete(entry);
 
368
  }
 
369
  user_vars.clear();
 
370
 
 
371
 
376
372
  close_temporary_tables();
377
373
 
378
374
  if (global_read_lock)
379
 
    unlock_global_read_lock(this);
 
375
  {
 
376
    unlockGlobalReadLock();
 
377
  }
380
378
 
381
379
  cleanup_done= true;
382
380
}
384
382
Session::~Session()
385
383
{
386
384
  this->checkSentry();
387
 
  add_to_status(&global_status_var, &status_var);
388
385
 
389
 
  if (client->isConnected())
 
386
  if (client and client->isConnected())
390
387
  {
 
388
    assert(security_ctx);
391
389
    if (global_system_variables.log_warnings)
392
 
        errmsg_printf(ERRMSG_LVL_WARN, ER(ER_FORCING_CLOSE),internal::my_progname,
393
 
                      thread_id,
394
 
                      (getSecurityContext().getUser().c_str() ?
395
 
                       getSecurityContext().getUser().c_str() : ""));
396
 
    disconnect(0, false);
 
390
    {
 
391
      errmsg_printf(ERRMSG_LVL_WARN, ER(ER_FORCING_CLOSE),
 
392
                    internal::my_progname,
 
393
                    thread_id,
 
394
                    security_ctx->username().c_str());
 
395
    }
 
396
 
 
397
    disconnect();
397
398
  }
398
399
 
399
400
  /* Close connection */
400
 
  client->close();
401
 
  delete client;
 
401
  if (client)
 
402
  {
 
403
    client->close();
 
404
    boost::checked_delete(client);
 
405
    client= NULL;
 
406
  }
402
407
 
403
408
  if (cleanup_done == false)
404
409
    cleanup();
406
411
  plugin::StorageEngine::closeConnection(this);
407
412
  plugin_sessionvar_cleanup(this);
408
413
 
409
 
  free_root(&warn_root,MYF(0));
 
414
  warn_root.free_root(MYF(0));
410
415
  mysys_var=0;                                  // Safety (shouldn't be needed)
411
416
  dbug_sentry= Session_SENTRY_GONE;
412
417
 
413
 
  free_root(&main_mem_root, MYF(0));
414
 
  pthread_setspecific(THR_Session,  0);
 
418
  main_mem_root.free_root(MYF(0));
 
419
  currentMemRoot().release();
 
420
  currentSession().release();
415
421
 
416
422
  plugin::Logging::postEndDo(this);
417
 
 
418
 
  /* Ensure that no one is using Session */
419
 
  pthread_mutex_unlock(&LOCK_delete);
420
 
  pthread_mutex_destroy(&LOCK_delete);
421
 
}
422
 
 
423
 
/*
424
 
  Add all status variables to another status variable array
425
 
 
426
 
  SYNOPSIS
427
 
   add_to_status()
428
 
   to_var       add to this array
429
 
   from_var     from this array
430
 
 
431
 
  NOTES
432
 
    This function assumes that all variables are long/ulong.
433
 
    If this assumption will change, then we have to explictely add
434
 
    the other variables after the while loop
435
 
*/
436
 
void add_to_status(system_status_var *to_var, system_status_var *from_var)
437
 
{
438
 
  ulong *end= (ulong*) ((unsigned char*) to_var +
439
 
                        offsetof(system_status_var, last_system_status_var) +
440
 
                        sizeof(ulong));
441
 
  ulong *to= (ulong*) to_var, *from= (ulong*) from_var;
442
 
 
443
 
  while (to != end)
444
 
    *(to++)+= *(from++);
445
 
}
446
 
 
447
 
/*
448
 
  Add the difference between two status variable arrays to another one.
449
 
 
450
 
  SYNOPSIS
451
 
    add_diff_to_status
452
 
    to_var       add to this array
453
 
    from_var     from this array
454
 
    dec_var      minus this array
455
 
 
456
 
  NOTE
457
 
    This function assumes that all variables are long/ulong.
458
 
*/
459
 
void add_diff_to_status(system_status_var *to_var, system_status_var *from_var,
460
 
                        system_status_var *dec_var)
461
 
{
462
 
  ulong *end= (ulong*) ((unsigned char*) to_var + offsetof(system_status_var,
463
 
                                                  last_system_status_var) +
464
 
                        sizeof(ulong));
465
 
  ulong *to= (ulong*) to_var, *from= (ulong*) from_var, *dec= (ulong*) dec_var;
466
 
 
467
 
  while (to != end)
468
 
    *(to++)+= *(from++) - *(dec++);
469
 
}
470
 
 
471
 
void Session::awake(Session::killed_state state_to_set)
472
 
{
 
423
  plugin::EventObserver::deregisterSessionEvents(*this); 
 
424
 
 
425
  for (PropertyMap::iterator iter= life_properties.begin(); iter != life_properties.end(); iter++)
 
426
  {
 
427
    boost::checked_delete((*iter).second);
 
428
  }
 
429
  life_properties.clear();
 
430
}
 
431
 
 
432
void Session::setClient(plugin::Client *client_arg)
 
433
{
 
434
  client= client_arg;
 
435
  client->setSession(this);
 
436
}
 
437
 
 
438
void Session::awake(Session::killed_state_t state_to_set)
 
439
{
 
440
  if ((state_to_set == Session::KILL_QUERY) and (command == COM_SLEEP))
 
441
    return;
 
442
 
473
443
  this->checkSentry();
474
 
  safe_mutex_assert_owner(&LOCK_delete);
475
 
 
476
 
  killed= state_to_set;
 
444
 
 
445
  setKilled(state_to_set);
 
446
  scheduler->killSession(this);
 
447
 
477
448
  if (state_to_set != Session::KILL_QUERY)
478
449
  {
479
 
    scheduler->killSession(this);
480
450
    DRIZZLE_CONNECTION_DONE(thread_id);
481
451
  }
 
452
 
482
453
  if (mysys_var)
483
454
  {
484
 
    pthread_mutex_lock(&mysys_var->mutex);
 
455
    boost_unique_lock_t scopedLock(mysys_var->mutex);
485
456
    /*
 
457
      "
486
458
      This broadcast could be up in the air if the victim thread
487
459
      exits the cond in the time between read and broadcast, but that is
488
460
      ok since all we want to do is to make the victim thread get out
503
475
    */
504
476
    if (mysys_var->current_cond && mysys_var->current_mutex)
505
477
    {
506
 
      pthread_mutex_lock(mysys_var->current_mutex);
507
 
      pthread_cond_broadcast(mysys_var->current_cond);
508
 
      pthread_mutex_unlock(mysys_var->current_mutex);
 
478
      mysys_var->current_mutex->lock();
 
479
      mysys_var->current_cond->notify_all();
 
480
      mysys_var->current_mutex->unlock();
509
481
    }
510
 
    pthread_mutex_unlock(&mysys_var->mutex);
511
482
  }
512
483
}
513
484
 
523
494
  */
524
495
  assert(thread_stack);
525
496
 
526
 
  if (pthread_setspecific(THR_Session,  this) ||
527
 
      pthread_setspecific(THR_Mem_root, &mem_root))
528
 
    return true;
 
497
  currentSession().release();
 
498
  currentSession().reset(this);
 
499
 
 
500
  currentMemRoot().release();
 
501
  currentMemRoot().reset(&mem_root);
529
502
 
530
503
  mysys_var=my_thread_var;
531
504
 
534
507
    This allows us to move Session to different threads if needed.
535
508
  */
536
509
  mysys_var->id= thread_id;
537
 
  real_id= pthread_self();                      // For debugging
538
510
 
539
511
  /*
540
512
    We have to call thr_lock_info_init() again here as Session may have been
541
513
    created in another thread
542
514
  */
543
 
  thr_lock_info_init(&lock_info);
 
515
  lock_info.init();
 
516
 
544
517
  return false;
545
518
}
546
519
 
560
533
  command= COM_SLEEP;
561
534
  set_time();
562
535
 
563
 
  reset_root_defaults(mem_root, variables.query_alloc_block_size,
564
 
                      variables.query_prealloc_size);
 
536
  mem_root->reset_root_defaults(variables.query_alloc_block_size,
 
537
                                variables.query_prealloc_size);
565
538
  transaction.xid_state.xid.null();
566
539
  transaction.xid_state.in_session=1;
 
540
  if (use_usage)
 
541
    resetUsage();
567
542
}
568
543
 
569
544
bool Session::initGlobals()
570
545
{
571
546
  if (storeGlobals())
572
547
  {
573
 
    disconnect(ER_OUT_OF_RESOURCES, true);
574
 
    statistic_increment(aborted_connects, &LOCK_status);
 
548
    disconnect(ER_OUT_OF_RESOURCES);
 
549
    status_var.aborted_connects++;
575
550
    return true;
576
551
  }
577
552
  return false;
581
556
{
582
557
  if (initGlobals() || authenticate())
583
558
  {
584
 
    disconnect(0, true);
 
559
    disconnect();
585
560
    return;
586
561
  }
587
562
 
588
563
  prepareForQueries();
589
564
 
590
 
  while (! client->haveError() && killed != KILL_CONNECTION)
 
565
  while (not client->haveError() && getKilled() != KILL_CONNECTION)
591
566
  {
592
 
    if (! executeStatement())
 
567
    if (not executeStatement())
593
568
      break;
594
569
  }
595
570
 
596
 
  disconnect(0, true);
 
571
  disconnect();
597
572
}
598
573
 
599
 
bool Session::schedule()
 
574
bool Session::schedule(Session::shared_ptr &arg)
600
575
{
601
 
  scheduler= plugin::Scheduler::getScheduler();
602
 
  assert(scheduler);
603
 
 
604
 
  connection_count.increment();
605
 
 
606
 
  if (connection_count > max_used_connections)
607
 
    max_used_connections= connection_count;
608
 
 
609
 
  thread_id= variables.pseudo_thread_id= global_thread_id++;
610
 
 
611
 
  pthread_mutex_lock(&LOCK_thread_count);
612
 
  getSessionList().push_back(this);
613
 
  pthread_mutex_unlock(&LOCK_thread_count);
614
 
 
615
 
  if (scheduler->addSession(this))
616
 
  {
617
 
    DRIZZLE_CONNECTION_START(thread_id);
 
576
  arg->scheduler= plugin::Scheduler::getScheduler();
 
577
  assert(arg->scheduler);
 
578
 
 
579
  ++connection_count;
 
580
 
 
581
  long current_connections= connection_count;
 
582
 
 
583
  if (current_connections > 0 and static_cast<uint64_t>(current_connections) > current_global_counters.max_used_connections)
 
584
  {
 
585
    current_global_counters.max_used_connections= static_cast<uint64_t>(connection_count);
 
586
  }
 
587
 
 
588
  current_global_counters.connections++;
 
589
  arg->thread_id= arg->variables.pseudo_thread_id= global_thread_id++;
 
590
 
 
591
  session::Cache::singleton().insert(arg);
 
592
 
 
593
  if (unlikely(plugin::EventObserver::connectSession(*arg)))
 
594
  {
 
595
    // We should do something about an error...
 
596
  }
 
597
 
 
598
  if (plugin::Scheduler::getScheduler()->addSession(arg))
 
599
  {
 
600
    DRIZZLE_CONNECTION_START(arg->getSessionId());
618
601
    char error_message_buff[DRIZZLE_ERRMSG_SIZE];
619
602
 
620
 
    killed= Session::KILL_CONNECTION;
 
603
    arg->setKilled(Session::KILL_CONNECTION);
621
604
 
622
 
    statistic_increment(aborted_connects, &LOCK_status);
 
605
    arg->status_var.aborted_connects++;
623
606
 
624
607
    /* Can't use my_error() since store_globals has not been called. */
625
608
    /* TODO replace will better error message */
626
609
    snprintf(error_message_buff, sizeof(error_message_buff),
627
610
             ER(ER_CANT_CREATE_THREAD), 1);
628
 
    client->sendError(ER_CANT_CREATE_THREAD, error_message_buff);
 
611
    arg->client->sendError(ER_CANT_CREATE_THREAD, error_message_buff);
 
612
 
629
613
    return true;
630
614
  }
631
615
 
633
617
}
634
618
 
635
619
 
636
 
const char* Session::enter_cond(pthread_cond_t *cond,
637
 
                                pthread_mutex_t* mutex,
638
 
                                const char* msg)
 
620
/*
 
621
  Is this session viewable by the current user?
 
622
*/
 
623
bool Session::isViewable(identifier::User::const_reference user_arg) const
 
624
{
 
625
  return plugin::Authorization::isAuthorized(user_arg, this, false);
 
626
}
 
627
 
 
628
 
 
629
const char* Session::enter_cond(boost::condition_variable_any &cond, boost::mutex &mutex, const char* msg)
639
630
{
640
631
  const char* old_msg = get_proc_info();
641
632
  safe_mutex_assert_owner(mutex);
642
 
  mysys_var->current_mutex = mutex;
643
 
  mysys_var->current_cond = cond;
 
633
  mysys_var->current_mutex = &mutex;
 
634
  mysys_var->current_cond = &cond;
644
635
  this->set_proc_info(msg);
645
636
  return old_msg;
646
637
}
653
644
    locked (if that would not be the case, you'll get a deadlock if someone
654
645
    does a Session::awake() on you).
655
646
  */
656
 
  pthread_mutex_unlock(mysys_var->current_mutex);
657
 
  pthread_mutex_lock(&mysys_var->mutex);
 
647
  mysys_var->current_mutex->unlock();
 
648
  boost_unique_lock_t scopedLock(mysys_var->mutex);
658
649
  mysys_var->current_mutex = 0;
659
650
  mysys_var->current_cond = 0;
660
651
  this->set_proc_info(old_msg);
661
 
  pthread_mutex_unlock(&mysys_var->mutex);
662
652
}
663
653
 
664
654
bool Session::authenticate()
665
655
{
666
 
  lex_start(this);
667
656
  if (client->authenticate())
668
657
    return false;
669
658
 
670
 
  statistic_increment(aborted_connects, &LOCK_status);
 
659
  status_var.aborted_connects++;
 
660
 
671
661
  return true;
672
662
}
673
663
 
674
 
bool Session::checkUser(const char *passwd, uint32_t passwd_len, const char *in_db)
 
664
bool Session::checkUser(const std::string &passwd_str,
 
665
                        const std::string &in_db)
675
666
{
676
 
  const string passwd_str(passwd, passwd_len);
677
667
  bool is_authenticated=
678
 
    plugin::Authentication::isAuthenticated(getSecurityContext(),
679
 
                                            passwd_str);
 
668
    plugin::Authentication::isAuthenticated(user(), passwd_str);
680
669
 
681
670
  if (is_authenticated != true)
682
671
  {
 
672
    status_var.access_denied++;
683
673
    /* isAuthenticated has pushed the error message */
684
674
    return false;
685
675
  }
686
676
 
687
677
  /* Change database if necessary */
688
 
  if (in_db && in_db[0])
 
678
  if (not in_db.empty())
689
679
  {
690
 
    SchemaIdentifier identifier(in_db);
691
 
    if (mysql_change_db(this, identifier))
 
680
    identifier::Schema identifier(in_db);
 
681
    if (change_db(this, identifier))
692
682
    {
693
 
      /* mysql_change_db() has pushed the error message. */
 
683
      /* change_db() has pushed the error message. */
694
684
      return false;
695
685
    }
696
686
  }
697
687
  my_ok();
698
 
  password= test(passwd_len);          // remember for error messages
 
688
  password= not passwd_str.empty();
699
689
 
700
690
  /* Ready to handle queries */
701
691
  return true;
717
707
  main_da.reset_diagnostics_area();
718
708
 
719
709
  if (client->readCommand(&l_packet, &packet_length) == false)
 
710
  {
 
711
    return false;
 
712
  }
 
713
 
 
714
  if (getKilled() == KILL_CONNECTION)
720
715
    return false;
721
716
 
722
717
  if (packet_length == 0)
723
718
    return true;
724
719
 
725
 
  l_command= (enum enum_server_command) (unsigned char) l_packet[0];
 
720
  l_command= static_cast<enum_server_command>(l_packet[0]);
726
721
 
727
722
  if (command >= COM_END)
728
723
    command= COM_END;                           // Wrong command
729
724
 
730
725
  assert(packet_length);
731
 
  return ! dispatch_command(l_command, this, l_packet+1, (uint32_t) (packet_length-1));
 
726
  return not dispatch_command(l_command, this, l_packet+1, (uint32_t) (packet_length-1));
732
727
}
733
728
 
734
729
bool Session::readAndStoreQuery(const char *in_packet, uint32_t in_packet_length)
740
735
    in_packet_length--;
741
736
  }
742
737
  const char *pos= in_packet + in_packet_length; /* Point at end null */
743
 
  while (in_packet_length > 0 &&
744
 
         (pos[-1] == ';' || my_isspace(charset() ,pos[-1])))
 
738
  while (in_packet_length > 0 && (pos[-1] == ';' || my_isspace(charset() ,pos[-1])))
745
739
  {
746
740
    pos--;
747
741
    in_packet_length--;
748
742
  }
749
743
 
750
 
  query.assign(in_packet, in_packet + in_packet_length);
 
744
  std::string *new_query= new std::string(in_packet, in_packet + in_packet_length);
 
745
  // We can not be entirely sure _schema has a value
 
746
  if (_schema)
 
747
  {
 
748
    plugin::QueryRewriter::rewriteQuery(*_schema, *new_query);
 
749
  }
 
750
  query.reset(new_query);
 
751
  _state.reset(new State(in_packet, in_packet_length));
751
752
 
752
753
  return true;
753
754
}
772
773
       * (Which of course should never happen...)
773
774
       */
774
775
      server_status&= ~SERVER_STATUS_IN_TRANS;
775
 
      if (transaction_services.ha_commit_trans(this, true))
 
776
      if (transaction_services.commitTransaction(this, true))
776
777
        result= false;
777
778
      options&= ~(OPTION_BEGIN);
778
779
      break;
789
790
    case ROLLBACK_AND_CHAIN:
790
791
    {
791
792
      server_status&= ~SERVER_STATUS_IN_TRANS;
792
 
      if (transaction_services.ha_rollback_trans(this, true))
 
793
      if (transaction_services.rollbackTransaction(this, true))
793
794
        result= false;
794
795
      options&= ~(OPTION_BEGIN);
795
796
      if (result == true && (completion == ROLLBACK_AND_CHAIN))
802
803
  }
803
804
 
804
805
  if (result == false)
805
 
    my_error(killed_errno(), MYF(0));
 
806
  {
 
807
    my_error(static_cast<drizzled::error_t>(killed_errno()), MYF(0));
 
808
  }
806
809
  else if ((result == true) && do_release)
807
 
    killed= Session::KILL_CONNECTION;
 
810
  {
 
811
    setKilled(Session::KILL_CONNECTION);
 
812
  }
808
813
 
809
814
  return result;
810
815
}
822
827
  if (options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
823
828
  {
824
829
    server_status&= ~SERVER_STATUS_IN_TRANS;
825
 
    if (transaction_services.ha_commit_trans(this, true))
 
830
    if (transaction_services.commitTransaction(this, true))
826
831
      result= false;
827
832
  }
828
833
  options&= ~(OPTION_BEGIN);
873
878
  free_items();
874
879
  /* Reset where. */
875
880
  where= Session::DEFAULT_WHERE;
 
881
 
 
882
  /* Reset the temporary shares we built */
 
883
  for_each(temporary_shares.begin(),
 
884
           temporary_shares.end(),
 
885
           DeletePtr());
 
886
  temporary_shares.clear();
876
887
}
877
888
 
878
889
/**
899
910
  if (allocate_lex_string)
900
911
    if (!(lex_str= (LEX_STRING *)alloc(sizeof(LEX_STRING))))
901
912
      return 0;
902
 
  if (!(lex_str->str= strmake_root(mem_root, str, length)))
 
913
  if (!(lex_str->str= mem_root->strmake_root(str, length)))
903
914
    return 0;
904
915
  lex_str->length= length;
905
916
  return lex_str;
943
954
  return (result->send_fields(field_list));
944
955
}
945
956
 
946
 
void select_result::send_error(uint32_t errcode, const char *err)
 
957
void select_result::send_error(drizzled::error_t errcode, const char *err)
947
958
{
948
959
  my_message(errcode, err, MYF(0));
949
960
}
952
963
  Handling writing to file
953
964
************************************************************************/
954
965
 
955
 
void select_to_file::send_error(uint32_t errcode,const char *err)
 
966
void select_to_file::send_error(drizzled::error_t errcode,const char *err)
956
967
{
957
968
  my_message(errcode, err, MYF(0));
958
969
  if (file > 0)
959
970
  {
960
 
    (void) end_io_cache(cache);
 
971
    (void) cache->end_io_cache();
961
972
    (void) internal::my_close(file, MYF(0));
962
 
    (void) internal::my_delete(path, MYF(0));           // Delete file on error
 
973
    (void) internal::my_delete(path.file_string().c_str(), MYF(0));             // Delete file on error
963
974
    file= -1;
964
975
  }
965
976
}
967
978
 
968
979
bool select_to_file::send_eof()
969
980
{
970
 
  int error= test(end_io_cache(cache));
 
981
  int error= test(cache->end_io_cache());
971
982
  if (internal::my_close(file, MYF(MY_WME)))
972
983
    error= 1;
973
984
  if (!error)
989
1000
  /* In case of error send_eof() may be not called: close the file here. */
990
1001
  if (file >= 0)
991
1002
  {
992
 
    (void) end_io_cache(cache);
 
1003
    (void) cache->end_io_cache();
993
1004
    (void) internal::my_close(file, MYF(0));
994
1005
    file= -1;
995
1006
  }
996
 
  path[0]= '\0';
 
1007
  path= "";
997
1008
  row_count= 0;
998
1009
}
999
1010
 
1003
1014
    cache(static_cast<internal::IO_CACHE *>(memory::sql_calloc(sizeof(internal::IO_CACHE)))),
1004
1015
    row_count(0L)
1005
1016
{
1006
 
  path[0]=0;
 
1017
  path= "";
1007
1018
}
1008
1019
 
1009
1020
select_to_file::~select_to_file()
1037
1048
*/
1038
1049
 
1039
1050
 
1040
 
static int create_file(Session *session, char *path, file_exchange *exchange, internal::IO_CACHE *cache)
 
1051
static int create_file(Session *session,
 
1052
                       fs::path &target_path,
 
1053
                       file_exchange *exchange,
 
1054
                       internal::IO_CACHE *cache)
1041
1055
{
 
1056
  fs::path to_file(exchange->file_name);
1042
1057
  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))
 
1058
 
 
1059
  if (not to_file.has_root_directory())
1050
1060
  {
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);
 
1061
    target_path= fs::system_complete(getDataHomeCatalog());
 
1062
    util::string::const_shared_ptr schema(session->schema());
 
1063
    if (schema and not schema->empty())
 
1064
    {
 
1065
      int count_elements= 0;
 
1066
      for (fs::path::iterator iter= to_file.begin();
 
1067
           iter != to_file.end();
 
1068
           ++iter, ++count_elements)
 
1069
      { }
 
1070
 
 
1071
      if (count_elements == 1)
 
1072
      {
 
1073
        target_path /= *schema;
 
1074
      }
 
1075
    }
 
1076
    target_path /= to_file;
1055
1077
  }
1056
1078
  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))
 
1079
  {
 
1080
    target_path = exchange->file_name;
 
1081
  }
 
1082
 
 
1083
  if (not secure_file_priv.string().empty())
 
1084
  {
 
1085
    if (target_path.file_string().substr(0, secure_file_priv.file_string().size()) != secure_file_priv.file_string())
 
1086
    {
 
1087
      /* Write only allowed to dir or subdir specified by secure_file_priv */
 
1088
      my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
 
1089
      return -1;
 
1090
    }
 
1091
  }
 
1092
 
 
1093
  if (!access(target_path.file_string().c_str(), F_OK))
1068
1094
  {
1069
1095
    my_error(ER_FILE_EXISTS_ERROR, MYF(0), exchange->file_name);
1070
1096
    return -1;
1071
1097
  }
1072
1098
  /* Create the file world readable */
1073
 
  if ((file= internal::my_create(path, 0666, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0)
 
1099
  if ((file= internal::my_create(target_path.file_string().c_str(), 0666, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0)
1074
1100
    return file;
1075
1101
  (void) fchmod(file, 0666);                    // Because of umask()
1076
 
  if (init_io_cache(cache, file, 0L, internal::WRITE_CACHE, 0L, 1, MYF(MY_WME)))
 
1102
  if (cache->init_io_cache(file, 0L, internal::WRITE_CACHE, 0L, 1, MYF(MY_WME)))
1077
1103
  {
1078
1104
    internal::my_close(file, MYF(0));
1079
 
    internal::my_delete(path, MYF(0));  // Delete file on error, it was just created
 
1105
    internal::my_delete(target_path.file_string().c_str(), MYF(0));  // Delete file on error, it was just created
1080
1106
    return -1;
1081
1107
  }
1082
1108
  return file;
1090
1116
  bool string_results= false, non_string_results= false;
1091
1117
  unit= u;
1092
1118
  if ((uint32_t) strlen(exchange->file_name) + NAME_LEN >= FN_REFLEN)
1093
 
    strncpy(path,exchange->file_name,FN_REFLEN-1);
 
1119
  {
 
1120
    path= exchange->file_name;
 
1121
  }
1094
1122
 
1095
1123
  /* Check if there is any blobs in data */
1096
1124
  {
1100
1128
    {
1101
1129
      if (item->max_length >= MAX_BLOB_WIDTH)
1102
1130
      {
1103
 
        blob_flag=1;
1104
 
        break;
 
1131
        blob_flag=1;
 
1132
        break;
1105
1133
      }
 
1134
 
1106
1135
      if (item->result_type() == STRING_RESULT)
1107
1136
        string_results= true;
1108
1137
      else
1153
1182
  if (unit->offset_limit_cnt)
1154
1183
  {                                             // using limit offset,count
1155
1184
    unit->offset_limit_cnt--;
1156
 
    return(0);
 
1185
    return false;
1157
1186
  }
1158
1187
  row_count++;
1159
1188
  Item *item;
1162
1191
 
1163
1192
  if (my_b_write(cache,(unsigned char*) exchange->line_start->ptr(),
1164
1193
                 exchange->line_start->length()))
1165
 
    goto err;
 
1194
    return true;
 
1195
 
1166
1196
  while ((item=li++))
1167
1197
  {
1168
1198
    Item_result result_type=item->result_type();
1173
1203
    {
1174
1204
      if (my_b_write(cache,(unsigned char*) exchange->enclosed->ptr(),
1175
1205
                     exchange->enclosed->length()))
1176
 
        goto err;
 
1206
        return true;
1177
1207
    }
1178
1208
    if (!res)
1179
1209
    {                                           // NULL
1184
1214
          null_buff[0]=escape_char;
1185
1215
          null_buff[1]='N';
1186
1216
          if (my_b_write(cache,(unsigned char*) null_buff,2))
1187
 
            goto err;
 
1217
            return true;
1188
1218
        }
1189
1219
        else if (my_b_write(cache,(unsigned char*) "NULL",4))
1190
 
          goto err;
 
1220
          return true;
1191
1221
      }
1192
1222
      else
1193
1223
      {
1197
1227
    else
1198
1228
    {
1199
1229
      if (fixed_row_size)
1200
 
        used_length= min(res->length(),item->max_length);
 
1230
        used_length= min(res->length(), static_cast<size_t>(item->max_length));
1201
1231
      else
1202
1232
        used_length= res->length();
1203
1233
 
1278
1308
            tmp_buff[1]= *pos ? *pos : '0';
1279
1309
            if (my_b_write(cache,(unsigned char*) start,(uint32_t) (pos-start)) ||
1280
1310
                my_b_write(cache,(unsigned char*) tmp_buff,2))
1281
 
              goto err;
 
1311
              return true;
1282
1312
            start=pos+1;
1283
1313
          }
1284
1314
        }
1285
1315
        if (my_b_write(cache,(unsigned char*) start,(uint32_t) (pos-start)))
1286
 
          goto err;
 
1316
          return true;
1287
1317
      }
1288
1318
      else if (my_b_write(cache,(unsigned char*) res->ptr(),used_length))
1289
 
        goto err;
 
1319
        return true;
1290
1320
    }
1291
1321
    if (fixed_row_size)
1292
1322
    {                                           // Fill with space
1302
1332
        for (; length > sizeof(space) ; length-=sizeof(space))
1303
1333
        {
1304
1334
          if (my_b_write(cache,(unsigned char*) space,sizeof(space)))
1305
 
            goto err;
 
1335
            return true;
1306
1336
        }
1307
1337
        if (my_b_write(cache,(unsigned char*) space,length))
1308
 
          goto err;
 
1338
          return true;
1309
1339
      }
1310
1340
    }
1311
1341
    if (res && enclosed)
1312
1342
    {
1313
1343
      if (my_b_write(cache, (unsigned char*) exchange->enclosed->ptr(),
1314
1344
                     exchange->enclosed->length()))
1315
 
        goto err;
 
1345
        return true;
1316
1346
    }
1317
1347
    if (--items_left)
1318
1348
    {
1319
1349
      if (my_b_write(cache, (unsigned char*) exchange->field_term->ptr(),
1320
1350
                     field_term_length))
1321
 
        goto err;
 
1351
        return true;
1322
1352
    }
1323
1353
  }
1324
1354
  if (my_b_write(cache,(unsigned char*) exchange->line_term->ptr(),
1325
1355
                 exchange->line_term->length()))
1326
 
    goto err;
1327
 
  return(0);
1328
 
err:
1329
 
  return(1);
 
1356
  {
 
1357
    return true;
 
1358
  }
 
1359
 
 
1360
  return false;
1330
1361
}
1331
1362
 
1332
1363
 
1359
1390
  if (row_count++ > 1)
1360
1391
  {
1361
1392
    my_message(ER_TOO_MANY_ROWS, ER(ER_TOO_MANY_ROWS), MYF(0));
1362
 
    goto err;
 
1393
    return 1;
1363
1394
  }
1364
1395
  while ((item=li++))
1365
1396
  {
1367
1398
    if (!res)                                   // If NULL
1368
1399
    {
1369
1400
      if (my_b_write(cache,(unsigned char*) "",1))
1370
 
        goto err;
 
1401
        return 1;
1371
1402
    }
1372
1403
    else if (my_b_write(cache,(unsigned char*) res->ptr(),res->length()))
1373
1404
    {
1374
 
      my_error(ER_ERROR_ON_WRITE, MYF(0), path, errno);
1375
 
      goto err;
 
1405
      my_error(ER_ERROR_ON_WRITE, MYF(0), path.file_string().c_str(), errno);
 
1406
      return 1;
1376
1407
    }
1377
1408
  }
1378
1409
  return(0);
1379
 
err:
1380
 
  return(1);
1381
1410
}
1382
1411
 
1383
1412
 
1435
1464
      switch (val_item->result_type())
1436
1465
      {
1437
1466
      case REAL_RESULT:
1438
 
        op= &select_max_min_finder_subselect::cmp_real;
1439
 
        break;
 
1467
        op= &select_max_min_finder_subselect::cmp_real;
 
1468
        break;
1440
1469
      case INT_RESULT:
1441
 
        op= &select_max_min_finder_subselect::cmp_int;
1442
 
        break;
 
1470
        op= &select_max_min_finder_subselect::cmp_int;
 
1471
        break;
1443
1472
      case STRING_RESULT:
1444
 
        op= &select_max_min_finder_subselect::cmp_str;
1445
 
        break;
 
1473
        op= &select_max_min_finder_subselect::cmp_str;
 
1474
        break;
1446
1475
      case DECIMAL_RESULT:
1447
1476
        op= &select_max_min_finder_subselect::cmp_decimal;
1448
1477
        break;
1449
1478
      case ROW_RESULT:
1450
1479
        // This case should never be choosen
1451
 
        assert(0);
1452
 
        op= 0;
 
1480
        assert(0);
 
1481
        op= 0;
1453
1482
      }
1454
1483
    }
1455
1484
    cache->store(val_item);
1488
1517
bool select_max_min_finder_subselect::cmp_decimal()
1489
1518
{
1490
1519
  Item *maxmin= ((Item_singlerow_subselect *)item)->element_index(0);
1491
 
  my_decimal cval, *cvalue= cache->val_decimal(&cval);
1492
 
  my_decimal mval, *mvalue= maxmin->val_decimal(&mval);
 
1520
  type::Decimal cval, *cvalue= cache->val_decimal(&cval);
 
1521
  type::Decimal mval, *mvalue= maxmin->val_decimal(&mval);
1493
1522
  if (fmax)
1494
1523
    return (cache->null_value && !maxmin->null_value) ||
1495
1524
      (!cache->null_value && !maxmin->null_value &&
1496
 
       my_decimal_cmp(cvalue, mvalue) > 0) ;
 
1525
       class_decimal_cmp(cvalue, mvalue) > 0) ;
1497
1526
  return (maxmin->null_value && !cache->null_value) ||
1498
1527
    (!cache->null_value && !maxmin->null_value &&
1499
 
     my_decimal_cmp(cvalue,mvalue) < 0);
 
1528
     class_decimal_cmp(cvalue,mvalue) < 0);
1500
1529
}
1501
1530
 
1502
1531
bool select_max_min_finder_subselect::cmp_str()
1538
1567
void Session::end_statement()
1539
1568
{
1540
1569
  /* Cleanup SQL processing state to reuse this statement in next query. */
1541
 
  lex_end(lex);
 
1570
  lex->end();
 
1571
  query_cache_key= ""; // reset the cache key
 
1572
  resetResultsetMessage();
1542
1573
}
1543
1574
 
1544
1575
bool Session::copy_db_to(char **p_db, size_t *p_db_length)
1545
1576
{
1546
 
  if (db.empty())
1547
 
  {
1548
 
    my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
1549
 
    return true;
1550
 
  }
1551
 
  *p_db= strmake(db.c_str(), db.length());
1552
 
  *p_db_length= db.length();
 
1577
  assert(_schema);
 
1578
  if (_schema and _schema->empty())
 
1579
  {
 
1580
    my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
 
1581
    return true;
 
1582
  }
 
1583
  else if (not _schema)
 
1584
  {
 
1585
    my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
 
1586
    return true;
 
1587
  }
 
1588
  assert(_schema);
 
1589
 
 
1590
  *p_db= strmake(_schema->c_str(), _schema->size());
 
1591
  *p_db_length= _schema->size();
 
1592
 
1553
1593
  return false;
1554
1594
}
1555
1595
 
1571
1611
  /* Fix for Intel compiler */
1572
1612
  if (copy_field)
1573
1613
  {
1574
 
    delete [] copy_field;
1575
 
    save_copy_field= copy_field= 0;
 
1614
    boost::checked_array_delete(copy_field);
 
1615
    save_copy_field= save_copy_field_end= copy_field= copy_field_end= 0;
1576
1616
  }
1577
1617
}
1578
1618
 
1579
1619
void Session::send_kill_message() const
1580
1620
{
1581
 
  int err= killed_errno();
1582
 
  if (err)
 
1621
  drizzled::error_t err= static_cast<drizzled::error_t>(killed_errno());
 
1622
  if (err != EE_OK)
1583
1623
    my_message(err, ER(err), MYF(0));
1584
1624
}
1585
1625
 
1589
1629
}
1590
1630
 
1591
1631
 
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
 
bool Session::set_db(const std::string &new_db)
 
1632
void Session::set_db(const std::string &new_db)
1621
1633
{
1622
1634
  /* Do not reallocate memory if current chunk is big enough. */
1623
1635
  if (new_db.length())
1624
 
    db= new_db;
 
1636
  {
 
1637
    _schema.reset(new std::string(new_db));
 
1638
  }
1625
1639
  else
1626
 
    db.clear();
1627
 
 
1628
 
  return false;
1629
 
}
1630
 
 
1631
 
 
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
 
}
 
1640
  {
 
1641
    _schema.reset(new std::string(""));
 
1642
  }
 
1643
}
 
1644
 
1670
1645
 
1671
1646
/**
1672
1647
  Mark transaction to rollback and mark error as fatal to a sub-statement.
1683
1658
  }
1684
1659
}
1685
1660
 
1686
 
void Session::disconnect(uint32_t errcode, bool should_lock)
 
1661
void Session::disconnect(enum error_t errcode)
1687
1662
{
1688
1663
  /* Allow any plugins to cleanup their session variables */
1689
1664
  plugin_sessionvar_cleanup(this);
1690
1665
 
1691
1666
  /* If necessary, log any aborted or unauthorized connections */
1692
 
  if (killed || client->wasAborted())
1693
 
    statistic_increment(aborted_threads, &LOCK_status);
 
1667
  if (getKilled() || client->wasAborted())
 
1668
  {
 
1669
    status_var.aborted_threads++;
 
1670
  }
1694
1671
 
1695
1672
  if (client->wasAborted())
1696
1673
  {
1697
 
    if (! killed && variables.log_warnings > 1)
 
1674
    if (not getKilled() && variables.log_warnings > 1)
1698
1675
    {
1699
 
      SecurityContext *sctx= &security_ctx;
1700
 
 
1701
1676
      errmsg_printf(ERRMSG_LVL_WARN, ER(ER_NEW_ABORTING_CONNECTION)
1702
1677
                  , thread_id
1703
 
                  , (db.empty() ? "unconnected" : db.c_str())
1704
 
                  , sctx->getUser().empty() == false ? sctx->getUser().c_str() : "unauthenticated"
1705
 
                  , sctx->getIp().c_str()
 
1678
                  , (_schema->empty() ? "unconnected" : _schema->c_str())
 
1679
                  , security_ctx->username().empty() == false ? security_ctx->username().c_str() : "unauthenticated"
 
1680
                  , security_ctx->address().c_str()
1706
1681
                  , (main_da.is_error() ? main_da.message() : ER(ER_UNKNOWN_ERROR)));
1707
1682
    }
1708
1683
  }
1709
1684
 
1710
 
  /* Close out our connection to the client */
1711
 
  if (should_lock)
1712
 
    (void) pthread_mutex_lock(&LOCK_thread_count);
1713
 
  killed= Session::KILL_CONNECTION;
 
1685
  setKilled(Session::KILL_CONNECTION);
 
1686
 
1714
1687
  if (client->isConnected())
1715
1688
  {
1716
 
    if (errcode)
 
1689
    if (errcode != EE_OK)
1717
1690
    {
1718
1691
      /*my_error(errcode, ER(errcode));*/
1719
1692
      client->sendError(errcode, ER(errcode));
1720
1693
    }
1721
1694
    client->close();
1722
1695
  }
1723
 
  if (should_lock)
1724
 
    (void) pthread_mutex_unlock(&LOCK_thread_count);
1725
1696
}
1726
1697
 
1727
1698
void Session::reset_for_next_command()
1749
1720
  Close all temporary tables created by 'CREATE TEMPORARY TABLE' for thread
1750
1721
*/
1751
1722
 
1752
 
void Session::close_temporary_tables()
 
1723
void Open_tables_state::close_temporary_tables()
1753
1724
{
1754
1725
  Table *table;
1755
1726
  Table *tmp_next;
1759
1730
 
1760
1731
  for (table= temporary_tables; table; table= tmp_next)
1761
1732
  {
1762
 
    tmp_next= table->next;
 
1733
    tmp_next= table->getNext();
1763
1734
    nukeTable(table);
1764
1735
  }
1765
1736
  temporary_tables= NULL;
1769
1740
  unlink from session->temporary tables and close temporary table
1770
1741
*/
1771
1742
 
1772
 
void Session::close_temporary_table(Table *table)
 
1743
void Open_tables_state::close_temporary_table(Table *table)
1773
1744
{
1774
 
  if (table->prev)
 
1745
  if (table->getPrev())
1775
1746
  {
1776
 
    table->prev->next= table->next;
1777
 
    if (table->prev->next)
1778
 
      table->next->prev= table->prev;
 
1747
    table->getPrev()->setNext(table->getNext());
 
1748
    if (table->getPrev()->getNext())
 
1749
    {
 
1750
      table->getNext()->setPrev(table->getPrev());
 
1751
    }
1779
1752
  }
1780
1753
  else
1781
1754
  {
1786
1759
      passing non-zero value to end_slave via rli->save_temporary_tables
1787
1760
      when no temp tables opened, see an invariant below.
1788
1761
    */
1789
 
    temporary_tables= table->next;
 
1762
    temporary_tables= table->getNext();
1790
1763
    if (temporary_tables)
1791
 
      table->next->prev= NULL;
 
1764
    {
 
1765
      table->getNext()->setPrev(NULL);
 
1766
    }
1792
1767
  }
1793
1768
  nukeTable(table);
1794
1769
}
1801
1776
  If this is needed, use close_temporary_table()
1802
1777
*/
1803
1778
 
1804
 
void Session::nukeTable(Table *table)
 
1779
void Open_tables_state::nukeTable(Table *table)
1805
1780
{
1806
 
  plugin::StorageEngine *table_type= table->s->db_type();
 
1781
  plugin::StorageEngine *table_type= table->getShare()->db_type();
1807
1782
 
1808
1783
  table->free_io_cache();
1809
 
  table->closefrm(false);
 
1784
  table->delete_table();
1810
1785
 
1811
 
  TableIdentifier identifier(table->s->getSchemaName(), table->s->table_name.str, table->s->path.str);
 
1786
  identifier::Table identifier(table->getShare()->getSchemaName(), table->getShare()->getTableName(), table->getShare()->getPath());
1812
1787
  rm_temporary_table(table_type, identifier);
1813
1788
 
1814
 
  table->s->free_table_share();
 
1789
  boost::checked_delete(table->getMutableShare());
1815
1790
 
1816
 
  /* This makes me sad, but we're allocating it via malloc */
1817
 
  free(table);
 
1791
  boost::checked_delete(table);
1818
1792
}
1819
1793
 
1820
1794
/** Clear most status variables. */
1821
1795
extern time_t flush_status_time;
1822
 
extern uint32_t max_used_connections;
1823
1796
 
1824
1797
void Session::refresh_status()
1825
1798
{
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
1799
  /* Reset thread's status variables */
1832
1800
  memset(&status_var, 0, sizeof(status_var));
1833
1801
 
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
1802
  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);
 
1803
  current_global_counters.max_used_connections= 1; /* We set it to one, because we know we exist */
 
1804
  current_global_counters.connections= 0;
1842
1805
}
1843
1806
 
1844
1807
user_var_entry *Session::getVariable(LEX_STRING &name, bool create_if_not_exists)
1845
1808
{
 
1809
  return getVariable(std::string(name.str, name.length), create_if_not_exists);
 
1810
}
 
1811
 
 
1812
user_var_entry *Session::getVariable(const std::string  &name, bool create_if_not_exists)
 
1813
{
 
1814
  UserVarsRange ppp= user_vars.equal_range(name);
 
1815
 
 
1816
  for (UserVars::iterator iter= ppp.first;
 
1817
       iter != ppp.second; ++iter)
 
1818
  {
 
1819
    return (*iter).second;
 
1820
  }
 
1821
 
 
1822
  if (not create_if_not_exists)
 
1823
    return NULL;
 
1824
 
1846
1825
  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)
 
1826
  entry= new (nothrow) user_var_entry(name.c_str(), query_id);
 
1827
 
 
1828
  if (entry == NULL)
 
1829
    return NULL;
 
1830
 
 
1831
  std::pair<UserVars::iterator, bool> returnable= user_vars.insert(make_pair(name, entry));
 
1832
 
 
1833
  if (not returnable.second)
1851
1834
  {
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
 
 
 
1835
    boost::checked_delete(entry);
1866
1836
  }
1867
1837
 
1868
1838
  return entry;
1869
1839
}
1870
1840
 
1871
 
void Session::mark_temp_tables_as_free_for_reuse()
1872
 
{
1873
 
  for (Table *table= temporary_tables ; table ; table= table->next)
 
1841
void Session::setVariable(const std::string &name, const std::string &value)
 
1842
{
 
1843
  user_var_entry *updateable_var= getVariable(name.c_str(), true);
 
1844
 
 
1845
  updateable_var->update_hash(false,
 
1846
                              (void*)value.c_str(),
 
1847
                              static_cast<uint32_t>(value.length()), STRING_RESULT,
 
1848
                              &my_charset_bin,
 
1849
                              DERIVATION_IMPLICIT, false);
 
1850
}
 
1851
 
 
1852
void Open_tables_state::mark_temp_tables_as_free_for_reuse()
 
1853
{
 
1854
  for (Table *table= temporary_tables ; table ; table= table->getNext())
1874
1855
  {
1875
 
    if (table->query_id == query_id)
 
1856
    if (table->query_id == getQueryId())
1876
1857
    {
1877
1858
      table->query_id= 0;
1878
1859
      table->cursor->ha_reset();
1882
1863
 
1883
1864
void Session::mark_used_tables_as_free_for_reuse(Table *table)
1884
1865
{
1885
 
  for (; table ; table= table->next)
 
1866
  for (; table ; table= table->getNext())
1886
1867
  {
1887
 
    if (table->query_id == query_id)
 
1868
    if (table->query_id == getQueryId())
1888
1869
    {
1889
1870
      table->query_id= 0;
1890
1871
      table->cursor->ha_reset();
1903
1884
*/
1904
1885
void Session::close_thread_tables()
1905
1886
{
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
 
  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
 
  }
 
1887
  clearDerivedTables();
1933
1888
 
1934
1889
  /*
1935
1890
    Mark all temporary tables used by this statement as free for reuse.
1943
1898
    does not belong to statement for which we do close_thread_tables()).
1944
1899
    TODO: This should be fixed in later releases.
1945
1900
   */
1946
 
  if (backups_available == false)
1947
1901
  {
1948
1902
    TransactionServices &transaction_services= TransactionServices::singleton();
1949
1903
    main_da.can_overwrite_status= true;
1950
 
    transaction_services.ha_autocommit_or_rollback(this, is_error());
 
1904
    transaction_services.autocommitOrRollback(this, is_error());
1951
1905
    main_da.can_overwrite_status= false;
1952
1906
    transaction.stmt.reset();
1953
1907
  }
1963
1917
      handled either before writing a query log event (inside
1964
1918
      binlog_query()) or when preparing a pending event.
1965
1919
     */
1966
 
    mysql_unlock_tables(this, lock);
 
1920
    unlockTables(lock);
1967
1921
    lock= 0;
1968
1922
  }
1969
1923
  /*
1970
 
    Note that we need to hold LOCK_open while changing the
 
1924
    Note that we need to hold table::Cache::singleton().mutex() while changing the
1971
1925
    open_tables list. Another thread may work on it.
1972
 
    (See: remove_table_from_cache(), mysql_wait_completed_table())
 
1926
    (See: table::Cache::singleton().removeTable(), wait_completed_table())
1973
1927
    Closing a MERGE child before the parent would be fatal if the
1974
1928
    other thread tries to abort the MERGE lock in between.
1975
1929
  */
2003
1957
 
2004
1958
    if (not lock_tables(tables, counter, &need_reopen))
2005
1959
      break;
 
1960
 
2006
1961
    if (not need_reopen)
2007
1962
      return true;
 
1963
 
2008
1964
    close_tables_for_reopen(&tables);
2009
1965
  }
2010
 
  if ((mysql_handle_derived(lex, &mysql_derived_prepare) ||
2011
 
       (fill_derived_tables() &&
2012
 
        mysql_handle_derived(lex, &mysql_derived_filling))))
2013
 
    return true;
2014
 
 
2015
 
  return false;
2016
 
}
2017
 
 
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
 
}
2028
 
 
2029
 
bool Session::rm_temporary_table(TableIdentifier &identifier)
2030
 
{
2031
 
  if (plugin::StorageEngine::dropTable(*this, identifier))
 
1966
 
 
1967
  if ((handle_derived(lex, &derived_prepare) || (handle_derived(lex, &derived_filling))))
 
1968
    return true;
 
1969
 
 
1970
  return false;
 
1971
}
 
1972
 
 
1973
/*
 
1974
  @note "best_effort" is used in cases were if a failure occurred on this
 
1975
  operation it would not be surprising because we are only removing because there
 
1976
  might be an issue (lame engines).
 
1977
*/
 
1978
 
 
1979
bool Open_tables_state::rm_temporary_table(const identifier::Table &identifier, bool best_effort)
 
1980
{
 
1981
  if (not plugin::StorageEngine::dropTable(*static_cast<Session *>(this), identifier))
2032
1982
  {
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()");
 
1983
    if (not best_effort)
 
1984
    {
 
1985
      std::string path;
 
1986
      identifier.getSQLPath(path);
 
1987
      errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
 
1988
                    path.c_str(), errno);
 
1989
    }
2036
1990
 
2037
1991
    return true;
2038
1992
  }
2040
1994
  return false;
2041
1995
}
2042
1996
 
2043
 
bool Session::rm_temporary_table(plugin::StorageEngine *base, TableIdentifier &identifier)
 
1997
bool Open_tables_state::rm_temporary_table(plugin::StorageEngine *base, const identifier::Table &identifier)
2044
1998
{
 
1999
  drizzled::error_t error;
2045
2000
  assert(base);
2046
2001
 
2047
 
  if (plugin::StorageEngine::dropTable(*this, *base, identifier))
 
2002
  if (not plugin::StorageEngine::dropTable(*static_cast<Session *>(this), *base, identifier, error))
2048
2003
  {
 
2004
    std::string path;
 
2005
    identifier.getSQLPath(path);
2049
2006
    errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
2050
 
                  identifier.getSQLPath().c_str(), errno);
2051
 
    dumpTemporaryTableNames("rm_temporary_table()");
 
2007
                  path.c_str(), error);
2052
2008
 
2053
2009
    return true;
2054
2010
  }
2060
2016
  @note this will be removed, I am looking through Hudson to see if it is finding
2061
2017
  any tables that are missed during cleanup.
2062
2018
*/
2063
 
void Session::dumpTemporaryTableNames(const char *foo)
 
2019
void Open_tables_state::dumpTemporaryTableNames(const char *foo)
2064
2020
{
2065
2021
  Table *table;
2066
2022
 
2068
2024
    return;
2069
2025
 
2070
2026
  cerr << "Begin Run: " << foo << "\n";
2071
 
  for (table= temporary_tables; table; table= table->next)
 
2027
  for (table= temporary_tables; table; table= table->getNext())
2072
2028
  {
2073
2029
    bool have_proto= false;
2074
2030
 
2075
 
    message::Table *proto= table->s->getTableProto();
2076
 
    if (table->s->getTableProto())
 
2031
    message::Table *proto= table->getShare()->getTableProto();
 
2032
    if (table->getShare()->getTableProto())
2077
2033
      have_proto= true;
2078
2034
 
2079
2035
    const char *answer= have_proto ? "true" : "false";
2080
2036
 
2081
2037
    if (have_proto)
2082
2038
    {
2083
 
      cerr << "\tTable Name " << table->s->getSchemaName() << "." << table->s->table_name.str << " : " << answer << "\n";
 
2039
      cerr << "\tTable Name " << table->getShare()->getSchemaName() << "." << table->getShare()->getTableName() << " : " << answer << "\n";
2084
2040
      cerr << "\t\t Proto " << proto->schema() << " " << proto->name() << "\n";
2085
2041
    }
2086
2042
    else
2087
 
      cerr << "\tTabl;e Name " << table->s->getSchemaName() << "." << table->s->table_name.str << " : " << answer << "\n";
 
2043
    {
 
2044
      cerr << "\tTabl;e Name " << table->getShare()->getSchemaName() << "." << table->getShare()->getTableName() << " : " << answer << "\n";
 
2045
    }
2088
2046
  }
2089
2047
}
2090
2048
 
2091
 
bool Session::storeTableMessage(TableIdentifier &identifier, message::Table &table_message)
 
2049
bool Session::TableMessages::storeTableMessage(const identifier::Table &identifier, message::Table &table_message)
2092
2050
{
2093
2051
  table_message_cache.insert(make_pair(identifier.getPath(), table_message));
2094
2052
 
2095
2053
  return true;
2096
2054
}
2097
2055
 
2098
 
bool Session::removeTableMessage(TableIdentifier &identifier)
 
2056
bool Session::TableMessages::removeTableMessage(const identifier::Table &identifier)
2099
2057
{
2100
2058
  TableMessageCache::iterator iter;
2101
2059
 
2109
2067
  return true;
2110
2068
}
2111
2069
 
2112
 
bool Session::getTableMessage(TableIdentifier &identifier, message::Table &table_message)
 
2070
bool Session::TableMessages::getTableMessage(const identifier::Table &identifier, message::Table &table_message)
2113
2071
{
2114
2072
  TableMessageCache::iterator iter;
2115
2073
 
2123
2081
  return true;
2124
2082
}
2125
2083
 
2126
 
bool Session::doesTableMessageExist(TableIdentifier &identifier)
 
2084
bool Session::TableMessages::doesTableMessageExist(const identifier::Table &identifier)
2127
2085
{
2128
2086
  TableMessageCache::iterator iter;
2129
2087
 
2137
2095
  return true;
2138
2096
}
2139
2097
 
2140
 
bool Session::renameTableMessage(TableIdentifier &from, TableIdentifier &to)
 
2098
bool Session::TableMessages::renameTableMessage(const identifier::Table &from, const identifier::Table &to)
2141
2099
{
2142
2100
  TableMessageCache::iterator iter;
2143
2101
 
2156
2114
  return true;
2157
2115
}
2158
2116
 
 
2117
table::Singular *Session::getInstanceTable()
 
2118
{
 
2119
  temporary_shares.push_back(new table::Singular()); // This will not go into the tableshare cache, so no key is used.
 
2120
 
 
2121
  table::Singular *tmp_share= temporary_shares.back();
 
2122
 
 
2123
  assert(tmp_share);
 
2124
 
 
2125
  return tmp_share;
 
2126
}
 
2127
 
 
2128
 
 
2129
/**
 
2130
  Create a reduced Table object with properly set up Field list from a
 
2131
  list of field definitions.
 
2132
 
 
2133
    The created table doesn't have a table Cursor associated with
 
2134
    it, has no keys, no group/distinct, no copy_funcs array.
 
2135
    The sole purpose of this Table object is to use the power of Field
 
2136
    class to read/write data to/from table->getInsertRecord(). Then one can store
 
2137
    the record in any container (RB tree, hash, etc).
 
2138
    The table is created in Session mem_root, so are the table's fields.
 
2139
    Consequently, if you don't BLOB fields, you don't need to free it.
 
2140
 
 
2141
  @param session         connection handle
 
2142
  @param field_list  list of column definitions
 
2143
 
 
2144
  @return
 
2145
    0 if out of memory, Table object in case of success
 
2146
*/
 
2147
table::Singular *Session::getInstanceTable(List<CreateField> &field_list)
 
2148
{
 
2149
  temporary_shares.push_back(new table::Singular(this, field_list)); // This will not go into the tableshare cache, so no key is used.
 
2150
 
 
2151
  table::Singular *tmp_share= temporary_shares.back();
 
2152
 
 
2153
  assert(tmp_share);
 
2154
 
 
2155
  return tmp_share;
 
2156
}
 
2157
 
 
2158
namespace display  {
 
2159
 
 
2160
static const std::string NONE= "NONE";
 
2161
static const std::string GOT_GLOBAL_READ_LOCK= "HAS GLOBAL READ LOCK";
 
2162
static const std::string MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT= "HAS GLOBAL READ LOCK WITH BLOCKING COMMIT";
 
2163
 
 
2164
const std::string &type(drizzled::Session::global_read_lock_t type)
 
2165
{
 
2166
  switch (type) {
 
2167
    default:
 
2168
    case Session::NONE:
 
2169
      return NONE;
 
2170
    case Session::GOT_GLOBAL_READ_LOCK:
 
2171
      return GOT_GLOBAL_READ_LOCK;
 
2172
    case Session::MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT:
 
2173
      return MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT;
 
2174
  }
 
2175
}
 
2176
 
 
2177
size_t max_string_length(drizzled::Session::global_read_lock_t)
 
2178
{
 
2179
  return MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT.size();
 
2180
}
 
2181
 
 
2182
} /* namespace display */
 
2183
 
2159
2184
} /* namespace drizzled */