~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/session.cc

  • Committer: Djellel E. Difallah
  • Date: 2010-03-27 10:10:49 UTC
  • mto: This revision was merged to the branch mainline in revision 1429.
  • Revision ID: ded@ubuntu-20100327101049-oo3arvatjoyku124
merge my_decimal and decimal

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
}
357
383
 
358
384
Session::~Session()
359
385
{
360
 
  this->checkSentry();
 
386
  Session_CHECK_SENTRY(this);
 
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
 
 
413
 
  this->checkSentry();
414
 
 
415
 
  setKilled(state_to_set);
416
 
  scheduler->killSession(this);
417
 
 
 
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
{
 
473
  Session_CHECK_SENTRY(this);
 
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
    if (mysql_change_db(this, in_db))
652
691
    {
653
 
      /* change_db() has pushed the error message. */
 
692
      /* mysql_change_db() has pushed the error message. */
654
693
      return false;
655
694
    }
656
695
  }
657
696
  my_ok();
658
 
  password= not passwd_str.empty();
 
697
  password= test(passwd_len);          // remember for error messages
659
698
 
660
699
  /* Ready to handle queries */
661
700
  return true;
677
716
  main_da.reset_diagnostics_area();
678
717
 
679
718
  if (client->readCommand(&l_packet, &packet_length) == false)
680
 
  {
681
 
    return false;
682
 
  }
683
 
 
684
 
  if (getKilled() == KILL_CONNECTION)
685
719
    return false;
686
720
 
687
721
  if (packet_length == 0)
688
722
    return true;
689
723
 
690
 
  l_command= static_cast<enum_server_command>(l_packet[0]);
 
724
  l_command= (enum enum_server_command) (unsigned char) l_packet[0];
691
725
 
692
726
  if (command >= COM_END)
693
727
    command= COM_END;                           // Wrong command
694
728
 
695
729
  assert(packet_length);
696
 
  return not dispatch_command(l_command, this, l_packet+1, (uint32_t) (packet_length-1));
 
730
  return ! dispatch_command(l_command, this, l_packet+1, (uint32_t) (packet_length-1));
697
731
}
698
732
 
699
733
bool Session::readAndStoreQuery(const char *in_packet, uint32_t in_packet_length)
705
739
    in_packet_length--;
706
740
  }
707
741
  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])))
 
742
  while (in_packet_length > 0 &&
 
743
         (pos[-1] == ';' || my_isspace(charset() ,pos[-1])))
709
744
  {
710
745
    pos--;
711
746
    in_packet_length--;
712
747
  }
713
748
 
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));
 
749
  query.assign(in_packet, in_packet + in_packet_length);
722
750
 
723
751
  return true;
724
752
}
743
771
       * (Which of course should never happen...)
744
772
       */
745
773
      server_status&= ~SERVER_STATUS_IN_TRANS;
746
 
      if (transaction_services.commitTransaction(*this, true))
 
774
      if (transaction_services.ha_commit_trans(this, true))
747
775
        result= false;
748
776
      options&= ~(OPTION_BEGIN);
749
777
      break;
760
788
    case ROLLBACK_AND_CHAIN:
761
789
    {
762
790
      server_status&= ~SERVER_STATUS_IN_TRANS;
763
 
      if (transaction_services.rollbackTransaction(*this, true))
 
791
      if (transaction_services.ha_rollback_trans(this, true))
764
792
        result= false;
765
793
      options&= ~(OPTION_BEGIN);
766
794
      if (result == true && (completion == ROLLBACK_AND_CHAIN))
773
801
  }
774
802
 
775
803
  if (result == false)
776
 
  {
777
 
    my_error(static_cast<drizzled::error_t>(killed_errno()), MYF(0));
778
 
  }
 
804
    my_error(killed_errno(), MYF(0));
779
805
  else if ((result == true) && do_release)
780
 
  {
781
 
    setKilled(Session::KILL_CONNECTION);
782
 
  }
 
806
    killed= Session::KILL_CONNECTION;
783
807
 
784
808
  return result;
785
809
}
797
821
  if (options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
798
822
  {
799
823
    server_status&= ~SERVER_STATUS_IN_TRANS;
800
 
    if (transaction_services.commitTransaction(*this, true))
 
824
    if (transaction_services.ha_commit_trans(this, true))
801
825
      result= false;
802
826
  }
803
827
  options&= ~(OPTION_BEGIN);
808
832
{
809
833
  bool result= true;
810
834
 
811
 
  assert(! inTransaction());
812
 
 
813
 
  options|= OPTION_BEGIN;
814
 
  server_status|= SERVER_STATUS_IN_TRANS;
815
 
 
816
 
  if (plugin::TransactionalStorageEngine::notifyStartTransaction(this, opt))
 
835
  if (! endActiveTransaction())
817
836
  {
818
837
    result= false;
819
838
  }
 
839
  else
 
840
  {
 
841
    options|= OPTION_BEGIN;
 
842
    server_status|= SERVER_STATUS_IN_TRANS;
 
843
 
 
844
    if (plugin::TransactionalStorageEngine::notifyStartTransaction(this, opt))
 
845
    {
 
846
      result= false;
 
847
    }
 
848
  }
820
849
 
821
850
  return result;
822
851
}
838
867
    first_successful_insert_id_in_cur_stmt= 0;
839
868
    substitute_null_with_insert_id= true;
840
869
  }
841
 
 
842
870
  arg_of_last_insert_id_function= false;
843
 
 
844
871
  /* Free Items that were created during this execution */
845
872
  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();
 
873
  /* Reset where. */
 
874
  where= Session::DEFAULT_WHERE;
855
875
}
856
876
 
857
877
/**
876
896
                                     bool allocate_lex_string)
877
897
{
878
898
  if (allocate_lex_string)
879
 
    if (!(lex_str= (LEX_STRING *)getMemRoot()->allocate(sizeof(LEX_STRING))))
 
899
    if (!(lex_str= (LEX_STRING *)alloc(sizeof(LEX_STRING))))
880
900
      return 0;
881
 
  if (!(lex_str->str= mem_root->strmake_root(str, length)))
 
901
  if (!(lex_str->str= strmake_root(mem_root, str, length)))
882
902
    return 0;
883
903
  lex_str->length= length;
884
904
  return lex_str;
922
942
  return (result->send_fields(field_list));
923
943
}
924
944
 
925
 
void select_result::send_error(drizzled::error_t errcode, const char *err)
 
945
void select_result::send_error(uint32_t errcode, const char *err)
926
946
{
927
947
  my_message(errcode, err, MYF(0));
928
948
}
931
951
  Handling writing to file
932
952
************************************************************************/
933
953
 
934
 
void select_to_file::send_error(drizzled::error_t errcode,const char *err)
 
954
void select_to_file::send_error(uint32_t errcode,const char *err)
935
955
{
936
956
  my_message(errcode, err, MYF(0));
937
957
  if (file > 0)
938
958
  {
939
 
    (void) cache->end_io_cache();
 
959
    (void) end_io_cache(cache);
940
960
    (void) internal::my_close(file, MYF(0));
941
 
    (void) internal::my_delete(path.file_string().c_str(), MYF(0));             // Delete file on error
 
961
    (void) internal::my_delete(path, MYF(0));           // Delete file on error
942
962
    file= -1;
943
963
  }
944
964
}
946
966
 
947
967
bool select_to_file::send_eof()
948
968
{
949
 
  int error= test(cache->end_io_cache());
 
969
  int error= test(end_io_cache(cache));
950
970
  if (internal::my_close(file, MYF(MY_WME)))
951
971
    error= 1;
952
972
  if (!error)
968
988
  /* In case of error send_eof() may be not called: close the file here. */
969
989
  if (file >= 0)
970
990
  {
971
 
    (void) cache->end_io_cache();
 
991
    (void) end_io_cache(cache);
972
992
    (void) internal::my_close(file, MYF(0));
973
993
    file= -1;
974
994
  }
975
 
  path= "";
 
995
  path[0]= '\0';
976
996
  row_count= 0;
977
997
}
978
998
 
982
1002
    cache(static_cast<internal::IO_CACHE *>(memory::sql_calloc(sizeof(internal::IO_CACHE)))),
983
1003
    row_count(0L)
984
1004
{
985
 
  path= "";
 
1005
  path[0]=0;
986
1006
}
987
1007
 
988
1008
select_to_file::~select_to_file()
1016
1036
*/
1017
1037
 
1018
1038
 
1019
 
static int create_file(Session *session,
1020
 
                       fs::path &target_path,
1021
 
                       file_exchange *exchange,
1022
 
                       internal::IO_CACHE *cache)
 
1039
static int create_file(Session *session, char *path, file_exchange *exchange, internal::IO_CACHE *cache)
1023
1040
{
1024
 
  fs::path to_file(exchange->file_name);
1025
1041
  int file;
1026
 
 
1027
 
  if (not to_file.has_root_directory())
 
1042
  uint32_t option= MY_UNPACK_FILENAME | MY_RELATIVE_PATH;
 
1043
 
 
1044
#ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS
 
1045
  option|= MY_REPLACE_DIR;                      // Force use of db directory
 
1046
#endif
 
1047
 
 
1048
  if (!internal::dirname_length(exchange->file_name))
1028
1049
  {
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;
 
1050
    strcpy(path, drizzle_real_data_home);
 
1051
    if (! session->db.empty())
 
1052
      strncat(path, session->db.c_str(), FN_REFLEN-strlen(drizzle_real_data_home)-1);
 
1053
    (void) internal::fn_format(path, exchange->file_name, path, "", option);
1045
1054
  }
1046
1055
  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))
 
1056
    (void) internal::fn_format(path, exchange->file_name, drizzle_real_data_home, "", option);
 
1057
 
 
1058
  if (opt_secure_file_priv &&
 
1059
      strncmp(opt_secure_file_priv, path, strlen(opt_secure_file_priv)))
 
1060
  {
 
1061
    /* Write only allowed to dir or subdir specified by secure_file_priv */
 
1062
    my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
 
1063
    return -1;
 
1064
  }
 
1065
 
 
1066
  if (!access(path, F_OK))
1062
1067
  {
1063
1068
    my_error(ER_FILE_EXISTS_ERROR, MYF(0), exchange->file_name);
1064
1069
    return -1;
1065
1070
  }
1066
1071
  /* 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)
 
1072
  if ((file= internal::my_create(path, 0666, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0)
1068
1073
    return file;
1069
1074
  (void) fchmod(file, 0666);                    // Because of umask()
1070
 
  if (cache->init_io_cache(file, 0L, internal::WRITE_CACHE, 0L, 1, MYF(MY_WME)))
 
1075
  if (init_io_cache(cache, file, 0L, internal::WRITE_CACHE, 0L, 1, MYF(MY_WME)))
1071
1076
  {
1072
1077
    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
 
1078
    internal::my_delete(path, MYF(0));  // Delete file on error, it was just created
1074
1079
    return -1;
1075
1080
  }
1076
1081
  return file;
1084
1089
  bool string_results= false, non_string_results= false;
1085
1090
  unit= u;
1086
1091
  if ((uint32_t) strlen(exchange->file_name) + NAME_LEN >= FN_REFLEN)
1087
 
  {
1088
 
    path= exchange->file_name;
1089
 
  }
 
1092
    strncpy(path,exchange->file_name,FN_REFLEN-1);
1090
1093
 
1091
1094
  /* Check if there is any blobs in data */
1092
1095
  {
1093
 
    List<Item>::iterator li(list.begin());
 
1096
    List_iterator_fast<Item> li(list);
1094
1097
    Item *item;
1095
1098
    while ((item=li++))
1096
1099
    {
1097
1100
      if (item->max_length >= MAX_BLOB_WIDTH)
1098
1101
      {
1099
 
        blob_flag=1;
1100
 
        break;
 
1102
        blob_flag=1;
 
1103
        break;
1101
1104
      }
1102
 
 
1103
1105
      if (item->result_type() == STRING_RESULT)
1104
1106
        string_results= true;
1105
1107
      else
1140
1142
  return 0;
1141
1143
}
1142
1144
 
 
1145
 
 
1146
#define NEED_ESCAPING(x) ((int) (unsigned char) (x) == escape_char    || \
 
1147
                          (enclosed ? (int) (unsigned char) (x) == field_sep_char      \
 
1148
                                    : (int) (unsigned char) (x) == field_term_char) || \
 
1149
                          (int) (unsigned char) (x) == line_sep_char  || \
 
1150
                          !(x))
 
1151
 
1143
1152
bool select_export::send_data(List<Item> &items)
1144
1153
{
1145
1154
  char buff[MAX_FIELD_WIDTH],null_buff[2],space[MAX_FIELD_WIDTH];
1150
1159
  if (unit->offset_limit_cnt)
1151
1160
  {                                             // using limit offset,count
1152
1161
    unit->offset_limit_cnt--;
1153
 
    return false;
 
1162
    return(0);
1154
1163
  }
1155
1164
  row_count++;
1156
1165
  Item *item;
1157
1166
  uint32_t used_length=0,items_left=items.elements;
1158
 
  List<Item>::iterator li(items.begin());
 
1167
  List_iterator_fast<Item> li(items);
1159
1168
 
1160
1169
  if (my_b_write(cache,(unsigned char*) exchange->line_start->ptr(),
1161
1170
                 exchange->line_start->length()))
1162
 
    return true;
1163
 
 
 
1171
    goto err;
1164
1172
  while ((item=li++))
1165
1173
  {
1166
1174
    Item_result result_type=item->result_type();
1171
1179
    {
1172
1180
      if (my_b_write(cache,(unsigned char*) exchange->enclosed->ptr(),
1173
1181
                     exchange->enclosed->length()))
1174
 
        return true;
 
1182
        goto err;
1175
1183
    }
1176
1184
    if (!res)
1177
1185
    {                                           // NULL
1182
1190
          null_buff[0]=escape_char;
1183
1191
          null_buff[1]='N';
1184
1192
          if (my_b_write(cache,(unsigned char*) null_buff,2))
1185
 
            return true;
 
1193
            goto err;
1186
1194
        }
1187
1195
        else if (my_b_write(cache,(unsigned char*) "NULL",4))
1188
 
          return true;
 
1196
          goto err;
1189
1197
      }
1190
1198
      else
1191
1199
      {
1195
1203
    else
1196
1204
    {
1197
1205
      if (fixed_row_size)
1198
 
        used_length= min(res->length(), static_cast<size_t>(item->max_length));
 
1206
        used_length= min(res->length(),item->max_length);
1199
1207
      else
1200
1208
        used_length= res->length();
1201
1209
 
1257
1265
            assert before the loop makes that sure.
1258
1266
          */
1259
1267
 
1260
 
          if ((needs_escaping(*pos, enclosed) ||
 
1268
          if ((NEED_ESCAPING(*pos) ||
1261
1269
               (check_second_byte &&
1262
1270
                my_mbcharlen(character_set_client, (unsigned char) *pos) == 2 &&
1263
1271
                pos + 1 < end &&
1264
 
                needs_escaping(pos[1], enclosed))) &&
 
1272
                NEED_ESCAPING(pos[1]))) &&
1265
1273
              /*
1266
1274
                Don't escape field_term_char by doubling - doubling is only
1267
1275
                valid for ENCLOSED BY characters:
1276
1284
            tmp_buff[1]= *pos ? *pos : '0';
1277
1285
            if (my_b_write(cache,(unsigned char*) start,(uint32_t) (pos-start)) ||
1278
1286
                my_b_write(cache,(unsigned char*) tmp_buff,2))
1279
 
              return true;
 
1287
              goto err;
1280
1288
            start=pos+1;
1281
1289
          }
1282
1290
        }
1283
1291
        if (my_b_write(cache,(unsigned char*) start,(uint32_t) (pos-start)))
1284
 
          return true;
 
1292
          goto err;
1285
1293
      }
1286
1294
      else if (my_b_write(cache,(unsigned char*) res->ptr(),used_length))
1287
 
        return true;
 
1295
        goto err;
1288
1296
    }
1289
1297
    if (fixed_row_size)
1290
1298
    {                                           // Fill with space
1300
1308
        for (; length > sizeof(space) ; length-=sizeof(space))
1301
1309
        {
1302
1310
          if (my_b_write(cache,(unsigned char*) space,sizeof(space)))
1303
 
            return true;
 
1311
            goto err;
1304
1312
        }
1305
1313
        if (my_b_write(cache,(unsigned char*) space,length))
1306
 
          return true;
 
1314
          goto err;
1307
1315
      }
1308
1316
    }
1309
1317
    if (res && enclosed)
1310
1318
    {
1311
1319
      if (my_b_write(cache, (unsigned char*) exchange->enclosed->ptr(),
1312
1320
                     exchange->enclosed->length()))
1313
 
        return true;
 
1321
        goto err;
1314
1322
    }
1315
1323
    if (--items_left)
1316
1324
    {
1317
1325
      if (my_b_write(cache, (unsigned char*) exchange->field_term->ptr(),
1318
1326
                     field_term_length))
1319
 
        return true;
 
1327
        goto err;
1320
1328
    }
1321
1329
  }
1322
1330
  if (my_b_write(cache,(unsigned char*) exchange->line_term->ptr(),
1323
1331
                 exchange->line_term->length()))
1324
 
  {
1325
 
    return true;
1326
 
  }
1327
 
 
1328
 
  return false;
 
1332
    goto err;
 
1333
  return(0);
 
1334
err:
 
1335
  return(1);
1329
1336
}
1330
1337
 
1331
1338
 
1344
1351
 
1345
1352
bool select_dump::send_data(List<Item> &items)
1346
1353
{
1347
 
  List<Item>::iterator li(items.begin());
 
1354
  List_iterator_fast<Item> li(items);
1348
1355
  char buff[MAX_FIELD_WIDTH];
1349
1356
  String tmp(buff,sizeof(buff),&my_charset_bin),*res;
1350
1357
  tmp.length(0);
1358
1365
  if (row_count++ > 1)
1359
1366
  {
1360
1367
    my_message(ER_TOO_MANY_ROWS, ER(ER_TOO_MANY_ROWS), MYF(0));
1361
 
    return 1;
 
1368
    goto err;
1362
1369
  }
1363
1370
  while ((item=li++))
1364
1371
  {
1366
1373
    if (!res)                                   // If NULL
1367
1374
    {
1368
1375
      if (my_b_write(cache,(unsigned char*) "",1))
1369
 
        return 1;
 
1376
        goto err;
1370
1377
    }
1371
1378
    else if (my_b_write(cache,(unsigned char*) res->ptr(),res->length()))
1372
1379
    {
1373
 
      my_error(ER_ERROR_ON_WRITE, MYF(0), path.file_string().c_str(), errno);
1374
 
      return 1;
 
1380
      my_error(ER_ERROR_ON_WRITE, MYF(0), path, errno);
 
1381
      goto err;
1375
1382
    }
1376
1383
  }
1377
1384
  return(0);
 
1385
err:
 
1386
  return(1);
1378
1387
}
1379
1388
 
1380
1389
 
1397
1406
    unit->offset_limit_cnt--;
1398
1407
    return(0);
1399
1408
  }
1400
 
  List<Item>::iterator li(items.begin());
 
1409
  List_iterator_fast<Item> li(items);
1401
1410
  Item *val_item;
1402
1411
  for (uint32_t i= 0; (val_item= li++); i++)
1403
1412
    it->store(i, val_item);
1415
1424
bool select_max_min_finder_subselect::send_data(List<Item> &items)
1416
1425
{
1417
1426
  Item_maxmin_subselect *it= (Item_maxmin_subselect *)item;
1418
 
  List<Item>::iterator li(items.begin());
 
1427
  List_iterator_fast<Item> li(items);
1419
1428
  Item *val_item= li++;
1420
1429
  it->register_value();
1421
1430
  if (it->assigned())
1432
1441
      switch (val_item->result_type())
1433
1442
      {
1434
1443
      case REAL_RESULT:
1435
 
        op= &select_max_min_finder_subselect::cmp_real;
1436
 
        break;
 
1444
        op= &select_max_min_finder_subselect::cmp_real;
 
1445
        break;
1437
1446
      case INT_RESULT:
1438
 
        op= &select_max_min_finder_subselect::cmp_int;
1439
 
        break;
 
1447
        op= &select_max_min_finder_subselect::cmp_int;
 
1448
        break;
1440
1449
      case STRING_RESULT:
1441
 
        op= &select_max_min_finder_subselect::cmp_str;
1442
 
        break;
 
1450
        op= &select_max_min_finder_subselect::cmp_str;
 
1451
        break;
1443
1452
      case DECIMAL_RESULT:
1444
1453
        op= &select_max_min_finder_subselect::cmp_decimal;
1445
1454
        break;
1446
1455
      case ROW_RESULT:
1447
1456
        // This case should never be choosen
1448
 
        assert(0);
1449
 
        op= 0;
 
1457
        assert(0);
 
1458
        op= 0;
1450
1459
      }
1451
1460
    }
1452
1461
    cache->store(val_item);
1485
1494
bool select_max_min_finder_subselect::cmp_decimal()
1486
1495
{
1487
1496
  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);
 
1497
  my_decimal cval, *cvalue= cache->val_decimal(&cval);
 
1498
  my_decimal mval, *mvalue= maxmin->val_decimal(&mval);
1490
1499
  if (fmax)
1491
1500
    return (cache->null_value && !maxmin->null_value) ||
1492
1501
      (!cache->null_value && !maxmin->null_value &&
1493
 
       class_decimal_cmp(cvalue, mvalue) > 0) ;
 
1502
       my_decimal_cmp(cvalue, mvalue) > 0) ;
1494
1503
  return (maxmin->null_value && !cache->null_value) ||
1495
1504
    (!cache->null_value && !maxmin->null_value &&
1496
 
     class_decimal_cmp(cvalue,mvalue) < 0);
 
1505
     my_decimal_cmp(cvalue,mvalue) < 0);
1497
1506
}
1498
1507
 
1499
1508
bool select_max_min_finder_subselect::cmp_str()
1535
1544
void Session::end_statement()
1536
1545
{
1537
1546
  /* Cleanup SQL processing state to reuse this statement in next query. */
1538
 
  lex->end();
1539
 
  query_cache_key= ""; // reset the cache key
1540
 
  resetResultsetMessage();
 
1547
  lex_end(lex);
1541
1548
}
1542
1549
 
1543
1550
bool Session::copy_db_to(char **p_db, size_t *p_db_length)
1544
1551
{
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
 
 
 
1552
  if (db.empty())
 
1553
  {
 
1554
    my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
 
1555
    return true;
 
1556
  }
 
1557
  *p_db= strmake(db.c_str(), db.length());
 
1558
  *p_db_length= db.length();
1561
1559
  return false;
1562
1560
}
1563
1561
 
1579
1577
  /* Fix for Intel compiler */
1580
1578
  if (copy_field)
1581
1579
  {
1582
 
    boost::checked_array_delete(copy_field);
1583
 
    save_copy_field= save_copy_field_end= copy_field= copy_field_end= 0;
 
1580
    delete [] copy_field;
 
1581
    save_copy_field= copy_field= 0;
1584
1582
  }
1585
1583
}
1586
1584
 
1587
1585
void Session::send_kill_message() const
1588
1586
{
1589
 
  drizzled::error_t err= static_cast<drizzled::error_t>(killed_errno());
1590
 
  if (err != EE_OK)
 
1587
  int err= killed_errno();
 
1588
  if (err)
1591
1589
    my_message(err, ER(err), MYF(0));
1592
1590
}
1593
1591
 
1597
1595
}
1598
1596
 
1599
1597
 
1600
 
void Session::set_db(const std::string &new_db)
 
1598
/****************************************************************************
 
1599
  Handling of open and locked tables states.
 
1600
 
 
1601
  This is used when we want to open/lock (and then close) some tables when
 
1602
  we already have a set of tables open and locked. We use these methods for
 
1603
  access to mysql.proc table to find definitions of stored routines.
 
1604
****************************************************************************/
 
1605
 
 
1606
void Session::reset_n_backup_open_tables_state(Open_tables_state *backup)
 
1607
{
 
1608
  backup->set_open_tables_state(this);
 
1609
  reset_open_tables_state();
 
1610
  backups_available= false;
 
1611
}
 
1612
 
 
1613
 
 
1614
void Session::restore_backup_open_tables_state(Open_tables_state *backup)
 
1615
{
 
1616
  /*
 
1617
    Before we will throw away current open tables state we want
 
1618
    to be sure that it was properly cleaned up.
 
1619
  */
 
1620
  assert(open_tables == 0 && temporary_tables == 0 &&
 
1621
              derived_tables == 0 &&
 
1622
              lock == 0);
 
1623
  set_open_tables_state(backup);
 
1624
}
 
1625
 
 
1626
bool Session::set_db(const char *new_db, size_t length)
1601
1627
{
1602
1628
  /* Do not reallocate memory if current chunk is big enough. */
1603
 
  if (new_db.length())
1604
 
  {
1605
 
    _schema.reset(new std::string(new_db));
1606
 
  }
 
1629
  if (length)
 
1630
    db= new_db;
1607
1631
  else
1608
 
  {
1609
 
    _schema.reset(new std::string(""));
1610
 
  }
1611
 
}
1612
 
 
 
1632
    db.clear();
 
1633
 
 
1634
  return false;
 
1635
}
 
1636
 
 
1637
 
 
1638
 
 
1639
 
 
1640
/**
 
1641
  Check the killed state of a user thread
 
1642
  @param session  user thread
 
1643
  @retval 0 the user thread is active
 
1644
  @retval 1 the user thread has been killed
 
1645
*/
 
1646
extern "C" int session_killed(const Session *session)
 
1647
{
 
1648
  return(session->killed);
 
1649
}
 
1650
 
 
1651
/**
 
1652
  Return the session id of a user session
 
1653
  @param pointer to Session object
 
1654
  @return session's id
 
1655
*/
 
1656
extern "C" unsigned long session_get_thread_id(const Session *session)
 
1657
{
 
1658
  return (unsigned long) session->getSessionId();
 
1659
}
 
1660
 
 
1661
 
 
1662
const struct charset_info_st *session_charset(Session *session)
 
1663
{
 
1664
  return(session->charset());
 
1665
}
 
1666
 
 
1667
int session_non_transactional_update(const Session *session)
 
1668
{
 
1669
  return(session->transaction.all.hasModifiedNonTransData());
 
1670
}
 
1671
 
 
1672
void session_mark_transaction_to_rollback(Session *session, bool all)
 
1673
{
 
1674
  mark_transaction_to_rollback(session, all);
 
1675
}
1613
1676
 
1614
1677
/**
1615
1678
  Mark transaction to rollback and mark error as fatal to a sub-statement.
1617
1680
  @param  session   Thread handle
1618
1681
  @param  all   true <=> rollback main transaction.
1619
1682
*/
1620
 
void Session::markTransactionForRollback(bool all)
 
1683
void mark_transaction_to_rollback(Session *session, bool all)
1621
1684
{
1622
 
  is_fatal_sub_stmt_error= true;
1623
 
  transaction_rollback_request= all;
 
1685
  if (session)
 
1686
  {
 
1687
    session->is_fatal_sub_stmt_error= true;
 
1688
    session->transaction_rollback_request= all;
 
1689
  }
1624
1690
}
1625
1691
 
1626
 
void Session::disconnect(enum error_t errcode)
 
1692
void Session::disconnect(uint32_t errcode, bool should_lock)
1627
1693
{
1628
1694
  /* Allow any plugins to cleanup their session variables */
1629
1695
  plugin_sessionvar_cleanup(this);
1630
1696
 
1631
1697
  /* If necessary, log any aborted or unauthorized connections */
1632
 
  if (getKilled() || client->wasAborted())
1633
 
  {
1634
 
    status_var.aborted_threads++;
1635
 
  }
 
1698
  if (killed || client->wasAborted())
 
1699
    statistic_increment(aborted_threads, &LOCK_status);
1636
1700
 
1637
1701
  if (client->wasAborted())
1638
1702
  {
1639
 
    if (not getKilled() && variables.log_warnings > 1)
 
1703
    if (! killed && variables.log_warnings > 1)
1640
1704
    {
1641
 
      errmsg_printf(error::WARN, ER(ER_NEW_ABORTING_CONNECTION)
 
1705
      SecurityContext *sctx= &security_ctx;
 
1706
 
 
1707
      errmsg_printf(ERRMSG_LVL_WARN, ER(ER_NEW_ABORTING_CONNECTION)
1642
1708
                  , 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()
 
1709
                  , (db.empty() ? "unconnected" : db.c_str())
 
1710
                  , sctx->getUser().empty() == false ? sctx->getUser().c_str() : "unauthenticated"
 
1711
                  , sctx->getIp().c_str()
1646
1712
                  , (main_da.is_error() ? main_da.message() : ER(ER_UNKNOWN_ERROR)));
1647
1713
    }
1648
1714
  }
1649
1715
 
1650
 
  setKilled(Session::KILL_CONNECTION);
1651
 
 
 
1716
  /* Close out our connection to the client */
 
1717
  if (should_lock)
 
1718
    (void) pthread_mutex_lock(&LOCK_thread_count);
 
1719
  killed= Session::KILL_CONNECTION;
1652
1720
  if (client->isConnected())
1653
1721
  {
1654
 
    if (errcode != EE_OK)
 
1722
    if (errcode)
1655
1723
    {
1656
1724
      /*my_error(errcode, ER(errcode));*/
1657
1725
      client->sendError(errcode, ER(errcode));
1658
1726
    }
1659
1727
    client->close();
1660
1728
  }
 
1729
  if (should_lock)
 
1730
    (void) pthread_mutex_unlock(&LOCK_thread_count);
1661
1731
}
1662
1732
 
1663
1733
void Session::reset_for_next_command()
1685
1755
  Close all temporary tables created by 'CREATE TEMPORARY TABLE' for thread
1686
1756
*/
1687
1757
 
1688
 
void Open_tables_state::close_temporary_tables()
 
1758
void Session::close_temporary_tables()
1689
1759
{
1690
1760
  Table *table;
1691
1761
  Table *tmp_next;
1692
1762
 
1693
 
  if (not temporary_tables)
 
1763
  if (!temporary_tables)
1694
1764
    return;
1695
1765
 
1696
1766
  for (table= temporary_tables; table; table= tmp_next)
1697
1767
  {
1698
 
    tmp_next= table->getNext();
1699
 
    nukeTable(table);
 
1768
    tmp_next= table->next;
 
1769
    close_temporary(table);
1700
1770
  }
1701
1771
  temporary_tables= NULL;
1702
1772
}
1705
1775
  unlink from session->temporary tables and close temporary table
1706
1776
*/
1707
1777
 
1708
 
void Open_tables_state::close_temporary_table(Table *table)
 
1778
void Session::close_temporary_table(Table *table)
1709
1779
{
1710
 
  if (table->getPrev())
 
1780
  if (table->prev)
1711
1781
  {
1712
 
    table->getPrev()->setNext(table->getNext());
1713
 
    if (table->getPrev()->getNext())
1714
 
    {
1715
 
      table->getNext()->setPrev(table->getPrev());
1716
 
    }
 
1782
    table->prev->next= table->next;
 
1783
    if (table->prev->next)
 
1784
      table->next->prev= table->prev;
1717
1785
  }
1718
1786
  else
1719
1787
  {
1724
1792
      passing non-zero value to end_slave via rli->save_temporary_tables
1725
1793
      when no temp tables opened, see an invariant below.
1726
1794
    */
1727
 
    temporary_tables= table->getNext();
 
1795
    temporary_tables= table->next;
1728
1796
    if (temporary_tables)
1729
 
    {
1730
 
      table->getNext()->setPrev(NULL);
1731
 
    }
 
1797
      table->next->prev= NULL;
1732
1798
  }
1733
 
  nukeTable(table);
 
1799
  close_temporary(table);
1734
1800
}
1735
1801
 
1736
1802
/*
1737
 
  Close and drop a temporary table
 
1803
  Close and delete a temporary table
1738
1804
 
1739
1805
  NOTE
1740
1806
  This dosn't unlink table from session->temporary
1741
1807
  If this is needed, use close_temporary_table()
1742
1808
*/
1743
1809
 
1744
 
void Open_tables_state::nukeTable(Table *table)
 
1810
void Session::close_temporary(Table *table)
1745
1811
{
1746
 
  plugin::StorageEngine *table_type= table->getShare()->db_type();
 
1812
  plugin::StorageEngine *table_type= table->s->db_type();
1747
1813
 
1748
1814
  table->free_io_cache();
1749
 
  table->delete_table();
1750
 
 
1751
 
  identifier::Table identifier(table->getShare()->getSchemaName(), table->getShare()->getTableName(), table->getShare()->getPath());
1752
 
  rm_temporary_table(table_type, identifier);
1753
 
 
1754
 
  boost::checked_delete(table->getMutableShare());
1755
 
 
1756
 
  boost::checked_delete(table);
 
1815
  table->closefrm(false);
 
1816
 
 
1817
  rm_temporary_table(table_type, table->s->path.str);
 
1818
 
 
1819
  table->s->free_table_share();
 
1820
 
 
1821
  /* This makes me sad, but we're allocating it via malloc */
 
1822
  free(table);
1757
1823
}
1758
1824
 
1759
1825
/** Clear most status variables. */
1760
1826
extern time_t flush_status_time;
 
1827
extern uint32_t max_used_connections;
1761
1828
 
1762
1829
void Session::refresh_status()
1763
1830
{
 
1831
  pthread_mutex_lock(&LOCK_status);
 
1832
 
 
1833
  /* Add thread's status variabes to global status */
 
1834
  add_to_status(&global_status_var, &status_var);
 
1835
 
1764
1836
  /* Reset thread's status variables */
1765
1837
  memset(&status_var, 0, sizeof(status_var));
1766
1838
 
 
1839
  /* Reset some global variables */
 
1840
  reset_status_vars();
 
1841
 
 
1842
  /* Reset the counters of all key caches (default and named). */
 
1843
  reset_key_cache_counters();
1767
1844
  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;
 
1845
  max_used_connections= 1; /* We set it to one, because we know we exist */
 
1846
  pthread_mutex_unlock(&LOCK_status);
1770
1847
}
1771
1848
 
1772
1849
user_var_entry *Session::getVariable(LEX_STRING &name, bool create_if_not_exists)
1773
1850
{
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
1851
  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)
 
1852
 
 
1853
  entry= (user_var_entry*) hash_search(&user_vars, (unsigned char*) name.str, name.length);
 
1854
 
 
1855
  if ((entry == NULL) && create_if_not_exists)
1798
1856
  {
1799
 
    boost::checked_delete(entry);
 
1857
    if (!hash_inited(&user_vars))
 
1858
      return NULL;
 
1859
    entry= new (nothrow) user_var_entry(name.str, query_id);
 
1860
 
 
1861
    if (entry == NULL)
 
1862
      return NULL;
 
1863
 
 
1864
    if (my_hash_insert(&user_vars, (unsigned char*) entry))
 
1865
    {
 
1866
      assert(1);
 
1867
      free((char*) entry);
 
1868
      return 0;
 
1869
    }
 
1870
 
1800
1871
  }
1801
1872
 
1802
1873
  return entry;
1803
1874
}
1804
1875
 
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())
 
1876
void Session::mark_temp_tables_as_free_for_reuse()
 
1877
{
 
1878
  for (Table *table= temporary_tables ; table ; table= table->next)
 
1879
  {
 
1880
    if (table->query_id == query_id)
1823
1881
    {
1824
1882
      table->query_id= 0;
1825
1883
      table->cursor->ha_reset();
1829
1887
 
1830
1888
void Session::mark_used_tables_as_free_for_reuse(Table *table)
1831
1889
{
1832
 
  for (; table ; table= table->getNext())
 
1890
  for (; table ; table= table->next)
1833
1891
  {
1834
 
    if (table->query_id == getQueryId())
 
1892
    if (table->query_id == query_id)
1835
1893
    {
1836
1894
      table->query_id= 0;
1837
1895
      table->cursor->ha_reset();
1850
1908
*/
1851
1909
void Session::close_thread_tables()
1852
1910
{
1853
 
  clearDerivedTables();
 
1911
  Table *table;
 
1912
 
 
1913
  /*
 
1914
    We are assuming here that session->derived_tables contains ONLY derived
 
1915
    tables for this substatement. i.e. instead of approach which uses
 
1916
    query_id matching for determining which of the derived tables belong
 
1917
    to this substatement we rely on the ability of substatements to
 
1918
    save/restore session->derived_tables during their execution.
 
1919
 
 
1920
    TODO: Probably even better approach is to simply associate list of
 
1921
          derived tables with (sub-)statement instead of thread and destroy
 
1922
          them at the end of its execution.
 
1923
  */
 
1924
  if (derived_tables)
 
1925
  {
 
1926
    Table *next;
 
1927
    /*
 
1928
      Close all derived tables generated in queries like
 
1929
      SELECT * FROM (SELECT * FROM t1)
 
1930
    */
 
1931
    for (table= derived_tables ; table ; table= next)
 
1932
    {
 
1933
      next= table->next;
 
1934
      table->free_tmp_table(this);
 
1935
    }
 
1936
    derived_tables= 0;
 
1937
  }
1854
1938
 
1855
1939
  /*
1856
1940
    Mark all temporary tables used by this statement as free for reuse.
1864
1948
    does not belong to statement for which we do close_thread_tables()).
1865
1949
    TODO: This should be fixed in later releases.
1866
1950
   */
 
1951
  if (backups_available == false)
1867
1952
  {
1868
1953
    TransactionServices &transaction_services= TransactionServices::singleton();
1869
1954
    main_da.can_overwrite_status= true;
1870
 
    transaction_services.autocommitOrRollback(*this, is_error());
 
1955
    transaction_services.ha_autocommit_or_rollback(this, is_error());
1871
1956
    main_da.can_overwrite_status= false;
1872
1957
    transaction.stmt.reset();
1873
1958
  }
1883
1968
      handled either before writing a query log event (inside
1884
1969
      binlog_query()) or when preparing a pending event.
1885
1970
     */
1886
 
    unlockTables(lock);
 
1971
    mysql_unlock_tables(this, lock);
1887
1972
    lock= 0;
1888
1973
  }
1889
1974
  /*
1890
 
    Note that we need to hold table::Cache::singleton().mutex() while changing the
 
1975
    Note that we need to hold LOCK_open while changing the
1891
1976
    open_tables list. Another thread may work on it.
1892
 
    (See: table::Cache::singleton().removeTable(), wait_completed_table())
 
1977
    (See: remove_table_from_cache(), mysql_wait_completed_table())
1893
1978
    Closing a MERGE child before the parent would be fatal if the
1894
1979
    other thread tries to abort the MERGE lock in between.
1895
1980
  */
1921
2006
    if (open_tables_from_list(&tables, &counter))
1922
2007
      return true;
1923
2008
 
1924
 
    if (not lock_tables(tables, counter, &need_reopen))
 
2009
    if (!lock_tables(tables, counter, &need_reopen))
1925
2010
      break;
1926
 
 
1927
 
    if (not need_reopen)
 
2011
    if (!need_reopen)
1928
2012
      return true;
1929
 
 
1930
2013
    close_tables_for_reopen(&tables);
1931
2014
  }
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))
 
2015
  if ((mysql_handle_derived(lex, &mysql_derived_prepare) ||
 
2016
       (fill_derived_tables() &&
 
2017
        mysql_handle_derived(lex, &mysql_derived_filling))))
 
2018
    return true;
 
2019
 
 
2020
  return false;
 
2021
}
 
2022
 
 
2023
bool Session::openTables(TableList *tables, uint32_t flags)
 
2024
{
 
2025
  uint32_t counter;
 
2026
  bool ret= fill_derived_tables();
 
2027
  assert(ret == false);
 
2028
  if (open_tables_from_list(&tables, &counter, flags) ||
 
2029
      mysql_handle_derived(lex, &mysql_derived_prepare))
 
2030
    return true;
 
2031
  return false;
 
2032
}
 
2033
 
 
2034
bool Session::rm_temporary_table(TableIdentifier &identifier)
 
2035
{
 
2036
  if (not plugin::StorageEngine::dropTable(*this, identifier))
1948
2037
  {
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
 
    }
 
2038
    errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
 
2039
                  identifier.getPath().c_str(), errno);
1956
2040
 
1957
2041
    return true;
1958
2042
  }
1960
2044
  return false;
1961
2045
}
1962
2046
 
1963
 
bool Open_tables_state::rm_temporary_table(plugin::StorageEngine *base, const identifier::Table &identifier)
 
2047
bool Session::rm_temporary_table(plugin::StorageEngine *base, const char *path)
1964
2048
{
1965
 
  drizzled::error_t error;
 
2049
  bool error= false;
 
2050
  TableIdentifier dummy(path);
 
2051
 
1966
2052
  assert(base);
1967
2053
 
1968
 
  if (not plugin::StorageEngine::dropTable(*static_cast<Session *>(this), *base, identifier, error))
1969
 
  {
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);
1974
 
 
1975
 
    return true;
1976
 
  }
1977
 
 
1978
 
  return false;
1979
 
}
1980
 
 
1981
 
/**
1982
 
  @note this will be removed, I am looking through Hudson to see if it is finding
1983
 
  any tables that are missed during cleanup.
1984
 
*/
1985
 
void Open_tables_state::dumpTemporaryTableNames(const char *foo)
1986
 
{
1987
 
  Table *table;
1988
 
 
1989
 
  if (not temporary_tables)
1990
 
    return;
1991
 
 
1992
 
  cerr << "Begin Run: " << foo << "\n";
1993
 
  for (table= temporary_tables; table; table= table->getNext())
1994
 
  {
1995
 
    bool have_proto= false;
1996
 
 
1997
 
    message::Table *proto= table->getShare()->getTableMessage();
1998
 
    if (table->getShare()->getTableMessage())
1999
 
      have_proto= true;
2000
 
 
2001
 
    const char *answer= have_proto ? "true" : "false";
2002
 
 
2003
 
    if (have_proto)
2004
 
    {
2005
 
      cerr << "\tTable Name " << table->getShare()->getSchemaName() << "." << table->getShare()->getTableName() << " : " << answer << "\n";
2006
 
      cerr << "\t\t Proto " << proto->schema() << " " << proto->name() << "\n";
2007
 
    }
2008
 
    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 */
 
2054
  if (delete_table_proto_file(path))
 
2055
    error= true;
 
2056
 
 
2057
  if (base->doDropTable(*this, dummy))
 
2058
  {
 
2059
    error= true;
 
2060
    errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
 
2061
                  path, errno);
 
2062
  }
 
2063
  return error;
 
2064
}
 
2065
 
 
2066
bool Session::storeTableMessage(TableIdentifier &identifier, message::Table &table_message)
 
2067
{
 
2068
  table_message_cache.insert(make_pair(identifier.getPath(), table_message));
 
2069
 
 
2070
  return true;
 
2071
}
 
2072
 
 
2073
bool Session::removeTableMessage(TableIdentifier &identifier)
 
2074
{
 
2075
  TableMessageCache::iterator iter;
 
2076
 
 
2077
  iter= table_message_cache.find(identifier.getPath());
 
2078
 
 
2079
  if (iter == table_message_cache.end())
 
2080
    return false;
 
2081
 
 
2082
  table_message_cache.erase(iter);
 
2083
 
 
2084
  return true;
 
2085
}
 
2086
 
 
2087
bool Session::getTableMessage(TableIdentifier &identifier, message::Table &table_message)
 
2088
{
 
2089
  TableMessageCache::iterator iter;
 
2090
 
 
2091
  iter= table_message_cache.find(identifier.getPath());
 
2092
 
 
2093
  if (iter == table_message_cache.end())
 
2094
    return false;
 
2095
 
 
2096
  table_message.CopyFrom(((*iter).second));
 
2097
 
 
2098
  return true;
 
2099
}
 
2100
 
 
2101
bool Session::doesTableMessageExist(TableIdentifier &identifier)
 
2102
{
 
2103
  TableMessageCache::iterator iter;
 
2104
 
 
2105
  iter= table_message_cache.find(identifier.getPath());
 
2106
 
 
2107
  if (iter == table_message_cache.end())
 
2108
  {
 
2109
    return false;
 
2110
  }
 
2111
 
 
2112
  return true;
 
2113
}
 
2114
 
 
2115
bool Session::renameTableMessage(TableIdentifier &from, TableIdentifier &to)
 
2116
{
 
2117
  TableMessageCache::iterator iter;
 
2118
 
 
2119
  table_message_cache[to.getPath()]= table_message_cache[from.getPath()];
 
2120
 
 
2121
  iter= table_message_cache.find(to.getPath());
 
2122
 
 
2123
  if (iter == table_message_cache.end())
 
2124
  {
 
2125
    return false;
 
2126
  }
 
2127
 
 
2128
  to.copyToTableMessage((*iter).second);
 
2129
 
 
2130
  (void)removeTableMessage(from);
 
2131
 
 
2132
  return true;
 
2133
}
2081
2134
 
2082
2135
} /* namespace drizzled */