~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/session.cc

Merge Stewart.

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
22
22
 */
23
23
 
24
24
#include "config.h"
25
 
 
26
 
#include <drizzled/copy_field.h>
27
 
#include "drizzled/session.h"
28
 
#include "drizzled/session/cache.h"
29
 
#include "drizzled/error.h"
30
 
#include "drizzled/gettext.h"
31
 
#include "drizzled/query_id.h"
32
 
#include "drizzled/data_home.h"
33
 
#include "drizzled/sql_base.h"
34
 
#include "drizzled/lock.h"
35
 
#include "drizzled/item/cache.h"
36
 
#include "drizzled/item/float.h"
37
 
#include "drizzled/item/return_int.h"
38
 
#include "drizzled/item/empty_string.h"
39
 
#include "drizzled/show.h"
40
 
#include "drizzled/plugin/client.h"
 
25
#include <drizzled/session.h>
 
26
#include "drizzled/session_list.h"
 
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>
41
40
#include "drizzled/plugin/scheduler.h"
42
41
#include "drizzled/plugin/authentication.h"
43
 
#include "drizzled/plugin/logging.h"
44
42
#include "drizzled/plugin/transactional_storage_engine.h"
45
 
#include "drizzled/plugin/query_rewrite.h"
46
43
#include "drizzled/probes.h"
47
44
#include "drizzled/table_proto.h"
48
45
#include "drizzled/db.h"
49
46
#include "drizzled/pthread_globals.h"
50
47
#include "drizzled/transaction_services.h"
51
 
#include "drizzled/drizzled.h"
52
 
 
53
 
#include "drizzled/identifier.h"
54
 
 
55
 
#include <drizzled/refresh_version.h>
56
 
 
57
 
#include "drizzled/table/singular.h"
58
48
 
59
49
#include "plugin/myisam/myisam.h"
60
50
#include "drizzled/internal/iocache.h"
61
 
#include "drizzled/internal/thread_var.h"
62
 
#include "drizzled/plugin/event_observer.h"
63
 
 
64
 
#include "drizzled/util/functors.h"
65
 
 
66
 
#include "drizzled/display.h"
67
 
 
 
51
 
 
52
#include <fcntl.h>
68
53
#include <algorithm>
69
54
#include <climits>
70
 
#include <fcntl.h>
71
 
#include <sys/stat.h>
72
 
 
73
 
#include <boost/filesystem.hpp>
74
 
#include <boost/checked_delete.hpp>
75
 
 
76
 
#include "drizzled/util/backtrace.h"
77
55
 
78
56
using namespace std;
79
 
 
80
 
namespace fs=boost::filesystem;
81
57
namespace drizzled
82
58
{
83
59
 
 
60
extern "C"
 
61
{
 
62
  unsigned char *get_var_key(user_var_entry *entry, size_t *length, bool );
 
63
  void free_user_var(user_var_entry *entry);
 
64
}
 
65
 
84
66
/*
85
67
  The following is used to initialise Table_ident with a internal
86
68
  table name
89
71
char empty_c_string[1]= {0};    /* used for not defined db */
90
72
 
91
73
const char * const Session::DEFAULT_WHERE= "field list";
 
74
extern pthread_key_t THR_Session;
 
75
extern pthread_key_t THR_Mem_root;
 
76
extern uint32_t max_used_connections;
 
77
extern atomic<uint32_t> connection_count;
 
78
 
 
79
 
 
80
/****************************************************************************
 
81
** User variables
 
82
****************************************************************************/
 
83
unsigned char *get_var_key(user_var_entry *entry, size_t *length, bool )
 
84
{
 
85
  *length= entry->name.length;
 
86
  return (unsigned char*) entry->name.str;
 
87
}
 
88
 
 
89
void free_user_var(user_var_entry *entry)
 
90
{
 
91
  delete entry;
 
92
}
92
93
 
93
94
bool Key_part_spec::operator==(const Key_part_spec& other) const
94
95
{
95
96
  return length == other.length &&
96
97
         field_name.length == other.field_name.length &&
97
 
    !my_strcasecmp(system_charset_info, field_name.str, other.field_name.str);
 
98
         !strcmp(field_name.str, other.field_name.str);
98
99
}
99
100
 
100
 
Open_tables_state::Open_tables_state(uint64_t version_arg) :
101
 
  version(version_arg)
 
101
Open_tables_state::Open_tables_state(uint64_t version_arg)
 
102
  :version(version_arg), backups_available(false)
102
103
{
103
 
  open_tables= temporary_tables= derived_tables= NULL;
104
 
  extra_lock= lock= NULL;
 
104
  reset_open_tables_state();
105
105
}
106
106
 
107
107
/*
108
108
  The following functions form part of the C plugin API
109
109
*/
110
 
int tmpfile(const char *prefix)
 
110
extern "C" int mysql_tmpfile(const char *prefix)
111
111
{
112
112
  char filename[FN_REFLEN];
113
 
  int fd = internal::create_temp_file(filename, drizzle_tmpdir.c_str(), prefix, MYF(MY_WME));
 
113
  int fd = internal::create_temp_file(filename, drizzle_tmpdir, prefix, MYF(MY_WME));
114
114
  if (fd >= 0) {
115
115
    unlink(filename);
116
116
  }
118
118
  return fd;
119
119
}
120
120
 
121
 
void **Session::getEngineData(const plugin::MonitoredInTransaction *monitored)
122
 
{
123
 
  return static_cast<void **>(&ha_data[monitored->getId()].ha_ptr);
124
 
}
125
 
 
126
 
ResourceContext *Session::getResourceContext(const plugin::MonitoredInTransaction *monitored,
 
121
extern "C"
 
122
int session_tablespace_op(const Session *session)
 
123
{
 
124
  return test(session->tablespace_op);
 
125
}
 
126
 
 
127
/**
 
128
   Set the process info field of the Session structure.
 
129
 
 
130
   This function is used by plug-ins. Internally, the
 
131
   Session::set_proc_info() function should be used.
 
132
 
 
133
   @see Session::set_proc_info
 
134
 */
 
135
extern "C" void
 
136
set_session_proc_info(Session *session, const char *info)
 
137
{
 
138
  session->set_proc_info(info);
 
139
}
 
140
 
 
141
extern "C"
 
142
const char *get_session_proc_info(Session *session)
 
143
{
 
144
  return session->get_proc_info();
 
145
}
 
146
 
 
147
void **Session::getEngineData(const plugin::StorageEngine *engine)
 
148
{
 
149
  return static_cast<void **>(&ha_data[engine->slot].ha_ptr);
 
150
}
 
151
 
 
152
ResourceContext *Session::getResourceContext(const plugin::StorageEngine *engine,
127
153
                                             size_t index)
128
154
{
129
 
  return &ha_data[monitored->getId()].resource_context[index];
 
155
  return &ha_data[engine->getSlot()].resource_context[index];
130
156
}
131
157
 
 
158
extern "C"
132
159
int64_t session_test_options(const Session *session, int64_t test_options)
133
160
{
134
161
  return session->options & test_options;
135
162
}
136
163
 
137
 
Session::Session(plugin::Client *client_arg, catalog::Instance::shared_ptr catalog_arg) :
 
164
extern "C"
 
165
int session_sql_command(const Session *session)
 
166
{
 
167
  return (int) session->lex->sql_command;
 
168
}
 
169
 
 
170
extern "C"
 
171
int session_tx_isolation(const Session *session)
 
172
{
 
173
  return (int) session->variables.tx_isolation;
 
174
}
 
175
 
 
176
Session::Session(plugin::Client *client_arg)
 
177
  :
138
178
  Open_tables_state(refresh_version),
139
179
  mem_root(&main_mem_root),
140
 
  xa_id(0),
141
180
  lex(&main_lex),
142
 
  query(new std::string),
143
 
  _schema(new std::string("")),
 
181
  query(),
144
182
  client(client_arg),
145
183
  scheduler(NULL),
146
184
  scheduler_arg(NULL),
147
185
  lock_id(&main_lock_id),
148
 
  thread_stack(NULL),
149
 
  security_ctx(identifier::User::make_shared()),
150
 
  _where(Session::DEFAULT_WHERE),
151
 
  dbug_sentry(Session_SENTRY_MAGIC),
152
 
  mysys_var(0),
153
 
  command(COM_CONNECT),
154
 
  file_id(0),
155
 
  _epoch(boost::gregorian::date(1970,1,1)),
156
 
  _connect_time(boost::posix_time::microsec_clock::universal_time()),
157
 
  utime_after_lock(0),
158
 
  ha_data(plugin::num_trx_monitored_objects),
159
 
  query_id(0),
160
 
  warn_query_id(0),
161
 
  concurrent_execute_allowed(true),
 
186
  user_time(0),
162
187
  arg_of_last_insert_id_function(false),
163
188
  first_successful_insert_id_in_prev_stmt(0),
164
189
  first_successful_insert_id_in_cur_stmt(0),
165
190
  limit_found_rows(0),
166
 
  options(session_startup_options),
167
 
  row_count_func(-1),
168
 
  sent_row_count(0),
169
 
  examined_row_count(0),
170
 
  used_tables(0),
171
 
  total_warn_count(0),
172
 
  col_access(0),
173
 
  statement_id_counter(0),
174
 
  row_count(0),
175
 
  thread_id(0),
176
 
  tmp_table(0),
177
 
  _global_read_lock(NONE),
178
 
  count_cuted_fields(CHECK_FIELD_ERROR_FOR_NULL),
179
 
  _killed(NOT_KILLED),
 
191
  global_read_lock(0),
180
192
  some_tables_deleted(false),
181
193
  no_errors(false),
182
194
  password(false),
183
195
  is_fatal_error(false),
184
196
  transaction_rollback_request(false),
185
197
  is_fatal_sub_stmt_error(0),
 
198
  derived_tables_processing(false),
186
199
  tablespace_op(false),
187
 
  derived_tables_processing(false),
188
200
  m_lip(NULL),
189
201
  cached_table(0),
190
202
  transaction_message(NULL),
191
 
  statement_message(NULL),
192
 
  session_event_observers(NULL),
193
 
  _catalog(catalog_arg),
194
 
  use_usage(false)
 
203
  statement_message(NULL)
195
204
{
 
205
  memset(process_list_info, 0, PROCESS_LIST_WIDTH);
196
206
  client->setSession(this);
197
207
 
198
208
  /*
201
211
    will be re-initialized in init_for_queries().
202
212
  */
203
213
  memory::init_sql_alloc(&main_mem_root, memory::ROOT_MIN_BLOCK_SIZE, 0);
 
214
  thread_stack= NULL;
 
215
  count_cuted_fields= CHECK_FIELD_IGNORE;
 
216
  killed= NOT_KILLED;
 
217
  col_access= 0;
 
218
  tmp_table= 0;
 
219
  used_tables= 0;
204
220
  cuted_fields= sent_row_count= row_count= 0L;
 
221
  row_count_func= -1;
 
222
  statement_id_counter= 0UL;
205
223
  // Must be reset to handle error with Session's created for init of mysqld
206
224
  lex->current_select= 0;
 
225
  start_time=(time_t) 0;
 
226
  start_utime= 0L;
 
227
  utime_after_lock= 0L;
207
228
  memset(&variables, 0, sizeof(variables));
208
 
  scoreboard_index= -1;
209
 
  cleanup_done= abort_on_warning= no_warnings_for_error= false;  
210
 
 
211
 
  /* query_cache init */
212
 
  query_cache_key= "";
213
 
  resultset= NULL;
 
229
  thread_id= 0;
 
230
  file_id = 0;
 
231
  query_id= 0;
 
232
  warn_query_id= 0;
 
233
  memset(ha_data, 0, sizeof(ha_data));
 
234
  mysys_var= 0;
 
235
  dbug_sentry=Session_SENTRY_MAGIC;
 
236
  cleanup_done= abort_on_warning= no_warnings_for_error= false;
 
237
  pthread_mutex_init(&LOCK_delete, MY_MUTEX_INIT_FAST);
214
238
 
215
239
  /* Variables with default values */
216
240
  proc_info="login";
 
241
  where= Session::DEFAULT_WHERE;
 
242
  command= COM_CONNECT;
217
243
 
218
244
  plugin_sessionvar_init(this);
219
245
  /*
223
249
  */
224
250
  variables.pseudo_thread_id= thread_id;
225
251
  server_status= SERVER_STATUS_AUTOCOMMIT;
 
252
  options= session_startup_options;
226
253
 
227
254
  if (variables.max_join_size == HA_POS_ERROR)
228
255
    options |= OPTION_BIG_SELECTS;
234
261
  session_tx_isolation= (enum_tx_isolation) variables.tx_isolation;
235
262
  warn_list.empty();
236
263
  memset(warn_count, 0, sizeof(warn_count));
 
264
  total_warn_count= 0;
237
265
  memset(&status_var, 0, sizeof(status_var));
238
266
 
239
267
  /* Initialize sub structures */
240
268
  memory::init_sql_alloc(&warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE);
 
269
  hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0,
 
270
            (hash_get_key) get_var_key,
 
271
            (hash_free_key) free_user_var, 0);
241
272
 
242
273
  substitute_null_with_insert_id = false;
243
 
  lock_info.init(); /* safety: will be reset after start */
 
274
  thr_lock_info_init(&lock_info); /* safety: will be reset after start */
244
275
  thr_lock_owner_init(&main_lock_id, &lock_info);
245
276
 
246
277
  m_internal_handler= NULL;
247
 
  
248
 
  plugin::EventObserver::registerSessionEvents(*this); 
249
278
}
250
279
 
251
280
void Session::free_items()
269
298
  m_internal_handler= handler;
270
299
}
271
300
 
272
 
bool Session::handle_error(drizzled::error_t sql_errno, const char *message,
273
 
                           DRIZZLE_ERROR::enum_warning_level level)
 
301
bool Session::handle_error(uint32_t sql_errno, const char *message,
 
302
                       DRIZZLE_ERROR::enum_warning_level level)
274
303
{
275
304
  if (m_internal_handler)
276
305
  {
280
309
  return false;                                 // 'false', as per coding style
281
310
}
282
311
 
283
 
void Session::setAbort(bool arg)
284
 
{
285
 
  mysys_var->abort= arg;
286
 
}
287
 
 
288
 
void Session::lockOnSys()
289
 
{
290
 
  if (not mysys_var)
291
 
    return;
292
 
 
293
 
  setAbort(true);
294
 
  boost_unique_lock_t scopedLock(mysys_var->mutex);
295
 
  if (mysys_var->current_cond)
296
 
  {
297
 
    mysys_var->current_mutex->lock();
298
 
    mysys_var->current_cond->notify_all();
299
 
    mysys_var->current_mutex->unlock();
300
 
  }
301
 
}
302
 
 
303
312
void Session::pop_internal_handler()
304
313
{
305
314
  assert(m_internal_handler != NULL);
306
315
  m_internal_handler= NULL;
307
316
}
308
317
 
309
 
void Session::get_xid(DRIZZLE_XID *xid)
310
 
{
311
 
  *xid = *(DRIZZLE_XID *) &transaction.xid_state.xid;
312
 
}
 
318
#if defined(__cplusplus)
 
319
extern "C" {
 
320
#endif
 
321
 
 
322
void *session_alloc(Session *session, unsigned int size)
 
323
{
 
324
  return session->alloc(size);
 
325
}
 
326
 
 
327
void *session_calloc(Session *session, unsigned int size)
 
328
{
 
329
  return session->calloc(size);
 
330
}
 
331
 
 
332
char *session_strdup(Session *session, const char *str)
 
333
{
 
334
  return session->strdup(str);
 
335
}
 
336
 
 
337
char *session_strmake(Session *session, const char *str, unsigned int size)
 
338
{
 
339
  return session->strmake(str, size);
 
340
}
 
341
 
 
342
void *session_memdup(Session *session, const void* str, unsigned int size)
 
343
{
 
344
  return session->memdup(str, size);
 
345
}
 
346
 
 
347
void session_get_xid(const Session *session, DRIZZLE_XID *xid)
 
348
{
 
349
  *xid = *(DRIZZLE_XID *) &session->transaction.xid_state.xid;
 
350
}
 
351
 
 
352
#if defined(__cplusplus)
 
353
}
 
354
#endif
313
355
 
314
356
/* Do operations that may take a long time */
315
357
 
317
359
{
318
360
  assert(cleanup_done == false);
319
361
 
320
 
  setKilled(KILL_CONNECTION);
 
362
  killed= KILL_CONNECTION;
321
363
#ifdef ENABLE_WHEN_BINLOG_WILL_BE_ABLE_TO_PREPARE
322
364
  if (transaction.xid_state.xa_state == XA_PREPARED)
323
365
  {
326
368
#endif
327
369
  {
328
370
    TransactionServices &transaction_services= TransactionServices::singleton();
329
 
    transaction_services.rollbackTransaction(*this, true);
 
371
    transaction_services.ha_rollback_trans(this, true);
330
372
    xid_cache_delete(&transaction.xid_state);
331
373
  }
332
 
 
333
 
  for (UserVars::iterator iter= user_vars.begin();
334
 
       iter != user_vars.end();
335
 
       iter++)
336
 
  {
337
 
    user_var_entry *entry= (*iter).second;
338
 
    boost::checked_delete(entry);
339
 
  }
340
 
  user_vars.clear();
341
 
 
342
 
 
 
374
  hash_free(&user_vars);
343
375
  close_temporary_tables();
344
376
 
345
377
  if (global_read_lock)
346
 
  {
347
 
    unlockGlobalReadLock();
348
 
  }
 
378
    unlock_global_read_lock(this);
349
379
 
350
380
  cleanup_done= true;
351
381
}
352
382
 
353
383
Session::~Session()
354
384
{
355
 
  this->checkSentry();
 
385
  Session_CHECK_SENTRY(this);
 
386
  add_to_status(&global_status_var, &status_var);
356
387
 
357
 
  if (client and client->isConnected())
 
388
  if (client->isConnected())
358
389
  {
359
 
    assert(security_ctx);
360
390
    if (global_system_variables.log_warnings)
361
 
    {
362
 
      errmsg_printf(error::WARN, ER(ER_FORCING_CLOSE),
363
 
                    internal::my_progname,
364
 
                    thread_id,
365
 
                    security_ctx->username().c_str());
366
 
    }
367
 
 
368
 
    disconnect();
 
391
        errmsg_printf(ERRMSG_LVL_WARN, ER(ER_FORCING_CLOSE),internal::my_progname,
 
392
                      thread_id,
 
393
                      (getSecurityContext().getUser().c_str() ?
 
394
                       getSecurityContext().getUser().c_str() : ""));
 
395
    disconnect(0, false);
369
396
  }
370
397
 
371
398
  /* Close connection */
372
 
  if (client)
373
 
  {
374
 
    client->close();
375
 
    boost::checked_delete(client);
376
 
    client= NULL;
377
 
  }
 
399
  client->close();
 
400
  delete client;
378
401
 
379
402
  if (cleanup_done == false)
380
403
    cleanup();
382
405
  plugin::StorageEngine::closeConnection(this);
383
406
  plugin_sessionvar_cleanup(this);
384
407
 
385
 
  warn_root.free_root(MYF(0));
 
408
  free_root(&warn_root,MYF(0));
386
409
  mysys_var=0;                                  // Safety (shouldn't be needed)
387
410
  dbug_sentry= Session_SENTRY_GONE;
388
411
 
389
 
  main_mem_root.free_root(MYF(0));
390
 
  currentMemRoot().release();
391
 
  currentSession().release();
392
 
 
393
 
  plugin::Logging::postEndDo(this);
394
 
  plugin::EventObserver::deregisterSessionEvents(*this); 
395
 
}
396
 
 
397
 
void Session::setClient(plugin::Client *client_arg)
398
 
{
399
 
  client= client_arg;
400
 
  client->setSession(this);
401
 
}
402
 
 
403
 
void Session::awake(Session::killed_state_t state_to_set)
404
 
{
405
 
  if ((state_to_set == Session::KILL_QUERY) and (command == COM_SLEEP))
406
 
    return;
407
 
 
408
 
  this->checkSentry();
409
 
 
410
 
  setKilled(state_to_set);
411
 
  scheduler->killSession(this);
412
 
 
 
412
  free_root(&main_mem_root, MYF(0));
 
413
  pthread_setspecific(THR_Session,  0);
 
414
 
 
415
 
 
416
  /* Ensure that no one is using Session */
 
417
  pthread_mutex_unlock(&LOCK_delete);
 
418
  pthread_mutex_destroy(&LOCK_delete);
 
419
}
 
420
 
 
421
/*
 
422
  Add all status variables to another status variable array
 
423
 
 
424
  SYNOPSIS
 
425
   add_to_status()
 
426
   to_var       add to this array
 
427
   from_var     from this array
 
428
 
 
429
  NOTES
 
430
    This function assumes that all variables are long/ulong.
 
431
    If this assumption will change, then we have to explictely add
 
432
    the other variables after the while loop
 
433
*/
 
434
void add_to_status(system_status_var *to_var, system_status_var *from_var)
 
435
{
 
436
  ulong *end= (ulong*) ((unsigned char*) to_var +
 
437
                        offsetof(system_status_var, last_system_status_var) +
 
438
                        sizeof(ulong));
 
439
  ulong *to= (ulong*) to_var, *from= (ulong*) from_var;
 
440
 
 
441
  while (to != end)
 
442
    *(to++)+= *(from++);
 
443
}
 
444
 
 
445
/*
 
446
  Add the difference between two status variable arrays to another one.
 
447
 
 
448
  SYNOPSIS
 
449
    add_diff_to_status
 
450
    to_var       add to this array
 
451
    from_var     from this array
 
452
    dec_var      minus this array
 
453
 
 
454
  NOTE
 
455
    This function assumes that all variables are long/ulong.
 
456
*/
 
457
void add_diff_to_status(system_status_var *to_var, system_status_var *from_var,
 
458
                        system_status_var *dec_var)
 
459
{
 
460
  ulong *end= (ulong*) ((unsigned char*) to_var + offsetof(system_status_var,
 
461
                                                  last_system_status_var) +
 
462
                        sizeof(ulong));
 
463
  ulong *to= (ulong*) to_var, *from= (ulong*) from_var, *dec= (ulong*) dec_var;
 
464
 
 
465
  while (to != end)
 
466
    *(to++)+= *(from++) - *(dec++);
 
467
}
 
468
 
 
469
void Session::awake(Session::killed_state state_to_set)
 
470
{
 
471
  Session_CHECK_SENTRY(this);
 
472
  safe_mutex_assert_owner(&LOCK_delete);
 
473
 
 
474
  killed= state_to_set;
413
475
  if (state_to_set != Session::KILL_QUERY)
414
476
  {
 
477
    scheduler->killSession(this);
415
478
    DRIZZLE_CONNECTION_DONE(thread_id);
416
479
  }
417
 
 
418
480
  if (mysys_var)
419
481
  {
420
 
    boost_unique_lock_t scopedLock(mysys_var->mutex);
 
482
    pthread_mutex_lock(&mysys_var->mutex);
421
483
    /*
422
 
      "
423
484
      This broadcast could be up in the air if the victim thread
424
485
      exits the cond in the time between read and broadcast, but that is
425
486
      ok since all we want to do is to make the victim thread get out
440
501
    */
441
502
    if (mysys_var->current_cond && mysys_var->current_mutex)
442
503
    {
443
 
      mysys_var->current_mutex->lock();
444
 
      mysys_var->current_cond->notify_all();
445
 
      mysys_var->current_mutex->unlock();
 
504
      pthread_mutex_lock(mysys_var->current_mutex);
 
505
      pthread_cond_broadcast(mysys_var->current_cond);
 
506
      pthread_mutex_unlock(mysys_var->current_mutex);
446
507
    }
 
508
    pthread_mutex_unlock(&mysys_var->mutex);
447
509
  }
448
510
}
449
511
 
459
521
  */
460
522
  assert(thread_stack);
461
523
 
462
 
  currentSession().release();
463
 
  currentSession().reset(this);
464
 
 
465
 
  currentMemRoot().release();
466
 
  currentMemRoot().reset(&mem_root);
 
524
  if (pthread_setspecific(THR_Session,  this) ||
 
525
      pthread_setspecific(THR_Mem_root, &mem_root))
 
526
    return true;
467
527
 
468
528
  mysys_var=my_thread_var;
469
529
 
472
532
    This allows us to move Session to different threads if needed.
473
533
  */
474
534
  mysys_var->id= thread_id;
 
535
  real_id= pthread_self();                      // For debugging
475
536
 
476
537
  /*
477
538
    We have to call thr_lock_info_init() again here as Session may have been
478
539
    created in another thread
479
540
  */
480
 
  lock_info.init();
481
 
 
 
541
  thr_lock_info_init(&lock_info);
482
542
  return false;
483
543
}
484
544
 
498
558
  command= COM_SLEEP;
499
559
  set_time();
500
560
 
501
 
  mem_root->reset_root_defaults(variables.query_alloc_block_size,
502
 
                                variables.query_prealloc_size);
 
561
  reset_root_defaults(mem_root, variables.query_alloc_block_size,
 
562
                      variables.query_prealloc_size);
503
563
  transaction.xid_state.xid.null();
504
564
  transaction.xid_state.in_session=1;
505
 
  if (use_usage)
506
 
    resetUsage();
507
565
}
508
566
 
509
567
bool Session::initGlobals()
510
568
{
511
569
  if (storeGlobals())
512
570
  {
513
 
    disconnect(ER_OUT_OF_RESOURCES);
514
 
    status_var.aborted_connects++;
 
571
    disconnect(ER_OUT_OF_RESOURCES, true);
 
572
    statistic_increment(aborted_connects, &LOCK_status);
515
573
    return true;
516
574
  }
517
575
  return false;
521
579
{
522
580
  if (initGlobals() || authenticate())
523
581
  {
524
 
    disconnect();
 
582
    disconnect(0, true);
525
583
    return;
526
584
  }
527
585
 
528
586
  prepareForQueries();
529
587
 
530
 
  while (not client->haveError() && getKilled() != KILL_CONNECTION)
 
588
  while (! client->haveError() && killed != KILL_CONNECTION)
531
589
  {
532
 
    if (not executeStatement())
 
590
    if (! executeStatement())
533
591
      break;
534
592
  }
535
593
 
536
 
  disconnect();
 
594
  disconnect(0, true);
537
595
}
538
596
 
539
 
bool Session::schedule(Session::shared_ptr &arg)
 
597
bool Session::schedule()
540
598
{
541
 
  arg->scheduler= plugin::Scheduler::getScheduler();
542
 
  assert(arg->scheduler);
543
 
 
544
 
  ++connection_count;
545
 
 
546
 
  long current_connections= connection_count;
547
 
 
548
 
  if (current_connections > 0 and static_cast<uint64_t>(current_connections) > current_global_counters.max_used_connections)
549
 
  {
550
 
    current_global_counters.max_used_connections= static_cast<uint64_t>(connection_count);
551
 
  }
552
 
 
553
 
  current_global_counters.connections++;
554
 
  arg->thread_id= arg->variables.pseudo_thread_id= global_thread_id++;
555
 
 
556
 
  session::Cache::singleton().insert(arg);
557
 
 
558
 
  if (unlikely(plugin::EventObserver::connectSession(*arg)))
559
 
  {
560
 
    // We should do something about an error...
561
 
  }
562
 
 
563
 
  if (plugin::Scheduler::getScheduler()->addSession(arg))
564
 
  {
565
 
    DRIZZLE_CONNECTION_START(arg->getSessionId());
 
599
  scheduler= plugin::Scheduler::getScheduler();
 
600
  assert(scheduler);
 
601
 
 
602
  connection_count.increment();
 
603
 
 
604
  if (connection_count > max_used_connections)
 
605
    max_used_connections= connection_count;
 
606
 
 
607
  thread_id= variables.pseudo_thread_id= global_thread_id++;
 
608
 
 
609
  pthread_mutex_lock(&LOCK_thread_count);
 
610
  getSessionList().push_back(this);
 
611
  pthread_mutex_unlock(&LOCK_thread_count);
 
612
 
 
613
  if (scheduler->addSession(this))
 
614
  {
 
615
    DRIZZLE_CONNECTION_START(thread_id);
566
616
    char error_message_buff[DRIZZLE_ERRMSG_SIZE];
567
617
 
568
 
    arg->setKilled(Session::KILL_CONNECTION);
 
618
    killed= Session::KILL_CONNECTION;
569
619
 
570
 
    arg->status_var.aborted_connects++;
 
620
    statistic_increment(aborted_connects, &LOCK_status);
571
621
 
572
622
    /* Can't use my_error() since store_globals has not been called. */
573
623
    /* TODO replace will better error message */
574
624
    snprintf(error_message_buff, sizeof(error_message_buff),
575
625
             ER(ER_CANT_CREATE_THREAD), 1);
576
 
    arg->client->sendError(ER_CANT_CREATE_THREAD, error_message_buff);
577
 
 
 
626
    client->sendError(ER_CANT_CREATE_THREAD, error_message_buff);
578
627
    return true;
579
628
  }
580
629
 
582
631
}
583
632
 
584
633
 
585
 
/*
586
 
  Is this session viewable by the current user?
587
 
*/
588
 
bool Session::isViewable(identifier::User::const_reference user_arg) const
589
 
{
590
 
  return plugin::Authorization::isAuthorized(user_arg, this, false);
591
 
}
592
 
 
593
 
 
594
 
const char* Session::enter_cond(boost::condition_variable_any &cond, boost::mutex &mutex, const char* msg)
 
634
const char* Session::enter_cond(pthread_cond_t *cond,
 
635
                                pthread_mutex_t* mutex,
 
636
                                const char* msg)
595
637
{
596
638
  const char* old_msg = get_proc_info();
597
639
  safe_mutex_assert_owner(mutex);
598
 
  mysys_var->current_mutex = &mutex;
599
 
  mysys_var->current_cond = &cond;
 
640
  mysys_var->current_mutex = mutex;
 
641
  mysys_var->current_cond = cond;
600
642
  this->set_proc_info(msg);
601
643
  return old_msg;
602
644
}
609
651
    locked (if that would not be the case, you'll get a deadlock if someone
610
652
    does a Session::awake() on you).
611
653
  */
612
 
  mysys_var->current_mutex->unlock();
613
 
  boost_unique_lock_t scopedLock(mysys_var->mutex);
 
654
  pthread_mutex_unlock(mysys_var->current_mutex);
 
655
  pthread_mutex_lock(&mysys_var->mutex);
614
656
  mysys_var->current_mutex = 0;
615
657
  mysys_var->current_cond = 0;
616
658
  this->set_proc_info(old_msg);
 
659
  pthread_mutex_unlock(&mysys_var->mutex);
617
660
}
618
661
 
619
662
bool Session::authenticate()
620
663
{
 
664
  lex_start(this);
621
665
  if (client->authenticate())
622
666
    return false;
623
667
 
624
 
  status_var.aborted_connects++;
625
 
 
 
668
  statistic_increment(aborted_connects, &LOCK_status);
626
669
  return true;
627
670
}
628
671
 
629
 
bool Session::checkUser(const std::string &passwd_str,
630
 
                        const std::string &in_db)
 
672
bool Session::checkUser(const char *passwd, uint32_t passwd_len, const char *in_db)
631
673
{
632
 
  bool is_authenticated=
633
 
    plugin::Authentication::isAuthenticated(user(), passwd_str);
 
674
  LEX_STRING db_str= { (char *) in_db, in_db ? strlen(in_db) : 0 };
 
675
  bool is_authenticated;
 
676
 
 
677
  if (passwd_len != 0 && passwd_len != SCRAMBLE_LENGTH)
 
678
  {
 
679
    my_error(ER_HANDSHAKE_ERROR, MYF(0), getSecurityContext().getIp().c_str());
 
680
    return false;
 
681
  }
 
682
 
 
683
  is_authenticated= plugin::Authentication::isAuthenticated(this, passwd);
634
684
 
635
685
  if (is_authenticated != true)
636
686
  {
637
 
    status_var.access_denied++;
638
 
    /* isAuthenticated has pushed the error message */
 
687
    my_error(ER_ACCESS_DENIED_ERROR, MYF(0),
 
688
             getSecurityContext().getUser().c_str(),
 
689
             getSecurityContext().getIp().c_str(),
 
690
             passwd_len ? ER(ER_YES) : ER(ER_NO));
 
691
 
639
692
    return false;
640
693
  }
641
694
 
642
695
  /* Change database if necessary */
643
 
  if (not in_db.empty())
 
696
  if (in_db && in_db[0])
644
697
  {
645
 
    identifier::Schema identifier(in_db);
646
 
    if (change_db(this, identifier))
 
698
    if (mysql_change_db(this, &db_str, false))
647
699
    {
648
 
      /* change_db() has pushed the error message. */
 
700
      /* mysql_change_db() has pushed the error message. */
649
701
      return false;
650
702
    }
651
703
  }
652
704
  my_ok();
653
 
  password= not passwd_str.empty();
 
705
  password= test(passwd_len);          // remember for error messages
654
706
 
655
707
  /* Ready to handle queries */
656
708
  return true;
672
724
  main_da.reset_diagnostics_area();
673
725
 
674
726
  if (client->readCommand(&l_packet, &packet_length) == false)
675
 
  {
676
 
    return false;
677
 
  }
678
 
 
679
 
  if (getKilled() == KILL_CONNECTION)
680
727
    return false;
681
728
 
682
729
  if (packet_length == 0)
683
730
    return true;
684
731
 
685
 
  l_command= static_cast<enum_server_command>(l_packet[0]);
 
732
  l_command= (enum enum_server_command) (unsigned char) l_packet[0];
686
733
 
687
734
  if (command >= COM_END)
688
735
    command= COM_END;                           // Wrong command
689
736
 
690
737
  assert(packet_length);
691
 
  return not dispatch_command(l_command, this, l_packet+1, (uint32_t) (packet_length-1));
 
738
  return ! dispatch_command(l_command, this, l_packet+1, (uint32_t) (packet_length-1));
692
739
}
693
740
 
694
741
bool Session::readAndStoreQuery(const char *in_packet, uint32_t in_packet_length)
700
747
    in_packet_length--;
701
748
  }
702
749
  const char *pos= in_packet + in_packet_length; /* Point at end null */
703
 
  while (in_packet_length > 0 && (pos[-1] == ';' || my_isspace(charset() ,pos[-1])))
 
750
  while (in_packet_length > 0 &&
 
751
         (pos[-1] == ';' || my_isspace(charset() ,pos[-1])))
704
752
  {
705
753
    pos--;
706
754
    in_packet_length--;
707
755
  }
708
756
 
709
 
  std::string *new_query= new std::string(in_packet, in_packet + in_packet_length);
710
 
  // We can not be entirely sure _schema has a value
711
 
  if (_schema)
712
 
  {
713
 
    plugin::QueryRewriter::rewriteQuery(*_schema, *new_query);
714
 
  }
715
 
  query.reset(new_query);
716
 
  _state.reset(new session::State(in_packet, in_packet_length));
 
757
  query.assign(in_packet, in_packet + in_packet_length);
717
758
 
718
759
  return true;
719
760
}
738
779
       * (Which of course should never happen...)
739
780
       */
740
781
      server_status&= ~SERVER_STATUS_IN_TRANS;
741
 
      if (transaction_services.commitTransaction(*this, true))
 
782
      if (transaction_services.ha_commit_trans(this, true))
742
783
        result= false;
743
784
      options&= ~(OPTION_BEGIN);
744
785
      break;
755
796
    case ROLLBACK_AND_CHAIN:
756
797
    {
757
798
      server_status&= ~SERVER_STATUS_IN_TRANS;
758
 
      if (transaction_services.rollbackTransaction(*this, true))
 
799
      if (transaction_services.ha_rollback_trans(this, true))
759
800
        result= false;
760
801
      options&= ~(OPTION_BEGIN);
761
802
      if (result == true && (completion == ROLLBACK_AND_CHAIN))
768
809
  }
769
810
 
770
811
  if (result == false)
771
 
  {
772
 
    my_error(static_cast<drizzled::error_t>(killed_errno()), MYF(0));
773
 
  }
 
812
    my_error(killed_errno(), MYF(0));
774
813
  else if ((result == true) && do_release)
775
 
  {
776
 
    setKilled(Session::KILL_CONNECTION);
777
 
  }
 
814
    killed= Session::KILL_CONNECTION;
778
815
 
779
816
  return result;
780
817
}
792
829
  if (options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
793
830
  {
794
831
    server_status&= ~SERVER_STATUS_IN_TRANS;
795
 
    if (transaction_services.commitTransaction(*this, true))
 
832
    if (transaction_services.ha_commit_trans(this, true))
796
833
      result= false;
797
834
  }
798
835
  options&= ~(OPTION_BEGIN);
803
840
{
804
841
  bool result= true;
805
842
 
806
 
  assert(! inTransaction());
807
 
 
808
 
  options|= OPTION_BEGIN;
809
 
  server_status|= SERVER_STATUS_IN_TRANS;
810
 
 
811
 
  if (plugin::TransactionalStorageEngine::notifyStartTransaction(this, opt))
 
843
  if (! endActiveTransaction())
812
844
  {
813
845
    result= false;
814
846
  }
 
847
  else
 
848
  {
 
849
    options|= OPTION_BEGIN;
 
850
    server_status|= SERVER_STATUS_IN_TRANS;
 
851
 
 
852
    if (opt == START_TRANS_OPT_WITH_CONS_SNAPSHOT)
 
853
    {
 
854
      if (plugin::TransactionalStorageEngine::startConsistentSnapshot(this))
 
855
      {
 
856
        result= false;
 
857
      }
 
858
    }
 
859
  }
815
860
 
816
861
  return result;
817
862
}
833
878
    first_successful_insert_id_in_cur_stmt= 0;
834
879
    substitute_null_with_insert_id= true;
835
880
  }
836
 
 
837
881
  arg_of_last_insert_id_function= false;
838
 
 
839
882
  /* Free Items that were created during this execution */
840
883
  free_items();
841
 
 
842
 
  /* Reset _where. */
843
 
  _where= Session::DEFAULT_WHERE;
844
 
 
845
 
  /* Reset the temporary shares we built */
846
 
  for_each(temporary_shares.begin(),
847
 
           temporary_shares.end(),
848
 
           DeletePtr());
849
 
  temporary_shares.clear();
 
884
  /* Reset where. */
 
885
  where= Session::DEFAULT_WHERE;
850
886
}
851
887
 
852
888
/**
871
907
                                     bool allocate_lex_string)
872
908
{
873
909
  if (allocate_lex_string)
874
 
    if (!(lex_str= (LEX_STRING *)getMemRoot()->allocate(sizeof(LEX_STRING))))
 
910
    if (!(lex_str= (LEX_STRING *)alloc(sizeof(LEX_STRING))))
875
911
      return 0;
876
 
  if (!(lex_str->str= mem_root->strmake_root(str, length)))
 
912
  if (!(lex_str->str= strmake_root(mem_root, str, length)))
877
913
    return 0;
878
914
  lex_str->length= length;
879
915
  return lex_str;
917
953
  return (result->send_fields(field_list));
918
954
}
919
955
 
920
 
void select_result::send_error(drizzled::error_t errcode, const char *err)
 
956
void select_result::send_error(uint32_t errcode, const char *err)
921
957
{
922
958
  my_message(errcode, err, MYF(0));
923
959
}
926
962
  Handling writing to file
927
963
************************************************************************/
928
964
 
929
 
void select_to_file::send_error(drizzled::error_t errcode,const char *err)
 
965
void select_to_file::send_error(uint32_t errcode,const char *err)
930
966
{
931
967
  my_message(errcode, err, MYF(0));
932
968
  if (file > 0)
933
969
  {
934
 
    (void) cache->end_io_cache();
 
970
    (void) end_io_cache(cache);
935
971
    (void) internal::my_close(file, MYF(0));
936
 
    (void) internal::my_delete(path.file_string().c_str(), MYF(0));             // Delete file on error
 
972
    (void) internal::my_delete(path, MYF(0));           // Delete file on error
937
973
    file= -1;
938
974
  }
939
975
}
941
977
 
942
978
bool select_to_file::send_eof()
943
979
{
944
 
  int error= test(cache->end_io_cache());
 
980
  int error= test(end_io_cache(cache));
945
981
  if (internal::my_close(file, MYF(MY_WME)))
946
982
    error= 1;
947
983
  if (!error)
963
999
  /* In case of error send_eof() may be not called: close the file here. */
964
1000
  if (file >= 0)
965
1001
  {
966
 
    (void) cache->end_io_cache();
 
1002
    (void) end_io_cache(cache);
967
1003
    (void) internal::my_close(file, MYF(0));
968
1004
    file= -1;
969
1005
  }
970
 
  path= "";
 
1006
  path[0]= '\0';
971
1007
  row_count= 0;
972
1008
}
973
1009
 
977
1013
    cache(static_cast<internal::IO_CACHE *>(memory::sql_calloc(sizeof(internal::IO_CACHE)))),
978
1014
    row_count(0L)
979
1015
{
980
 
  path= "";
 
1016
  path[0]=0;
981
1017
}
982
1018
 
983
1019
select_to_file::~select_to_file()
1011
1047
*/
1012
1048
 
1013
1049
 
1014
 
static int create_file(Session *session,
1015
 
                       fs::path &target_path,
1016
 
                       file_exchange *exchange,
1017
 
                       internal::IO_CACHE *cache)
 
1050
static int create_file(Session *session, char *path, file_exchange *exchange, internal::IO_CACHE *cache)
1018
1051
{
1019
 
  fs::path to_file(exchange->file_name);
1020
1052
  int file;
1021
 
 
1022
 
  if (not to_file.has_root_directory())
 
1053
  uint32_t option= MY_UNPACK_FILENAME | MY_RELATIVE_PATH;
 
1054
 
 
1055
#ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS
 
1056
  option|= MY_REPLACE_DIR;                      // Force use of db directory
 
1057
#endif
 
1058
 
 
1059
  if (!internal::dirname_length(exchange->file_name))
1023
1060
  {
1024
 
    target_path= fs::system_complete(getDataHomeCatalog());
1025
 
    util::string::const_shared_ptr schema(session->schema());
1026
 
    if (schema and not schema->empty())
1027
 
    {
1028
 
      int count_elements= 0;
1029
 
      for (fs::path::iterator iter= to_file.begin();
1030
 
           iter != to_file.end();
1031
 
           ++iter, ++count_elements)
1032
 
      { }
1033
 
 
1034
 
      if (count_elements == 1)
1035
 
      {
1036
 
        target_path /= *schema;
1037
 
      }
1038
 
    }
1039
 
    target_path /= to_file;
 
1061
    strcpy(path, drizzle_real_data_home);
 
1062
    if (! session->db.empty())
 
1063
      strncat(path, session->db.c_str(), FN_REFLEN-strlen(drizzle_real_data_home)-1);
 
1064
    (void) internal::fn_format(path, exchange->file_name, path, "", option);
1040
1065
  }
1041
1066
  else
1042
 
  {
1043
 
    target_path = exchange->file_name;
1044
 
  }
1045
 
 
1046
 
  if (not secure_file_priv.string().empty())
1047
 
  {
1048
 
    if (target_path.file_string().substr(0, secure_file_priv.file_string().size()) != secure_file_priv.file_string())
1049
 
    {
1050
 
      /* Write only allowed to dir or subdir specified by secure_file_priv */
1051
 
      my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
1052
 
      return -1;
1053
 
    }
1054
 
  }
1055
 
 
1056
 
  if (!access(target_path.file_string().c_str(), F_OK))
 
1067
    (void) internal::fn_format(path, exchange->file_name, drizzle_real_data_home, "", option);
 
1068
 
 
1069
  if (opt_secure_file_priv &&
 
1070
      strncmp(opt_secure_file_priv, path, strlen(opt_secure_file_priv)))
 
1071
  {
 
1072
    /* Write only allowed to dir or subdir specified by secure_file_priv */
 
1073
    my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
 
1074
    return -1;
 
1075
  }
 
1076
 
 
1077
  if (!access(path, F_OK))
1057
1078
  {
1058
1079
    my_error(ER_FILE_EXISTS_ERROR, MYF(0), exchange->file_name);
1059
1080
    return -1;
1060
1081
  }
1061
1082
  /* Create the file world readable */
1062
 
  if ((file= internal::my_create(target_path.file_string().c_str(), 0666, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0)
 
1083
  if ((file= internal::my_create(path, 0666, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0)
1063
1084
    return file;
1064
1085
  (void) fchmod(file, 0666);                    // Because of umask()
1065
 
  if (cache->init_io_cache(file, 0L, internal::WRITE_CACHE, 0L, 1, MYF(MY_WME)))
 
1086
  if (init_io_cache(cache, file, 0L, internal::WRITE_CACHE, 0L, 1, MYF(MY_WME)))
1066
1087
  {
1067
1088
    internal::my_close(file, MYF(0));
1068
 
    internal::my_delete(target_path.file_string().c_str(), MYF(0));  // Delete file on error, it was just created
 
1089
    internal::my_delete(path, MYF(0));  // Delete file on error, it was just created
1069
1090
    return -1;
1070
1091
  }
1071
1092
  return file;
1079
1100
  bool string_results= false, non_string_results= false;
1080
1101
  unit= u;
1081
1102
  if ((uint32_t) strlen(exchange->file_name) + NAME_LEN >= FN_REFLEN)
1082
 
  {
1083
 
    path= exchange->file_name;
1084
 
  }
 
1103
    strncpy(path,exchange->file_name,FN_REFLEN-1);
1085
1104
 
1086
1105
  /* Check if there is any blobs in data */
1087
1106
  {
1091
1110
    {
1092
1111
      if (item->max_length >= MAX_BLOB_WIDTH)
1093
1112
      {
1094
 
        blob_flag=1;
1095
 
        break;
 
1113
        blob_flag=1;
 
1114
        break;
1096
1115
      }
1097
 
 
1098
1116
      if (item->result_type() == STRING_RESULT)
1099
1117
        string_results= true;
1100
1118
      else
1135
1153
  return 0;
1136
1154
}
1137
1155
 
 
1156
 
 
1157
#define NEED_ESCAPING(x) ((int) (unsigned char) (x) == escape_char    || \
 
1158
                          (enclosed ? (int) (unsigned char) (x) == field_sep_char      \
 
1159
                                    : (int) (unsigned char) (x) == field_term_char) || \
 
1160
                          (int) (unsigned char) (x) == line_sep_char  || \
 
1161
                          !(x))
 
1162
 
1138
1163
bool select_export::send_data(List<Item> &items)
1139
1164
{
1140
1165
  char buff[MAX_FIELD_WIDTH],null_buff[2],space[MAX_FIELD_WIDTH];
1145
1170
  if (unit->offset_limit_cnt)
1146
1171
  {                                             // using limit offset,count
1147
1172
    unit->offset_limit_cnt--;
1148
 
    return false;
 
1173
    return(0);
1149
1174
  }
1150
1175
  row_count++;
1151
1176
  Item *item;
1154
1179
 
1155
1180
  if (my_b_write(cache,(unsigned char*) exchange->line_start->ptr(),
1156
1181
                 exchange->line_start->length()))
1157
 
    return true;
1158
 
 
 
1182
    goto err;
1159
1183
  while ((item=li++))
1160
1184
  {
1161
1185
    Item_result result_type=item->result_type();
1166
1190
    {
1167
1191
      if (my_b_write(cache,(unsigned char*) exchange->enclosed->ptr(),
1168
1192
                     exchange->enclosed->length()))
1169
 
        return true;
 
1193
        goto err;
1170
1194
    }
1171
1195
    if (!res)
1172
1196
    {                                           // NULL
1177
1201
          null_buff[0]=escape_char;
1178
1202
          null_buff[1]='N';
1179
1203
          if (my_b_write(cache,(unsigned char*) null_buff,2))
1180
 
            return true;
 
1204
            goto err;
1181
1205
        }
1182
1206
        else if (my_b_write(cache,(unsigned char*) "NULL",4))
1183
 
          return true;
 
1207
          goto err;
1184
1208
      }
1185
1209
      else
1186
1210
      {
1190
1214
    else
1191
1215
    {
1192
1216
      if (fixed_row_size)
1193
 
        used_length= min(res->length(), static_cast<size_t>(item->max_length));
 
1217
        used_length= min(res->length(),item->max_length);
1194
1218
      else
1195
1219
        used_length= res->length();
1196
1220
 
1252
1276
            assert before the loop makes that sure.
1253
1277
          */
1254
1278
 
1255
 
          if ((needs_escaping(*pos, enclosed) ||
 
1279
          if ((NEED_ESCAPING(*pos) ||
1256
1280
               (check_second_byte &&
1257
1281
                my_mbcharlen(character_set_client, (unsigned char) *pos) == 2 &&
1258
1282
                pos + 1 < end &&
1259
 
                needs_escaping(pos[1], enclosed))) &&
 
1283
                NEED_ESCAPING(pos[1]))) &&
1260
1284
              /*
1261
1285
                Don't escape field_term_char by doubling - doubling is only
1262
1286
                valid for ENCLOSED BY characters:
1271
1295
            tmp_buff[1]= *pos ? *pos : '0';
1272
1296
            if (my_b_write(cache,(unsigned char*) start,(uint32_t) (pos-start)) ||
1273
1297
                my_b_write(cache,(unsigned char*) tmp_buff,2))
1274
 
              return true;
 
1298
              goto err;
1275
1299
            start=pos+1;
1276
1300
          }
1277
1301
        }
1278
1302
        if (my_b_write(cache,(unsigned char*) start,(uint32_t) (pos-start)))
1279
 
          return true;
 
1303
          goto err;
1280
1304
      }
1281
1305
      else if (my_b_write(cache,(unsigned char*) res->ptr(),used_length))
1282
 
        return true;
 
1306
        goto err;
1283
1307
    }
1284
1308
    if (fixed_row_size)
1285
1309
    {                                           // Fill with space
1295
1319
        for (; length > sizeof(space) ; length-=sizeof(space))
1296
1320
        {
1297
1321
          if (my_b_write(cache,(unsigned char*) space,sizeof(space)))
1298
 
            return true;
 
1322
            goto err;
1299
1323
        }
1300
1324
        if (my_b_write(cache,(unsigned char*) space,length))
1301
 
          return true;
 
1325
          goto err;
1302
1326
      }
1303
1327
    }
1304
1328
    if (res && enclosed)
1305
1329
    {
1306
1330
      if (my_b_write(cache, (unsigned char*) exchange->enclosed->ptr(),
1307
1331
                     exchange->enclosed->length()))
1308
 
        return true;
 
1332
        goto err;
1309
1333
    }
1310
1334
    if (--items_left)
1311
1335
    {
1312
1336
      if (my_b_write(cache, (unsigned char*) exchange->field_term->ptr(),
1313
1337
                     field_term_length))
1314
 
        return true;
 
1338
        goto err;
1315
1339
    }
1316
1340
  }
1317
1341
  if (my_b_write(cache,(unsigned char*) exchange->line_term->ptr(),
1318
1342
                 exchange->line_term->length()))
1319
 
  {
1320
 
    return true;
1321
 
  }
1322
 
 
1323
 
  return false;
 
1343
    goto err;
 
1344
  return(0);
 
1345
err:
 
1346
  return(1);
1324
1347
}
1325
1348
 
1326
1349
 
1353
1376
  if (row_count++ > 1)
1354
1377
  {
1355
1378
    my_message(ER_TOO_MANY_ROWS, ER(ER_TOO_MANY_ROWS), MYF(0));
1356
 
    return 1;
 
1379
    goto err;
1357
1380
  }
1358
1381
  while ((item=li++))
1359
1382
  {
1361
1384
    if (!res)                                   // If NULL
1362
1385
    {
1363
1386
      if (my_b_write(cache,(unsigned char*) "",1))
1364
 
        return 1;
 
1387
        goto err;
1365
1388
    }
1366
1389
    else if (my_b_write(cache,(unsigned char*) res->ptr(),res->length()))
1367
1390
    {
1368
 
      my_error(ER_ERROR_ON_WRITE, MYF(0), path.file_string().c_str(), errno);
1369
 
      return 1;
 
1391
      my_error(ER_ERROR_ON_WRITE, MYF(0), path, errno);
 
1392
      goto err;
1370
1393
    }
1371
1394
  }
1372
1395
  return(0);
 
1396
err:
 
1397
  return(1);
1373
1398
}
1374
1399
 
1375
1400
 
1427
1452
      switch (val_item->result_type())
1428
1453
      {
1429
1454
      case REAL_RESULT:
1430
 
        op= &select_max_min_finder_subselect::cmp_real;
1431
 
        break;
 
1455
        op= &select_max_min_finder_subselect::cmp_real;
 
1456
        break;
1432
1457
      case INT_RESULT:
1433
 
        op= &select_max_min_finder_subselect::cmp_int;
1434
 
        break;
 
1458
        op= &select_max_min_finder_subselect::cmp_int;
 
1459
        break;
1435
1460
      case STRING_RESULT:
1436
 
        op= &select_max_min_finder_subselect::cmp_str;
1437
 
        break;
 
1461
        op= &select_max_min_finder_subselect::cmp_str;
 
1462
        break;
1438
1463
      case DECIMAL_RESULT:
1439
1464
        op= &select_max_min_finder_subselect::cmp_decimal;
1440
1465
        break;
1441
1466
      case ROW_RESULT:
1442
1467
        // This case should never be choosen
1443
 
        assert(0);
1444
 
        op= 0;
 
1468
        assert(0);
 
1469
        op= 0;
1445
1470
      }
1446
1471
    }
1447
1472
    cache->store(val_item);
1480
1505
bool select_max_min_finder_subselect::cmp_decimal()
1481
1506
{
1482
1507
  Item *maxmin= ((Item_singlerow_subselect *)item)->element_index(0);
1483
 
  type::Decimal cval, *cvalue= cache->val_decimal(&cval);
1484
 
  type::Decimal mval, *mvalue= maxmin->val_decimal(&mval);
 
1508
  my_decimal cval, *cvalue= cache->val_decimal(&cval);
 
1509
  my_decimal mval, *mvalue= maxmin->val_decimal(&mval);
1485
1510
  if (fmax)
1486
1511
    return (cache->null_value && !maxmin->null_value) ||
1487
1512
      (!cache->null_value && !maxmin->null_value &&
1488
 
       class_decimal_cmp(cvalue, mvalue) > 0) ;
 
1513
       my_decimal_cmp(cvalue, mvalue) > 0) ;
1489
1514
  return (maxmin->null_value && !cache->null_value) ||
1490
1515
    (!cache->null_value && !maxmin->null_value &&
1491
 
     class_decimal_cmp(cvalue,mvalue) < 0);
 
1516
     my_decimal_cmp(cvalue,mvalue) < 0);
1492
1517
}
1493
1518
 
1494
1519
bool select_max_min_finder_subselect::cmp_str()
1530
1555
void Session::end_statement()
1531
1556
{
1532
1557
  /* Cleanup SQL processing state to reuse this statement in next query. */
1533
 
  lex->end();
1534
 
  query_cache_key= ""; // reset the cache key
1535
 
  resetResultsetMessage();
 
1558
  lex_end(lex);
1536
1559
}
1537
1560
 
1538
1561
bool Session::copy_db_to(char **p_db, size_t *p_db_length)
1539
1562
{
1540
 
  assert(_schema);
1541
 
  if (_schema and _schema->empty())
1542
 
  {
1543
 
    my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
1544
 
    return true;
1545
 
  }
1546
 
  else if (not _schema)
1547
 
  {
1548
 
    my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
1549
 
    return true;
1550
 
  }
1551
 
  assert(_schema);
1552
 
 
1553
 
  *p_db= strmake(_schema->c_str(), _schema->size());
1554
 
  *p_db_length= _schema->size();
1555
 
 
 
1563
  if (db.empty())
 
1564
  {
 
1565
    my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
 
1566
    return true;
 
1567
  }
 
1568
  *p_db= strmake(db.c_str(), db.length());
 
1569
  *p_db_length= db.length();
1556
1570
  return false;
1557
1571
}
1558
1572
 
1574
1588
  /* Fix for Intel compiler */
1575
1589
  if (copy_field)
1576
1590
  {
1577
 
    boost::checked_array_delete(copy_field);
1578
 
    save_copy_field= save_copy_field_end= copy_field= copy_field_end= 0;
 
1591
    delete [] copy_field;
 
1592
    save_copy_field= copy_field= 0;
1579
1593
  }
1580
1594
}
1581
1595
 
1582
1596
void Session::send_kill_message() const
1583
1597
{
1584
 
  drizzled::error_t err= static_cast<drizzled::error_t>(killed_errno());
1585
 
  if (err != EE_OK)
 
1598
  int err= killed_errno();
 
1599
  if (err)
1586
1600
    my_message(err, ER(err), MYF(0));
1587
1601
}
1588
1602
 
1592
1606
}
1593
1607
 
1594
1608
 
1595
 
void Session::set_db(const std::string &new_db)
 
1609
/****************************************************************************
 
1610
  Handling of open and locked tables states.
 
1611
 
 
1612
  This is used when we want to open/lock (and then close) some tables when
 
1613
  we already have a set of tables open and locked. We use these methods for
 
1614
  access to mysql.proc table to find definitions of stored routines.
 
1615
****************************************************************************/
 
1616
 
 
1617
void Session::reset_n_backup_open_tables_state(Open_tables_state *backup)
 
1618
{
 
1619
  backup->set_open_tables_state(this);
 
1620
  reset_open_tables_state();
 
1621
  backups_available= false;
 
1622
}
 
1623
 
 
1624
 
 
1625
void Session::restore_backup_open_tables_state(Open_tables_state *backup)
 
1626
{
 
1627
  /*
 
1628
    Before we will throw away current open tables state we want
 
1629
    to be sure that it was properly cleaned up.
 
1630
  */
 
1631
  assert(open_tables == 0 && temporary_tables == 0 &&
 
1632
              derived_tables == 0 &&
 
1633
              lock == 0);
 
1634
  set_open_tables_state(backup);
 
1635
}
 
1636
 
 
1637
bool Session::set_db(const char *new_db, size_t length)
1596
1638
{
1597
1639
  /* Do not reallocate memory if current chunk is big enough. */
1598
 
  if (new_db.length())
1599
 
  {
1600
 
    _schema.reset(new std::string(new_db));
1601
 
  }
 
1640
  if (length)
 
1641
    db= new_db;
1602
1642
  else
1603
 
  {
1604
 
    _schema.reset(new std::string(""));
1605
 
  }
1606
 
}
1607
 
 
 
1643
    db.clear();
 
1644
 
 
1645
  return false;
 
1646
}
 
1647
 
 
1648
 
 
1649
 
 
1650
 
 
1651
/**
 
1652
  Check the killed state of a user thread
 
1653
  @param session  user thread
 
1654
  @retval 0 the user thread is active
 
1655
  @retval 1 the user thread has been killed
 
1656
*/
 
1657
extern "C" int session_killed(const Session *session)
 
1658
{
 
1659
  return(session->killed);
 
1660
}
 
1661
 
 
1662
/**
 
1663
  Return the session id of a user session
 
1664
  @param pointer to Session object
 
1665
  @return session's id
 
1666
*/
 
1667
extern "C" unsigned long session_get_thread_id(const Session *session)
 
1668
{
 
1669
  return (unsigned long) session->getSessionId();
 
1670
}
 
1671
 
 
1672
 
 
1673
const struct charset_info_st *session_charset(Session *session)
 
1674
{
 
1675
  return(session->charset());
 
1676
}
 
1677
 
 
1678
int session_non_transactional_update(const Session *session)
 
1679
{
 
1680
  return(session->transaction.all.hasModifiedNonTransData());
 
1681
}
 
1682
 
 
1683
void session_mark_transaction_to_rollback(Session *session, bool all)
 
1684
{
 
1685
  mark_transaction_to_rollback(session, all);
 
1686
}
1608
1687
 
1609
1688
/**
1610
1689
  Mark transaction to rollback and mark error as fatal to a sub-statement.
1612
1691
  @param  session   Thread handle
1613
1692
  @param  all   true <=> rollback main transaction.
1614
1693
*/
1615
 
void Session::markTransactionForRollback(bool all)
 
1694
void mark_transaction_to_rollback(Session *session, bool all)
1616
1695
{
1617
 
  is_fatal_sub_stmt_error= true;
1618
 
  transaction_rollback_request= all;
 
1696
  if (session)
 
1697
  {
 
1698
    session->is_fatal_sub_stmt_error= true;
 
1699
    session->transaction_rollback_request= all;
 
1700
  }
1619
1701
}
1620
1702
 
1621
 
void Session::disconnect(enum error_t errcode)
 
1703
void Session::disconnect(uint32_t errcode, bool should_lock)
1622
1704
{
1623
1705
  /* Allow any plugins to cleanup their session variables */
1624
1706
  plugin_sessionvar_cleanup(this);
1625
1707
 
1626
1708
  /* If necessary, log any aborted or unauthorized connections */
1627
 
  if (getKilled() || client->wasAborted())
1628
 
  {
1629
 
    status_var.aborted_threads++;
1630
 
  }
 
1709
  if (killed || client->wasAborted())
 
1710
    statistic_increment(aborted_threads, &LOCK_status);
1631
1711
 
1632
1712
  if (client->wasAborted())
1633
1713
  {
1634
 
    if (not getKilled() && variables.log_warnings > 1)
 
1714
    if (! killed && variables.log_warnings > 1)
1635
1715
    {
1636
 
      errmsg_printf(error::WARN, ER(ER_NEW_ABORTING_CONNECTION)
 
1716
      SecurityContext *sctx= &security_ctx;
 
1717
 
 
1718
      errmsg_printf(ERRMSG_LVL_WARN, ER(ER_NEW_ABORTING_CONNECTION)
1637
1719
                  , thread_id
1638
 
                  , (_schema->empty() ? "unconnected" : _schema->c_str())
1639
 
                  , security_ctx->username().empty() == false ? security_ctx->username().c_str() : "unauthenticated"
1640
 
                  , security_ctx->address().c_str()
 
1720
                  , (db.empty() ? "unconnected" : db.c_str())
 
1721
                  , sctx->getUser().empty() == false ? sctx->getUser().c_str() : "unauthenticated"
 
1722
                  , sctx->getIp().c_str()
1641
1723
                  , (main_da.is_error() ? main_da.message() : ER(ER_UNKNOWN_ERROR)));
1642
1724
    }
1643
1725
  }
1644
1726
 
1645
 
  setKilled(Session::KILL_CONNECTION);
1646
 
 
 
1727
  /* Close out our connection to the client */
 
1728
  if (should_lock)
 
1729
    (void) pthread_mutex_lock(&LOCK_thread_count);
 
1730
  killed= Session::KILL_CONNECTION;
1647
1731
  if (client->isConnected())
1648
1732
  {
1649
 
    if (errcode != EE_OK)
 
1733
    if (errcode)
1650
1734
    {
1651
1735
      /*my_error(errcode, ER(errcode));*/
1652
1736
      client->sendError(errcode, ER(errcode));
1653
1737
    }
1654
1738
    client->close();
1655
1739
  }
 
1740
  if (should_lock)
 
1741
    (void) pthread_mutex_unlock(&LOCK_thread_count);
1656
1742
}
1657
1743
 
1658
1744
void Session::reset_for_next_command()
1680
1766
  Close all temporary tables created by 'CREATE TEMPORARY TABLE' for thread
1681
1767
*/
1682
1768
 
1683
 
void Open_tables_state::close_temporary_tables()
 
1769
void Session::close_temporary_tables()
1684
1770
{
1685
1771
  Table *table;
1686
1772
  Table *tmp_next;
1687
1773
 
1688
 
  if (not temporary_tables)
 
1774
  if (!temporary_tables)
1689
1775
    return;
1690
1776
 
1691
1777
  for (table= temporary_tables; table; table= tmp_next)
1692
1778
  {
1693
 
    tmp_next= table->getNext();
1694
 
    nukeTable(table);
 
1779
    tmp_next= table->next;
 
1780
    close_temporary(table);
1695
1781
  }
1696
1782
  temporary_tables= NULL;
1697
1783
}
1700
1786
  unlink from session->temporary tables and close temporary table
1701
1787
*/
1702
1788
 
1703
 
void Open_tables_state::close_temporary_table(Table *table)
 
1789
void Session::close_temporary_table(Table *table)
1704
1790
{
1705
 
  if (table->getPrev())
 
1791
  if (table->prev)
1706
1792
  {
1707
 
    table->getPrev()->setNext(table->getNext());
1708
 
    if (table->getPrev()->getNext())
1709
 
    {
1710
 
      table->getNext()->setPrev(table->getPrev());
1711
 
    }
 
1793
    table->prev->next= table->next;
 
1794
    if (table->prev->next)
 
1795
      table->next->prev= table->prev;
1712
1796
  }
1713
1797
  else
1714
1798
  {
1719
1803
      passing non-zero value to end_slave via rli->save_temporary_tables
1720
1804
      when no temp tables opened, see an invariant below.
1721
1805
    */
1722
 
    temporary_tables= table->getNext();
 
1806
    temporary_tables= table->next;
1723
1807
    if (temporary_tables)
1724
 
    {
1725
 
      table->getNext()->setPrev(NULL);
1726
 
    }
 
1808
      table->next->prev= NULL;
1727
1809
  }
1728
 
  nukeTable(table);
 
1810
  close_temporary(table);
1729
1811
}
1730
1812
 
1731
1813
/*
1732
 
  Close and drop a temporary table
 
1814
  Close and delete a temporary table
1733
1815
 
1734
1816
  NOTE
1735
1817
  This dosn't unlink table from session->temporary
1736
1818
  If this is needed, use close_temporary_table()
1737
1819
*/
1738
1820
 
1739
 
void Open_tables_state::nukeTable(Table *table)
 
1821
void Session::close_temporary(Table *table)
1740
1822
{
1741
 
  plugin::StorageEngine *table_type= table->getShare()->db_type();
 
1823
  plugin::StorageEngine *table_type= table->s->db_type();
1742
1824
 
1743
1825
  table->free_io_cache();
1744
 
  table->delete_table();
1745
 
 
1746
 
  identifier::Table identifier(table->getShare()->getSchemaName(), table->getShare()->getTableName(), table->getShare()->getPath());
1747
 
  rm_temporary_table(table_type, identifier);
1748
 
 
1749
 
  boost::checked_delete(table->getMutableShare());
1750
 
 
1751
 
  boost::checked_delete(table);
 
1826
  table->closefrm(false);
 
1827
 
 
1828
  rm_temporary_table(table_type, table->s->path.str);
 
1829
 
 
1830
  table->s->free_table_share();
 
1831
 
 
1832
  /* This makes me sad, but we're allocating it via malloc */
 
1833
  free(table);
1752
1834
}
1753
1835
 
1754
1836
/** Clear most status variables. */
1755
1837
extern time_t flush_status_time;
 
1838
extern uint32_t max_used_connections;
1756
1839
 
1757
1840
void Session::refresh_status()
1758
1841
{
 
1842
  pthread_mutex_lock(&LOCK_status);
 
1843
 
 
1844
  /* Add thread's status variabes to global status */
 
1845
  add_to_status(&global_status_var, &status_var);
 
1846
 
1759
1847
  /* Reset thread's status variables */
1760
1848
  memset(&status_var, 0, sizeof(status_var));
1761
1849
 
 
1850
  /* Reset some global variables */
 
1851
  reset_status_vars();
 
1852
 
 
1853
  /* Reset the counters of all key caches (default and named). */
 
1854
  reset_key_cache_counters();
1762
1855
  flush_status_time= time((time_t*) 0);
1763
 
  current_global_counters.max_used_connections= 1; /* We set it to one, because we know we exist */
1764
 
  current_global_counters.connections= 0;
 
1856
  max_used_connections= 1; /* We set it to one, because we know we exist */
 
1857
  pthread_mutex_unlock(&LOCK_status);
1765
1858
}
1766
1859
 
1767
1860
user_var_entry *Session::getVariable(LEX_STRING &name, bool create_if_not_exists)
1768
1861
{
1769
 
  return getVariable(std::string(name.str, name.length), create_if_not_exists);
1770
 
}
1771
 
 
1772
 
user_var_entry *Session::getVariable(const std::string  &name, bool create_if_not_exists)
1773
 
{
1774
 
  if (cleanup_done)
1775
 
    return NULL;
1776
 
 
1777
 
  UserVars::iterator iter= user_vars.find(name);
1778
 
  if (iter != user_vars.end())
1779
 
    return (*iter).second;
1780
 
 
1781
 
  if (not create_if_not_exists)
1782
 
    return NULL;
1783
 
 
1784
1862
  user_var_entry *entry= NULL;
1785
 
  entry= new (nothrow) user_var_entry(name.c_str(), query_id);
1786
 
 
1787
 
  if (entry == NULL)
1788
 
    return NULL;
1789
 
 
1790
 
  std::pair<UserVars::iterator, bool> returnable= user_vars.insert(make_pair(name, entry));
1791
 
 
1792
 
  if (not returnable.second)
 
1863
 
 
1864
  entry= (user_var_entry*) hash_search(&user_vars, (unsigned char*) name.str, name.length);
 
1865
 
 
1866
  if ((entry == NULL) && create_if_not_exists)
1793
1867
  {
1794
 
    boost::checked_delete(entry);
 
1868
    if (!hash_inited(&user_vars))
 
1869
      return NULL;
 
1870
    entry= new (nothrow) user_var_entry(name.str, query_id);
 
1871
 
 
1872
    if (entry == NULL)
 
1873
      return NULL;
 
1874
 
 
1875
    if (my_hash_insert(&user_vars, (unsigned char*) entry))
 
1876
    {
 
1877
      assert(1);
 
1878
      free((char*) entry);
 
1879
      return 0;
 
1880
    }
 
1881
 
1795
1882
  }
1796
1883
 
1797
1884
  return entry;
1798
1885
}
1799
1886
 
1800
 
void Session::setVariable(const std::string &name, const std::string &value)
1801
 
{
1802
 
  user_var_entry *updateable_var= getVariable(name.c_str(), true);
1803
 
  if (updateable_var)
1804
 
  {
1805
 
    updateable_var->update_hash(false,
1806
 
                                (void*)value.c_str(),
1807
 
                                static_cast<uint32_t>(value.length()), STRING_RESULT,
1808
 
                                &my_charset_bin,
1809
 
                                DERIVATION_IMPLICIT, false);
1810
 
  }
1811
 
}
1812
 
 
1813
 
void Open_tables_state::mark_temp_tables_as_free_for_reuse()
1814
 
{
1815
 
  for (Table *table= temporary_tables ; table ; table= table->getNext())
1816
 
  {
1817
 
    if (table->query_id == getQueryId())
 
1887
void Session::mark_temp_tables_as_free_for_reuse()
 
1888
{
 
1889
  for (Table *table= temporary_tables ; table ; table= table->next)
 
1890
  {
 
1891
    if (table->query_id == query_id)
1818
1892
    {
1819
1893
      table->query_id= 0;
1820
1894
      table->cursor->ha_reset();
1824
1898
 
1825
1899
void Session::mark_used_tables_as_free_for_reuse(Table *table)
1826
1900
{
1827
 
  for (; table ; table= table->getNext())
 
1901
  for (; table ; table= table->next)
1828
1902
  {
1829
 
    if (table->query_id == getQueryId())
 
1903
    if (table->query_id == query_id)
1830
1904
    {
1831
1905
      table->query_id= 0;
1832
1906
      table->cursor->ha_reset();
1845
1919
*/
1846
1920
void Session::close_thread_tables()
1847
1921
{
1848
 
  clearDerivedTables();
 
1922
  Table *table;
 
1923
 
 
1924
  /*
 
1925
    We are assuming here that session->derived_tables contains ONLY derived
 
1926
    tables for this substatement. i.e. instead of approach which uses
 
1927
    query_id matching for determining which of the derived tables belong
 
1928
    to this substatement we rely on the ability of substatements to
 
1929
    save/restore session->derived_tables during their execution.
 
1930
 
 
1931
    TODO: Probably even better approach is to simply associate list of
 
1932
          derived tables with (sub-)statement instead of thread and destroy
 
1933
          them at the end of its execution.
 
1934
  */
 
1935
  if (derived_tables)
 
1936
  {
 
1937
    Table *next;
 
1938
    /*
 
1939
      Close all derived tables generated in queries like
 
1940
      SELECT * FROM (SELECT * FROM t1)
 
1941
    */
 
1942
    for (table= derived_tables ; table ; table= next)
 
1943
    {
 
1944
      next= table->next;
 
1945
      table->free_tmp_table(this);
 
1946
    }
 
1947
    derived_tables= 0;
 
1948
  }
1849
1949
 
1850
1950
  /*
1851
1951
    Mark all temporary tables used by this statement as free for reuse.
1859
1959
    does not belong to statement for which we do close_thread_tables()).
1860
1960
    TODO: This should be fixed in later releases.
1861
1961
   */
 
1962
  if (backups_available == false)
1862
1963
  {
1863
1964
    TransactionServices &transaction_services= TransactionServices::singleton();
1864
1965
    main_da.can_overwrite_status= true;
1865
 
    transaction_services.autocommitOrRollback(*this, is_error());
 
1966
    transaction_services.ha_autocommit_or_rollback(this, is_error());
1866
1967
    main_da.can_overwrite_status= false;
1867
1968
    transaction.stmt.reset();
1868
1969
  }
1878
1979
      handled either before writing a query log event (inside
1879
1980
      binlog_query()) or when preparing a pending event.
1880
1981
     */
1881
 
    unlockTables(lock);
 
1982
    mysql_unlock_tables(this, lock);
1882
1983
    lock= 0;
1883
1984
  }
1884
1985
  /*
1885
 
    Note that we need to hold table::Cache::singleton().mutex() while changing the
 
1986
    Note that we need to hold LOCK_open while changing the
1886
1987
    open_tables list. Another thread may work on it.
1887
 
    (See: table::Cache::singleton().removeTable(), wait_completed_table())
 
1988
    (See: remove_table_from_cache(), mysql_wait_completed_table())
1888
1989
    Closing a MERGE child before the parent would be fatal if the
1889
1990
    other thread tries to abort the MERGE lock in between.
1890
1991
  */
1916
2017
    if (open_tables_from_list(&tables, &counter))
1917
2018
      return true;
1918
2019
 
1919
 
    if (not lock_tables(tables, counter, &need_reopen))
 
2020
    if (!lock_tables(tables, counter, &need_reopen))
1920
2021
      break;
1921
 
 
1922
 
    if (not need_reopen)
 
2022
    if (!need_reopen)
1923
2023
      return true;
1924
 
 
1925
2024
    close_tables_for_reopen(&tables);
1926
2025
  }
1927
 
 
1928
 
  if ((handle_derived(lex, &derived_prepare) || (handle_derived(lex, &derived_filling))))
1929
 
    return true;
1930
 
 
1931
 
  return false;
1932
 
}
1933
 
 
1934
 
/*
1935
 
  @note "best_effort" is used in cases were if a failure occurred on this
1936
 
  operation it would not be surprising because we are only removing because there
1937
 
  might be an issue (lame engines).
1938
 
*/
1939
 
 
1940
 
bool Open_tables_state::rm_temporary_table(const identifier::Table &identifier, bool best_effort)
1941
 
{
1942
 
  if (not plugin::StorageEngine::dropTable(*static_cast<Session *>(this), identifier))
1943
 
  {
1944
 
    if (not best_effort)
1945
 
    {
1946
 
      std::string path;
1947
 
      identifier.getSQLPath(path);
1948
 
      errmsg_printf(error::WARN, _("Could not remove temporary table: '%s', error: %d"),
1949
 
                    path.c_str(), errno);
1950
 
    }
1951
 
 
1952
 
    return true;
1953
 
  }
1954
 
 
1955
 
  return false;
1956
 
}
1957
 
 
1958
 
bool Open_tables_state::rm_temporary_table(plugin::StorageEngine *base, const identifier::Table &identifier)
1959
 
{
1960
 
  drizzled::error_t error;
1961
 
  assert(base);
1962
 
 
1963
 
  if (not plugin::StorageEngine::dropTable(*static_cast<Session *>(this), *base, identifier, error))
1964
 
  {
1965
 
    std::string path;
1966
 
    identifier.getSQLPath(path);
1967
 
    errmsg_printf(error::WARN, _("Could not remove temporary table: '%s', error: %d"),
1968
 
                  path.c_str(), error);
1969
 
 
1970
 
    return true;
1971
 
  }
1972
 
 
1973
 
  return false;
1974
 
}
1975
 
 
1976
 
/**
1977
 
  @note this will be removed, I am looking through Hudson to see if it is finding
1978
 
  any tables that are missed during cleanup.
1979
 
*/
1980
 
void Open_tables_state::dumpTemporaryTableNames(const char *foo)
1981
 
{
1982
 
  Table *table;
1983
 
 
1984
 
  if (not temporary_tables)
1985
 
    return;
1986
 
 
1987
 
  cerr << "Begin Run: " << foo << "\n";
1988
 
  for (table= temporary_tables; table; table= table->getNext())
1989
 
  {
1990
 
    bool have_proto= false;
1991
 
 
1992
 
    message::Table *proto= table->getShare()->getTableMessage();
1993
 
    if (table->getShare()->getTableMessage())
1994
 
      have_proto= true;
1995
 
 
1996
 
    const char *answer= have_proto ? "true" : "false";
1997
 
 
1998
 
    if (have_proto)
1999
 
    {
2000
 
      cerr << "\tTable Name " << table->getShare()->getSchemaName() << "." << table->getShare()->getTableName() << " : " << answer << "\n";
2001
 
      cerr << "\t\t Proto " << proto->schema() << " " << proto->name() << "\n";
2002
 
    }
2003
 
    else
2004
 
    {
2005
 
      cerr << "\tTabl;e Name " << table->getShare()->getSchemaName() << "." << table->getShare()->getTableName() << " : " << answer << "\n";
2006
 
    }
2007
 
  }
2008
 
}
2009
 
 
2010
 
table::Singular *Session::getInstanceTable()
2011
 
{
2012
 
  temporary_shares.push_back(new table::Singular()); // This will not go into the tableshare cache, so no key is used.
2013
 
 
2014
 
  table::Singular *tmp_share= temporary_shares.back();
2015
 
 
2016
 
  assert(tmp_share);
2017
 
 
2018
 
  return tmp_share;
2019
 
}
2020
 
 
2021
 
 
2022
 
/**
2023
 
  Create a reduced Table object with properly set up Field list from a
2024
 
  list of field definitions.
2025
 
 
2026
 
    The created table doesn't have a table Cursor associated with
2027
 
    it, has no keys, no group/distinct, no copy_funcs array.
2028
 
    The sole purpose of this Table object is to use the power of Field
2029
 
    class to read/write data to/from table->getInsertRecord(). Then one can store
2030
 
    the record in any container (RB tree, hash, etc).
2031
 
    The table is created in Session mem_root, so are the table's fields.
2032
 
    Consequently, if you don't BLOB fields, you don't need to free it.
2033
 
 
2034
 
  @param session         connection handle
2035
 
  @param field_list  list of column definitions
2036
 
 
2037
 
  @return
2038
 
    0 if out of memory, Table object in case of success
2039
 
*/
2040
 
table::Singular *Session::getInstanceTable(List<CreateField> &field_list)
2041
 
{
2042
 
  temporary_shares.push_back(new table::Singular(this, field_list)); // This will not go into the tableshare cache, so no key is used.
2043
 
 
2044
 
  table::Singular *tmp_share= temporary_shares.back();
2045
 
 
2046
 
  assert(tmp_share);
2047
 
 
2048
 
  return tmp_share;
2049
 
}
2050
 
 
2051
 
namespace display  {
2052
 
 
2053
 
static const std::string NONE= "NONE";
2054
 
static const std::string GOT_GLOBAL_READ_LOCK= "HAS GLOBAL READ LOCK";
2055
 
static const std::string MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT= "HAS GLOBAL READ LOCK WITH BLOCKING COMMIT";
2056
 
 
2057
 
const std::string &type(drizzled::Session::global_read_lock_t type)
2058
 
{
2059
 
  switch (type) {
2060
 
    default:
2061
 
    case Session::NONE:
2062
 
      return NONE;
2063
 
    case Session::GOT_GLOBAL_READ_LOCK:
2064
 
      return GOT_GLOBAL_READ_LOCK;
2065
 
    case Session::MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT:
2066
 
      return MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT;
2067
 
  }
2068
 
}
2069
 
 
2070
 
size_t max_string_length(drizzled::Session::global_read_lock_t)
2071
 
{
2072
 
  return MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT.size();
2073
 
}
2074
 
 
2075
 
} /* namespace display */
 
2026
  if ((mysql_handle_derived(lex, &mysql_derived_prepare) ||
 
2027
       (fill_derived_tables() &&
 
2028
        mysql_handle_derived(lex, &mysql_derived_filling))))
 
2029
    return true;
 
2030
 
 
2031
  return false;
 
2032
}
 
2033
 
 
2034
bool Session::openTables(TableList *tables, uint32_t flags)
 
2035
{
 
2036
  uint32_t counter;
 
2037
  bool ret= fill_derived_tables();
 
2038
  assert(ret == false);
 
2039
  if (open_tables_from_list(&tables, &counter, flags) ||
 
2040
      mysql_handle_derived(lex, &mysql_derived_prepare))
 
2041
    return true;
 
2042
  return false;
 
2043
}
 
2044
 
 
2045
bool Session::rm_temporary_table(plugin::StorageEngine *base, TableIdentifier &identifier)
 
2046
{
 
2047
  bool error= false;
 
2048
 
 
2049
  assert(base);
 
2050
 
 
2051
  if (plugin::StorageEngine::deleteDefinitionFromPath(identifier))
 
2052
    error= true;
 
2053
 
 
2054
  if (base->doDropTable(*this, identifier.getPath()))
 
2055
  {
 
2056
    error= true;
 
2057
    errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
 
2058
                  identifier.getPath(), errno);
 
2059
  }
 
2060
  return error;
 
2061
}
 
2062
 
 
2063
bool Session::rm_temporary_table(plugin::StorageEngine *base, const char *path)
 
2064
{
 
2065
  bool error= false;
 
2066
 
 
2067
  assert(base);
 
2068
 
 
2069
  if (delete_table_proto_file(path))
 
2070
    error= true;
 
2071
 
 
2072
  if (base->doDropTable(*this, path))
 
2073
  {
 
2074
    error= true;
 
2075
    errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
 
2076
                  path, errno);
 
2077
  }
 
2078
  return error;
 
2079
}
2076
2080
 
2077
2081
} /* namespace drizzled */