~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/session.cc

  • Committer: Tim Martin
  • Date: 2010-04-05 14:22:01 UTC
  • mto: This revision was merged to the branch mainline in revision 1452.
  • Revision ID: timm@woolly-20100405142201-0qeekehrbui768he
Removed function prototype left over after previous dead code removal

Show diffs side-by-side

added added

removed removed

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