~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/session.cc

  • Committer: Padraig O'Sullivan
  • Date: 2010-02-10 16:26:01 UTC
  • mto: This revision was merged to the branch mainline in revision 1294.
  • Revision ID: osullivan.padraig@gmail.com-20100210162601-itx2ndl397pc1wr6
Corrected an order of initialization in a few optimizer classes

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
22
 */
23
23
 
24
24
#include "config.h"
25
 
#include "drizzled/session.h"
26
 
#include "drizzled/session/cache.h"
 
25
#include <drizzled/session.h>
 
26
#include "drizzled/session_list.h"
27
27
#include <sys/stat.h>
28
 
#include "drizzled/error.h"
29
 
#include "drizzled/gettext.h"
30
 
#include "drizzled/query_id.h"
31
 
#include "drizzled/data_home.h"
32
 
#include "drizzled/sql_base.h"
33
 
#include "drizzled/lock.h"
34
 
#include "drizzled/item/cache.h"
35
 
#include "drizzled/item/float.h"
36
 
#include "drizzled/item/return_int.h"
37
 
#include "drizzled/item/empty_string.h"
38
 
#include "drizzled/show.h"
39
 
#include "drizzled/plugin/client.h"
 
28
#include "drizzled/my_error.h"
 
29
#include <drizzled/error.h>
 
30
#include <drizzled/gettext.h>
 
31
#include <drizzled/query_id.h>
 
32
#include <drizzled/data_home.h>
 
33
#include <drizzled/sql_base.h>
 
34
#include <drizzled/lock.h>
 
35
#include <drizzled/item/cache.h>
 
36
#include <drizzled/item/float.h>
 
37
#include <drizzled/item/return_int.h>
 
38
#include <drizzled/item/empty_string.h>
 
39
#include <drizzled/show.h>
 
40
#include <drizzled/plugin/client.h>
40
41
#include "drizzled/plugin/scheduler.h"
41
42
#include "drizzled/plugin/authentication.h"
42
 
#include "drizzled/plugin/logging.h"
43
 
#include "drizzled/plugin/transactional_storage_engine.h"
44
 
#include "drizzled/plugin/query_rewrite.h"
45
43
#include "drizzled/probes.h"
46
44
#include "drizzled/table_proto.h"
47
45
#include "drizzled/db.h"
48
46
#include "drizzled/pthread_globals.h"
49
47
#include "drizzled/transaction_services.h"
50
 
#include "drizzled/drizzled.h"
51
 
 
52
 
#include "drizzled/table/instance.h"
53
48
 
54
49
#include "plugin/myisam/myisam.h"
55
50
#include "drizzled/internal/iocache.h"
56
 
#include "drizzled/internal/thread_var.h"
57
 
#include "drizzled/plugin/event_observer.h"
58
 
 
59
 
#include "drizzled/util/functors.h"
60
 
 
61
 
#include "drizzled/display.h"
62
51
 
63
52
#include <fcntl.h>
64
53
#include <algorithm>
65
54
#include <climits>
66
 
#include <boost/filesystem.hpp>
67
 
 
68
 
#include "drizzled/util/backtrace.h"
69
55
 
70
56
using namespace std;
71
 
 
72
 
namespace fs=boost::filesystem;
73
57
namespace drizzled
74
58
{
75
59
 
 
60
extern "C"
 
61
{
 
62
  unsigned char *get_var_key(user_var_entry *entry, size_t *length, bool );
 
63
  void free_user_var(user_var_entry *entry);
 
64
}
 
65
 
76
66
/*
77
67
  The following is used to initialise Table_ident with a internal
78
68
  table name
81
71
char empty_c_string[1]= {0};    /* used for not defined db */
82
72
 
83
73
const char * const Session::DEFAULT_WHERE= "field list";
 
74
extern pthread_key_t THR_Session;
 
75
extern pthread_key_t THR_Mem_root;
 
76
extern uint32_t max_used_connections;
 
77
extern atomic<uint32_t> connection_count;
 
78
 
 
79
 
 
80
/****************************************************************************
 
81
** User variables
 
82
****************************************************************************/
 
83
unsigned char *get_var_key(user_var_entry *entry, size_t *length, bool )
 
84
{
 
85
  *length= entry->name.length;
 
86
  return (unsigned char*) entry->name.str;
 
87
}
 
88
 
 
89
void free_user_var(user_var_entry *entry)
 
90
{
 
91
  delete entry;
 
92
}
84
93
 
85
94
bool Key_part_spec::operator==(const Key_part_spec& other) const
86
95
{
87
96
  return length == other.length &&
88
97
         field_name.length == other.field_name.length &&
89
 
    !my_strcasecmp(system_charset_info, field_name.str, other.field_name.str);
 
98
         !strcmp(field_name.str, other.field_name.str);
90
99
}
91
100
 
92
 
Open_tables_state::Open_tables_state(uint64_t version_arg) :
93
 
  version(version_arg)
 
101
Open_tables_state::Open_tables_state(uint64_t version_arg)
 
102
  :version(version_arg), backups_available(false)
94
103
{
95
 
  open_tables= temporary_tables= derived_tables= NULL;
96
 
  extra_lock= lock= NULL;
 
104
  reset_open_tables_state();
97
105
}
98
106
 
99
107
/*
100
108
  The following functions form part of the C plugin API
101
109
*/
102
 
int mysql_tmpfile(const char *prefix)
 
110
extern "C" int mysql_tmpfile(const char *prefix)
103
111
{
104
112
  char filename[FN_REFLEN];
105
 
  int fd = internal::create_temp_file(filename, drizzle_tmpdir.c_str(), prefix, MYF(MY_WME));
 
113
  int fd = internal::create_temp_file(filename, drizzle_tmpdir, prefix, MYF(MY_WME));
106
114
  if (fd >= 0) {
107
115
    unlink(filename);
108
116
  }
110
118
  return fd;
111
119
}
112
120
 
 
121
extern "C"
113
122
int session_tablespace_op(const Session *session)
114
123
{
115
124
  return test(session->tablespace_op);
123
132
 
124
133
   @see Session::set_proc_info
125
134
 */
126
 
void set_session_proc_info(Session *session, const char *info)
 
135
extern "C" void
 
136
set_session_proc_info(Session *session, const char *info)
127
137
{
128
138
  session->set_proc_info(info);
129
139
}
130
140
 
 
141
extern "C"
131
142
const char *get_session_proc_info(Session *session)
132
143
{
133
144
  return session->get_proc_info();
134
145
}
135
146
 
136
 
void **Session::getEngineData(const plugin::MonitoredInTransaction *monitored)
137
 
{
138
 
  return static_cast<void **>(&ha_data[monitored->getId()].ha_ptr);
139
 
}
140
 
 
141
 
ResourceContext *Session::getResourceContext(const plugin::MonitoredInTransaction *monitored,
142
 
                                             size_t index)
143
 
{
144
 
  return &ha_data[monitored->getId()].resource_context[index];
145
 
}
146
 
 
 
147
void **Session::getEngineData(const plugin::StorageEngine *engine)
 
148
{
 
149
  return static_cast<void **>(&ha_data[engine->slot].ha_ptr);
 
150
}
 
151
 
 
152
Ha_trx_info *Session::getEngineInfo(const plugin::StorageEngine *engine,
 
153
                                    size_t index)
 
154
{
 
155
  return &ha_data[engine->getSlot()].ha_info[index];
 
156
}
 
157
 
 
158
extern "C"
147
159
int64_t session_test_options(const Session *session, int64_t test_options)
148
160
{
149
161
  return session->options & test_options;
150
162
}
151
163
 
 
164
extern "C"
152
165
int session_sql_command(const Session *session)
153
166
{
154
167
  return (int) session->lex->sql_command;
155
168
}
156
169
 
157
 
enum_tx_isolation session_tx_isolation(const Session *session)
 
170
extern "C"
 
171
int session_tx_isolation(const Session *session)
158
172
{
159
 
  return (enum_tx_isolation)session->variables.tx_isolation;
 
173
  return (int) session->variables.tx_isolation;
160
174
}
161
175
 
162
 
Session::Session(plugin::Client *client_arg) :
 
176
Session::Session(plugin::Client *client_arg)
 
177
  :
163
178
  Open_tables_state(refresh_version),
164
179
  mem_root(&main_mem_root),
165
 
  xa_id(0),
166
180
  lex(&main_lex),
167
 
  query(new std::string),
168
 
  _schema(new std::string("")),
169
 
  catalog("LOCAL"),
170
181
  client(client_arg),
171
182
  scheduler(NULL),
172
183
  scheduler_arg(NULL),
173
184
  lock_id(&main_lock_id),
174
185
  user_time(0),
175
 
  ha_data(plugin::num_trx_monitored_objects),
176
 
  concurrent_execute_allowed(true),
177
186
  arg_of_last_insert_id_function(false),
178
187
  first_successful_insert_id_in_prev_stmt(0),
179
188
  first_successful_insert_id_in_cur_stmt(0),
180
189
  limit_found_rows(0),
181
 
  _global_read_lock(NONE),
182
 
  _killed(NOT_KILLED),
 
190
  global_read_lock(0),
183
191
  some_tables_deleted(false),
184
192
  no_errors(false),
185
193
  password(false),
191
199
  m_lip(NULL),
192
200
  cached_table(0),
193
201
  transaction_message(NULL),
194
 
  statement_message(NULL),
195
 
  session_event_observers(NULL),
196
 
  use_usage(false)
 
202
  statement_message(NULL)
197
203
{
 
204
  memset(process_list_info, 0, PROCESS_LIST_WIDTH);
198
205
  client->setSession(this);
199
206
 
200
207
  /*
204
211
  */
205
212
  memory::init_sql_alloc(&main_mem_root, memory::ROOT_MIN_BLOCK_SIZE, 0);
206
213
  thread_stack= NULL;
207
 
  count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;
 
214
  count_cuted_fields= CHECK_FIELD_IGNORE;
 
215
  killed= NOT_KILLED;
208
216
  col_access= 0;
209
217
  tmp_table= 0;
210
218
  used_tables= 0;
220
228
  thread_id= 0;
221
229
  file_id = 0;
222
230
  query_id= 0;
 
231
  query= NULL;
 
232
  query_length= 0;
223
233
  warn_query_id= 0;
 
234
  memset(ha_data, 0, sizeof(ha_data));
224
235
  mysys_var= 0;
225
 
  scoreboard_index= -1;
226
236
  dbug_sentry=Session_SENTRY_MAGIC;
227
 
  cleanup_done= abort_on_warning= no_warnings_for_error= false;  
228
 
 
229
 
  /* query_cache init */
230
 
  query_cache_key= "";
231
 
  resultset= NULL;
 
237
  cleanup_done= abort_on_warning= no_warnings_for_error= false;
 
238
  pthread_mutex_init(&LOCK_delete, MY_MUTEX_INIT_FAST);
232
239
 
233
240
  /* Variables with default values */
234
241
  proc_info="login";
250
257
  else
251
258
    options &= ~OPTION_BIG_SELECTS;
252
259
 
 
260
  transaction.all.modified_non_trans_table= transaction.stmt.modified_non_trans_table= false;
253
261
  open_options=ha_open_options;
254
262
  update_lock_default= TL_WRITE;
255
263
  session_tx_isolation= (enum_tx_isolation) variables.tx_isolation;
260
268
 
261
269
  /* Initialize sub structures */
262
270
  memory::init_sql_alloc(&warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE);
 
271
  hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0,
 
272
            (hash_get_key) get_var_key,
 
273
            (hash_free_key) free_user_var, 0);
263
274
 
264
275
  substitute_null_with_insert_id = false;
265
 
  lock_info.init(); /* safety: will be reset after start */
 
276
  thr_lock_info_init(&lock_info); /* safety: will be reset after start */
266
277
  thr_lock_owner_init(&main_lock_id, &lock_info);
267
278
 
268
279
  m_internal_handler= NULL;
269
 
  
270
 
  plugin::EventObserver::registerSessionEvents(*this); 
271
280
}
272
281
 
273
282
void Session::free_items()
302
311
  return false;                                 // 'false', as per coding style
303
312
}
304
313
 
305
 
void Session::setAbort(bool arg)
306
 
{
307
 
  mysys_var->abort= arg;
308
 
}
309
 
 
310
 
void Session::lockOnSys()
311
 
{
312
 
  if (not mysys_var)
313
 
    return;
314
 
 
315
 
  setAbort(true);
316
 
  boost_unique_lock_t scopedLock(mysys_var->mutex);
317
 
  if (mysys_var->current_cond)
318
 
  {
319
 
    mysys_var->current_mutex->lock();
320
 
    mysys_var->current_cond->notify_all();
321
 
    mysys_var->current_mutex->unlock();
322
 
  }
323
 
}
324
 
 
325
314
void Session::pop_internal_handler()
326
315
{
327
316
  assert(m_internal_handler != NULL);
328
317
  m_internal_handler= NULL;
329
318
}
330
319
 
331
 
void Session::get_xid(DRIZZLE_XID *xid)
332
 
{
333
 
  *xid = *(DRIZZLE_XID *) &transaction.xid_state.xid;
334
 
}
 
320
#if defined(__cplusplus)
 
321
extern "C" {
 
322
#endif
 
323
 
 
324
void *session_alloc(Session *session, unsigned int size)
 
325
{
 
326
  return session->alloc(size);
 
327
}
 
328
 
 
329
void *session_calloc(Session *session, unsigned int size)
 
330
{
 
331
  return session->calloc(size);
 
332
}
 
333
 
 
334
char *session_strdup(Session *session, const char *str)
 
335
{
 
336
  return session->strdup(str);
 
337
}
 
338
 
 
339
char *session_strmake(Session *session, const char *str, unsigned int size)
 
340
{
 
341
  return session->strmake(str, size);
 
342
}
 
343
 
 
344
void *session_memdup(Session *session, const void* str, unsigned int size)
 
345
{
 
346
  return session->memdup(str, size);
 
347
}
 
348
 
 
349
void session_get_xid(const Session *session, DRIZZLE_XID *xid)
 
350
{
 
351
  *xid = *(DRIZZLE_XID *) &session->transaction.xid_state.xid;
 
352
}
 
353
 
 
354
#if defined(__cplusplus)
 
355
}
 
356
#endif
335
357
 
336
358
/* Do operations that may take a long time */
337
359
 
339
361
{
340
362
  assert(cleanup_done == false);
341
363
 
342
 
  setKilled(KILL_CONNECTION);
 
364
  killed= KILL_CONNECTION;
343
365
#ifdef ENABLE_WHEN_BINLOG_WILL_BE_ABLE_TO_PREPARE
344
366
  if (transaction.xid_state.xa_state == XA_PREPARED)
345
367
  {
348
370
#endif
349
371
  {
350
372
    TransactionServices &transaction_services= TransactionServices::singleton();
351
 
    transaction_services.rollbackTransaction(this, true);
 
373
    transaction_services.ha_rollback_trans(this, true);
352
374
    xid_cache_delete(&transaction.xid_state);
353
375
  }
354
 
 
355
 
  for (UserVars::iterator iter= user_vars.begin();
356
 
       iter != user_vars.end();
357
 
       iter++)
358
 
  {
359
 
    user_var_entry *entry= (*iter).second;
360
 
    delete entry;
361
 
  }
362
 
  user_vars.clear();
363
 
 
364
 
 
 
376
  hash_free(&user_vars);
365
377
  close_temporary_tables();
366
378
 
367
379
  if (global_read_lock)
368
 
  {
369
 
    unlockGlobalReadLock();
370
 
  }
 
380
    unlock_global_read_lock(this);
371
381
 
372
382
  cleanup_done= true;
373
383
}
374
384
 
375
385
Session::~Session()
376
386
{
377
 
  this->checkSentry();
 
387
  Session_CHECK_SENTRY(this);
 
388
  add_to_status(&global_status_var, &status_var);
378
389
 
379
390
  if (client->isConnected())
380
391
  {
381
392
    if (global_system_variables.log_warnings)
382
393
        errmsg_printf(ERRMSG_LVL_WARN, ER(ER_FORCING_CLOSE),internal::my_progname,
383
394
                      thread_id,
384
 
                      (getSecurityContext().getUser().c_str() ?
385
 
                       getSecurityContext().getUser().c_str() : ""));
 
395
                      (security_ctx.user.c_str() ?
 
396
                       security_ctx.user.c_str() : ""));
386
397
    disconnect(0, false);
387
398
  }
388
399
 
396
407
  plugin::StorageEngine::closeConnection(this);
397
408
  plugin_sessionvar_cleanup(this);
398
409
 
399
 
  warn_root.free_root(MYF(0));
 
410
  free_root(&warn_root,MYF(0));
400
411
  mysys_var=0;                                  // Safety (shouldn't be needed)
401
412
  dbug_sentry= Session_SENTRY_GONE;
402
413
 
403
 
  main_mem_root.free_root(MYF(0));
404
 
  currentMemRoot().release();
405
 
  currentSession().release();
406
 
 
407
 
  plugin::Logging::postEndDo(this);
408
 
  plugin::EventObserver::deregisterSessionEvents(*this); 
409
 
 
410
 
  for (PropertyMap::iterator iter= life_properties.begin(); iter != life_properties.end(); iter++)
411
 
  {
412
 
    delete (*iter).second;
413
 
  }
414
 
  life_properties.clear();
415
 
}
416
 
 
417
 
void Session::setClient(plugin::Client *client_arg)
418
 
{
419
 
  client= client_arg;
420
 
  client->setSession(this);
421
 
}
422
 
 
423
 
void Session::awake(Session::killed_state_t state_to_set)
424
 
{
425
 
  if ((state_to_set == Session::KILL_QUERY) and (command == COM_SLEEP))
426
 
    return;
427
 
 
428
 
  this->checkSentry();
429
 
 
430
 
  setKilled(state_to_set);
431
 
  scheduler->killSession(this);
432
 
 
 
414
  free_root(&main_mem_root, MYF(0));
 
415
  pthread_setspecific(THR_Session,  0);
 
416
 
 
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(STATUS_VAR *to_var, STATUS_VAR *from_var)
 
437
{
 
438
  ulong *end= (ulong*) ((unsigned char*) to_var +
 
439
                        offsetof(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(STATUS_VAR *to_var, STATUS_VAR *from_var,
 
460
                        STATUS_VAR *dec_var)
 
461
{
 
462
  ulong *end= (ulong*) ((unsigned char*) to_var + offsetof(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;
433
477
  if (state_to_set != Session::KILL_QUERY)
434
478
  {
 
479
    scheduler->killSession(this);
435
480
    DRIZZLE_CONNECTION_DONE(thread_id);
436
481
  }
437
 
 
438
482
  if (mysys_var)
439
483
  {
440
 
    boost_unique_lock_t scopedLock(mysys_var->mutex);
 
484
    pthread_mutex_lock(&mysys_var->mutex);
441
485
    /*
442
 
      "
443
486
      This broadcast could be up in the air if the victim thread
444
487
      exits the cond in the time between read and broadcast, but that is
445
488
      ok since all we want to do is to make the victim thread get out
460
503
    */
461
504
    if (mysys_var->current_cond && mysys_var->current_mutex)
462
505
    {
463
 
      mysys_var->current_mutex->lock();
464
 
      mysys_var->current_cond->notify_all();
465
 
      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);
466
509
    }
 
510
    pthread_mutex_unlock(&mysys_var->mutex);
467
511
  }
468
512
}
469
513
 
479
523
  */
480
524
  assert(thread_stack);
481
525
 
482
 
  currentSession().release();
483
 
  currentSession().reset(this);
484
 
 
485
 
  currentMemRoot().release();
486
 
  currentMemRoot().reset(&mem_root);
 
526
  if (pthread_setspecific(THR_Session,  this) ||
 
527
      pthread_setspecific(THR_Mem_root, &mem_root))
 
528
    return true;
487
529
 
488
530
  mysys_var=my_thread_var;
489
531
 
492
534
    This allows us to move Session to different threads if needed.
493
535
  */
494
536
  mysys_var->id= thread_id;
 
537
  real_id= pthread_self();                      // For debugging
495
538
 
496
539
  /*
497
540
    We have to call thr_lock_info_init() again here as Session may have been
498
541
    created in another thread
499
542
  */
500
 
  lock_info.init();
501
 
 
 
543
  thr_lock_info_init(&lock_info);
502
544
  return false;
503
545
}
504
546
 
518
560
  command= COM_SLEEP;
519
561
  set_time();
520
562
 
521
 
  mem_root->reset_root_defaults(variables.query_alloc_block_size,
522
 
                                variables.query_prealloc_size);
 
563
  reset_root_defaults(mem_root, variables.query_alloc_block_size,
 
564
                      variables.query_prealloc_size);
523
565
  transaction.xid_state.xid.null();
524
566
  transaction.xid_state.in_session=1;
525
 
  if (use_usage)
526
 
    resetUsage();
527
567
}
528
568
 
529
569
bool Session::initGlobals()
531
571
  if (storeGlobals())
532
572
  {
533
573
    disconnect(ER_OUT_OF_RESOURCES, true);
534
 
    status_var.aborted_connects++;
 
574
    statistic_increment(aborted_connects, &LOCK_status);
535
575
    return true;
536
576
  }
537
577
  return false;
547
587
 
548
588
  prepareForQueries();
549
589
 
550
 
  while (not client->haveError() && getKilled() != KILL_CONNECTION)
 
590
  while (! client->haveError() && killed != KILL_CONNECTION)
551
591
  {
552
 
    if (not executeStatement())
 
592
    if (! executeStatement())
553
593
      break;
554
594
  }
555
595
 
556
596
  disconnect(0, true);
557
597
}
558
598
 
559
 
bool Session::schedule(Session::shared_ptr &arg)
 
599
bool Session::schedule()
560
600
{
561
 
  arg->scheduler= plugin::Scheduler::getScheduler();
562
 
  assert(arg->scheduler);
 
601
  scheduler= plugin::Scheduler::getScheduler();
 
602
  assert(scheduler);
563
603
 
564
604
  connection_count.increment();
565
605
 
566
 
  if (connection_count > current_global_counters.max_used_connections)
567
 
  {
568
 
    current_global_counters.max_used_connections= connection_count;
569
 
  }
570
 
 
571
 
  current_global_counters.connections++;
572
 
  arg->thread_id= arg->variables.pseudo_thread_id= global_thread_id++;
573
 
 
574
 
  session::Cache::singleton().insert(arg);
575
 
 
576
 
  if (unlikely(plugin::EventObserver::connectSession(*arg)))
577
 
  {
578
 
    // We should do something about an error...
579
 
  }
580
 
 
581
 
  if (plugin::Scheduler::getScheduler()->addSession(arg))
582
 
  {
583
 
    DRIZZLE_CONNECTION_START(arg->getSessionId());
 
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);
584
618
    char error_message_buff[DRIZZLE_ERRMSG_SIZE];
585
619
 
586
 
    arg->setKilled(Session::KILL_CONNECTION);
 
620
    killed= Session::KILL_CONNECTION;
587
621
 
588
 
    arg->status_var.aborted_connects++;
 
622
    statistic_increment(aborted_connects, &LOCK_status);
589
623
 
590
624
    /* Can't use my_error() since store_globals has not been called. */
591
625
    /* TODO replace will better error message */
592
626
    snprintf(error_message_buff, sizeof(error_message_buff),
593
627
             ER(ER_CANT_CREATE_THREAD), 1);
594
 
    arg->client->sendError(ER_CANT_CREATE_THREAD, error_message_buff);
595
 
 
 
628
    client->sendError(ER_CANT_CREATE_THREAD, error_message_buff);
596
629
    return true;
597
630
  }
598
631
 
600
633
}
601
634
 
602
635
 
603
 
/*
604
 
  Is this session viewable by the current user?
605
 
*/
606
 
bool Session::isViewable() const
607
 
{
608
 
  return plugin::Authorization::isAuthorized(current_session->getSecurityContext(),
609
 
                                             this,
610
 
                                             false);
611
 
}
612
 
 
613
 
 
614
 
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)
615
639
{
616
640
  const char* old_msg = get_proc_info();
617
641
  safe_mutex_assert_owner(mutex);
618
 
  mysys_var->current_mutex = &mutex;
619
 
  mysys_var->current_cond = &cond;
 
642
  mysys_var->current_mutex = mutex;
 
643
  mysys_var->current_cond = cond;
620
644
  this->set_proc_info(msg);
621
645
  return old_msg;
622
646
}
629
653
    locked (if that would not be the case, you'll get a deadlock if someone
630
654
    does a Session::awake() on you).
631
655
  */
632
 
  mysys_var->current_mutex->unlock();
633
 
  boost_unique_lock_t scopedLock(mysys_var->mutex);
 
656
  pthread_mutex_unlock(mysys_var->current_mutex);
 
657
  pthread_mutex_lock(&mysys_var->mutex);
634
658
  mysys_var->current_mutex = 0;
635
659
  mysys_var->current_cond = 0;
636
660
  this->set_proc_info(old_msg);
 
661
  pthread_mutex_unlock(&mysys_var->mutex);
637
662
}
638
663
 
639
664
bool Session::authenticate()
640
665
{
641
 
  lex->start(this);
 
666
  lex_start(this);
642
667
  if (client->authenticate())
643
668
    return false;
644
669
 
645
 
  status_var.aborted_connects++;
646
 
 
 
670
  statistic_increment(aborted_connects, &LOCK_status);
647
671
  return true;
648
672
}
649
673
 
650
 
bool Session::checkUser(const std::string &passwd_str,
651
 
                        const std::string &in_db)
 
674
bool Session::checkUser(const char *passwd, uint32_t passwd_len, const char *in_db)
652
675
{
653
 
  bool is_authenticated=
654
 
    plugin::Authentication::isAuthenticated(getSecurityContext(),
655
 
                                            passwd_str);
 
676
  LEX_STRING db_str= { (char *) in_db, in_db ? strlen(in_db) : 0 };
 
677
  bool is_authenticated;
 
678
 
 
679
  if (passwd_len != 0 && passwd_len != SCRAMBLE_LENGTH)
 
680
  {
 
681
    my_error(ER_HANDSHAKE_ERROR, MYF(0), security_ctx.ip.c_str());
 
682
    return false;
 
683
  }
 
684
 
 
685
  is_authenticated= plugin::Authentication::isAuthenticated(this, passwd);
656
686
 
657
687
  if (is_authenticated != true)
658
688
  {
659
 
    status_var.access_denied++;
660
 
    /* isAuthenticated has pushed the error message */
 
689
    my_error(ER_ACCESS_DENIED_ERROR, MYF(0),
 
690
             security_ctx.user.c_str(),
 
691
             security_ctx.ip.c_str(),
 
692
             passwd_len ? ER(ER_YES) : ER(ER_NO));
 
693
 
661
694
    return false;
662
695
  }
663
696
 
 
697
  security_ctx.skip_grants();
 
698
 
664
699
  /* Change database if necessary */
665
 
  if (not in_db.empty())
 
700
  if (in_db && in_db[0])
666
701
  {
667
 
    SchemaIdentifier identifier(in_db);
668
 
    if (mysql_change_db(this, identifier))
 
702
    if (mysql_change_db(this, &db_str, false))
669
703
    {
670
704
      /* mysql_change_db() has pushed the error message. */
671
705
      return false;
672
706
    }
673
707
  }
674
708
  my_ok();
675
 
  password= not passwd_str.empty();
 
709
  password= test(passwd_len);          // remember for error messages
676
710
 
677
711
  /* Ready to handle queries */
678
712
  return true;
694
728
  main_da.reset_diagnostics_area();
695
729
 
696
730
  if (client->readCommand(&l_packet, &packet_length) == false)
697
 
  {
698
 
    return false;
699
 
  }
700
 
 
701
 
  if (getKilled() == KILL_CONNECTION)
702
731
    return false;
703
732
 
704
733
  if (packet_length == 0)
705
734
    return true;
706
735
 
707
 
  l_command= static_cast<enum_server_command>(l_packet[0]);
 
736
  l_command= (enum enum_server_command) (unsigned char) l_packet[0];
708
737
 
709
738
  if (command >= COM_END)
710
739
    command= COM_END;                           // Wrong command
711
740
 
712
741
  assert(packet_length);
713
 
  return not dispatch_command(l_command, this, l_packet+1, (uint32_t) (packet_length-1));
 
742
  return ! dispatch_command(l_command, this, l_packet+1, (uint32_t) (packet_length-1));
714
743
}
715
744
 
716
745
bool Session::readAndStoreQuery(const char *in_packet, uint32_t in_packet_length)
722
751
    in_packet_length--;
723
752
  }
724
753
  const char *pos= in_packet + in_packet_length; /* Point at end null */
725
 
  while (in_packet_length > 0 && (pos[-1] == ';' || my_isspace(charset() ,pos[-1])))
 
754
  while (in_packet_length > 0 &&
 
755
         (pos[-1] == ';' || my_isspace(charset() ,pos[-1])))
726
756
  {
727
757
    pos--;
728
758
    in_packet_length--;
729
759
  }
730
760
 
731
 
  std::string *new_query= new std::string(in_packet, in_packet + in_packet_length);
732
 
  // We can not be entirely sure _schema has a value
733
 
  if (_schema)
734
 
  {
735
 
    plugin::QueryRewriter::rewriteQuery(*_schema, *new_query);
736
 
  }
737
 
  query.reset(new_query);
738
 
  _state.reset(new State(in_packet, in_packet_length));
 
761
  /* We must allocate some extra memory for the cached query string */
 
762
  query_length= 0; /* Extra safety: Avoid races */
 
763
  query= (char*) memdup_w_gap((unsigned char*) in_packet, in_packet_length, db.length() + 1);
 
764
  if (! query)
 
765
    return false;
 
766
 
 
767
  query[in_packet_length]=0;
 
768
  query_length= in_packet_length;
739
769
 
740
770
  return true;
741
771
}
760
790
       * (Which of course should never happen...)
761
791
       */
762
792
      server_status&= ~SERVER_STATUS_IN_TRANS;
763
 
      if (transaction_services.commitTransaction(this, true))
 
793
      if (transaction_services.ha_commit_trans(this, true))
764
794
        result= false;
765
795
      options&= ~(OPTION_BEGIN);
 
796
      transaction.all.modified_non_trans_table= false;
766
797
      break;
767
798
    case COMMIT_RELEASE:
768
799
      do_release= 1; /* fall through */
777
808
    case ROLLBACK_AND_CHAIN:
778
809
    {
779
810
      server_status&= ~SERVER_STATUS_IN_TRANS;
780
 
      if (transaction_services.rollbackTransaction(this, true))
 
811
      if (transaction_services.ha_rollback_trans(this, true))
781
812
        result= false;
782
813
      options&= ~(OPTION_BEGIN);
 
814
      transaction.all.modified_non_trans_table= false;
783
815
      if (result == true && (completion == ROLLBACK_AND_CHAIN))
784
816
        result= startTransaction();
785
817
      break;
790
822
  }
791
823
 
792
824
  if (result == false)
793
 
  {
794
825
    my_error(killed_errno(), MYF(0));
795
 
  }
796
826
  else if ((result == true) && do_release)
797
 
  {
798
 
    setKilled(Session::KILL_CONNECTION);
799
 
  }
 
827
    killed= Session::KILL_CONNECTION;
800
828
 
801
829
  return result;
802
830
}
814
842
  if (options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
815
843
  {
816
844
    server_status&= ~SERVER_STATUS_IN_TRANS;
817
 
    if (transaction_services.commitTransaction(this, true))
 
845
    if (transaction_services.ha_commit_trans(this, true))
818
846
      result= false;
819
847
  }
820
848
  options&= ~(OPTION_BEGIN);
 
849
  transaction.all.modified_non_trans_table= false;
821
850
  return result;
822
851
}
823
852
 
834
863
    options|= OPTION_BEGIN;
835
864
    server_status|= SERVER_STATUS_IN_TRANS;
836
865
 
837
 
    if (plugin::TransactionalStorageEngine::notifyStartTransaction(this, opt))
 
866
    if (opt == START_TRANS_OPT_WITH_CONS_SNAPSHOT)
838
867
    {
839
 
      result= false;
 
868
      // TODO make this a loop for all engines, not just this one (Inno only
 
869
      // right now)
 
870
      if (plugin::StorageEngine::startConsistentSnapshot(this))
 
871
      {
 
872
        result= false;
 
873
      }
840
874
    }
841
875
  }
842
876
 
865
899
  free_items();
866
900
  /* Reset where. */
867
901
  where= Session::DEFAULT_WHERE;
868
 
 
869
 
  /* Reset the temporary shares we built */
870
 
  for_each(temporary_shares.begin(),
871
 
           temporary_shares.end(),
872
 
           DeletePtr());
873
 
  temporary_shares.clear();
874
902
}
875
903
 
876
904
/**
884
912
  @return  NULL on failure, or pointer to the LEX_STRING object
885
913
*/
886
914
LEX_STRING *Session::make_lex_string(LEX_STRING *lex_str,
887
 
                                     const std::string &str,
888
 
                                     bool allocate_lex_string)
889
 
{
890
 
  return make_lex_string(lex_str, str.c_str(), str.length(), allocate_lex_string);
891
 
}
892
 
 
893
 
LEX_STRING *Session::make_lex_string(LEX_STRING *lex_str,
894
 
                                     const char* str, uint32_t length,
895
 
                                     bool allocate_lex_string)
 
915
                                 const char* str, uint32_t length,
 
916
                                 bool allocate_lex_string)
896
917
{
897
918
  if (allocate_lex_string)
898
919
    if (!(lex_str= (LEX_STRING *)alloc(sizeof(LEX_STRING))))
899
920
      return 0;
900
 
  if (!(lex_str->str= mem_root->strmake_root(str, length)))
 
921
  if (!(lex_str->str= strmake_root(mem_root, str, length)))
901
922
    return 0;
902
923
  lex_str->length= length;
903
924
  return lex_str;
955
976
  my_message(errcode, err, MYF(0));
956
977
  if (file > 0)
957
978
  {
958
 
    (void) cache->end_io_cache();
 
979
    (void) end_io_cache(cache);
959
980
    (void) internal::my_close(file, MYF(0));
960
 
    (void) internal::my_delete(path.file_string().c_str(), MYF(0));             // Delete file on error
 
981
    (void) internal::my_delete(path, MYF(0));           // Delete file on error
961
982
    file= -1;
962
983
  }
963
984
}
965
986
 
966
987
bool select_to_file::send_eof()
967
988
{
968
 
  int error= test(cache->end_io_cache());
 
989
  int error= test(end_io_cache(cache));
969
990
  if (internal::my_close(file, MYF(MY_WME)))
970
991
    error= 1;
971
992
  if (!error)
987
1008
  /* In case of error send_eof() may be not called: close the file here. */
988
1009
  if (file >= 0)
989
1010
  {
990
 
    (void) cache->end_io_cache();
 
1011
    (void) end_io_cache(cache);
991
1012
    (void) internal::my_close(file, MYF(0));
992
1013
    file= -1;
993
1014
  }
994
 
  path= "";
 
1015
  path[0]= '\0';
995
1016
  row_count= 0;
996
1017
}
997
1018
 
1001
1022
    cache(static_cast<internal::IO_CACHE *>(memory::sql_calloc(sizeof(internal::IO_CACHE)))),
1002
1023
    row_count(0L)
1003
1024
{
1004
 
  path= "";
 
1025
  path[0]=0;
1005
1026
}
1006
1027
 
1007
1028
select_to_file::~select_to_file()
1035
1056
*/
1036
1057
 
1037
1058
 
1038
 
static int create_file(Session *session,
1039
 
                       fs::path &target_path,
1040
 
                       file_exchange *exchange,
1041
 
                       internal::IO_CACHE *cache)
 
1059
static int create_file(Session *session, char *path, file_exchange *exchange, internal::IO_CACHE *cache)
1042
1060
{
1043
 
  fs::path to_file(exchange->file_name);
1044
1061
  int file;
1045
 
 
1046
 
  if (not to_file.has_root_directory())
 
1062
  uint32_t option= MY_UNPACK_FILENAME | MY_RELATIVE_PATH;
 
1063
 
 
1064
#ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS
 
1065
  option|= MY_REPLACE_DIR;                      // Force use of db directory
 
1066
#endif
 
1067
 
 
1068
  if (!internal::dirname_length(exchange->file_name))
1047
1069
  {
1048
 
    target_path= fs::system_complete(getDataHomeCatalog());
1049
 
    util::string::const_shared_ptr schema(session->schema());
1050
 
    if (schema and not schema->empty())
1051
 
    {
1052
 
      int count_elements= 0;
1053
 
      for (fs::path::iterator iter= to_file.begin();
1054
 
           iter != to_file.end();
1055
 
           ++iter, ++count_elements)
1056
 
      { }
1057
 
 
1058
 
      if (count_elements == 1)
1059
 
      {
1060
 
        target_path /= *schema;
1061
 
      }
1062
 
    }
1063
 
    target_path /= to_file;
 
1070
    strcpy(path, drizzle_real_data_home);
 
1071
    if (! session->db.empty())
 
1072
      strncat(path, session->db.c_str(), FN_REFLEN-strlen(drizzle_real_data_home)-1);
 
1073
    (void) internal::fn_format(path, exchange->file_name, path, "", option);
1064
1074
  }
1065
1075
  else
1066
 
  {
1067
 
    target_path = exchange->file_name;
1068
 
  }
1069
 
 
1070
 
  if (not secure_file_priv.string().empty())
1071
 
  {
1072
 
    if (target_path.file_string().substr(0, secure_file_priv.file_string().size()) != secure_file_priv.file_string())
1073
 
    {
1074
 
      /* Write only allowed to dir or subdir specified by secure_file_priv */
1075
 
      my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
1076
 
      return -1;
1077
 
    }
1078
 
  }
1079
 
 
1080
 
  if (!access(target_path.file_string().c_str(), F_OK))
 
1076
    (void) internal::fn_format(path, exchange->file_name, drizzle_real_data_home, "", option);
 
1077
 
 
1078
  if (opt_secure_file_priv &&
 
1079
      strncmp(opt_secure_file_priv, path, strlen(opt_secure_file_priv)))
 
1080
  {
 
1081
    /* Write only allowed to dir or subdir specified by secure_file_priv */
 
1082
    my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
 
1083
    return -1;
 
1084
  }
 
1085
 
 
1086
  if (!access(path, F_OK))
1081
1087
  {
1082
1088
    my_error(ER_FILE_EXISTS_ERROR, MYF(0), exchange->file_name);
1083
1089
    return -1;
1084
1090
  }
1085
1091
  /* Create the file world readable */
1086
 
  if ((file= internal::my_create(target_path.file_string().c_str(), 0666, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0)
 
1092
  if ((file= internal::my_create(path, 0666, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0)
1087
1093
    return file;
1088
1094
  (void) fchmod(file, 0666);                    // Because of umask()
1089
 
  if (cache->init_io_cache(file, 0L, internal::WRITE_CACHE, 0L, 1, MYF(MY_WME)))
 
1095
  if (init_io_cache(cache, file, 0L, internal::WRITE_CACHE, 0L, 1, MYF(MY_WME)))
1090
1096
  {
1091
1097
    internal::my_close(file, MYF(0));
1092
 
    internal::my_delete(target_path.file_string().c_str(), MYF(0));  // Delete file on error, it was just created
 
1098
    internal::my_delete(path, MYF(0));  // Delete file on error, it was just created
1093
1099
    return -1;
1094
1100
  }
1095
1101
  return file;
1103
1109
  bool string_results= false, non_string_results= false;
1104
1110
  unit= u;
1105
1111
  if ((uint32_t) strlen(exchange->file_name) + NAME_LEN >= FN_REFLEN)
1106
 
  {
1107
 
    path= exchange->file_name;
1108
 
  }
 
1112
    strncpy(path,exchange->file_name,FN_REFLEN-1);
1109
1113
 
1110
1114
  /* Check if there is any blobs in data */
1111
1115
  {
1115
1119
    {
1116
1120
      if (item->max_length >= MAX_BLOB_WIDTH)
1117
1121
      {
1118
 
        blob_flag=1;
1119
 
        break;
 
1122
        blob_flag=1;
 
1123
        break;
1120
1124
      }
1121
 
 
1122
1125
      if (item->result_type() == STRING_RESULT)
1123
1126
        string_results= true;
1124
1127
      else
1159
1162
  return 0;
1160
1163
}
1161
1164
 
 
1165
 
 
1166
#define NEED_ESCAPING(x) ((int) (unsigned char) (x) == escape_char    || \
 
1167
                          (enclosed ? (int) (unsigned char) (x) == field_sep_char      \
 
1168
                                    : (int) (unsigned char) (x) == field_term_char) || \
 
1169
                          (int) (unsigned char) (x) == line_sep_char  || \
 
1170
                          !(x))
 
1171
 
1162
1172
bool select_export::send_data(List<Item> &items)
1163
1173
{
1164
1174
  char buff[MAX_FIELD_WIDTH],null_buff[2],space[MAX_FIELD_WIDTH];
1169
1179
  if (unit->offset_limit_cnt)
1170
1180
  {                                             // using limit offset,count
1171
1181
    unit->offset_limit_cnt--;
1172
 
    return false;
 
1182
    return(0);
1173
1183
  }
1174
1184
  row_count++;
1175
1185
  Item *item;
1178
1188
 
1179
1189
  if (my_b_write(cache,(unsigned char*) exchange->line_start->ptr(),
1180
1190
                 exchange->line_start->length()))
1181
 
    return true;
1182
 
 
 
1191
    goto err;
1183
1192
  while ((item=li++))
1184
1193
  {
1185
1194
    Item_result result_type=item->result_type();
1190
1199
    {
1191
1200
      if (my_b_write(cache,(unsigned char*) exchange->enclosed->ptr(),
1192
1201
                     exchange->enclosed->length()))
1193
 
        return true;
 
1202
        goto err;
1194
1203
    }
1195
1204
    if (!res)
1196
1205
    {                                           // NULL
1201
1210
          null_buff[0]=escape_char;
1202
1211
          null_buff[1]='N';
1203
1212
          if (my_b_write(cache,(unsigned char*) null_buff,2))
1204
 
            return true;
 
1213
            goto err;
1205
1214
        }
1206
1215
        else if (my_b_write(cache,(unsigned char*) "NULL",4))
1207
 
          return true;
 
1216
          goto err;
1208
1217
      }
1209
1218
      else
1210
1219
      {
1214
1223
    else
1215
1224
    {
1216
1225
      if (fixed_row_size)
1217
 
        used_length= min(res->length(), static_cast<size_t>(item->max_length));
 
1226
        used_length= min(res->length(),item->max_length);
1218
1227
      else
1219
1228
        used_length= res->length();
1220
1229
 
1276
1285
            assert before the loop makes that sure.
1277
1286
          */
1278
1287
 
1279
 
          if ((needs_escaping(*pos, enclosed) ||
 
1288
          if ((NEED_ESCAPING(*pos) ||
1280
1289
               (check_second_byte &&
1281
1290
                my_mbcharlen(character_set_client, (unsigned char) *pos) == 2 &&
1282
1291
                pos + 1 < end &&
1283
 
                needs_escaping(pos[1], enclosed))) &&
 
1292
                NEED_ESCAPING(pos[1]))) &&
1284
1293
              /*
1285
1294
                Don't escape field_term_char by doubling - doubling is only
1286
1295
                valid for ENCLOSED BY characters:
1295
1304
            tmp_buff[1]= *pos ? *pos : '0';
1296
1305
            if (my_b_write(cache,(unsigned char*) start,(uint32_t) (pos-start)) ||
1297
1306
                my_b_write(cache,(unsigned char*) tmp_buff,2))
1298
 
              return true;
 
1307
              goto err;
1299
1308
            start=pos+1;
1300
1309
          }
1301
1310
        }
1302
1311
        if (my_b_write(cache,(unsigned char*) start,(uint32_t) (pos-start)))
1303
 
          return true;
 
1312
          goto err;
1304
1313
      }
1305
1314
      else if (my_b_write(cache,(unsigned char*) res->ptr(),used_length))
1306
 
        return true;
 
1315
        goto err;
1307
1316
    }
1308
1317
    if (fixed_row_size)
1309
1318
    {                                           // Fill with space
1319
1328
        for (; length > sizeof(space) ; length-=sizeof(space))
1320
1329
        {
1321
1330
          if (my_b_write(cache,(unsigned char*) space,sizeof(space)))
1322
 
            return true;
 
1331
            goto err;
1323
1332
        }
1324
1333
        if (my_b_write(cache,(unsigned char*) space,length))
1325
 
          return true;
 
1334
          goto err;
1326
1335
      }
1327
1336
    }
1328
1337
    if (res && enclosed)
1329
1338
    {
1330
1339
      if (my_b_write(cache, (unsigned char*) exchange->enclosed->ptr(),
1331
1340
                     exchange->enclosed->length()))
1332
 
        return true;
 
1341
        goto err;
1333
1342
    }
1334
1343
    if (--items_left)
1335
1344
    {
1336
1345
      if (my_b_write(cache, (unsigned char*) exchange->field_term->ptr(),
1337
1346
                     field_term_length))
1338
 
        return true;
 
1347
        goto err;
1339
1348
    }
1340
1349
  }
1341
1350
  if (my_b_write(cache,(unsigned char*) exchange->line_term->ptr(),
1342
1351
                 exchange->line_term->length()))
1343
 
  {
1344
 
    return true;
1345
 
  }
1346
 
 
1347
 
  return false;
 
1352
    goto err;
 
1353
  return(0);
 
1354
err:
 
1355
  return(1);
1348
1356
}
1349
1357
 
1350
1358
 
1377
1385
  if (row_count++ > 1)
1378
1386
  {
1379
1387
    my_message(ER_TOO_MANY_ROWS, ER(ER_TOO_MANY_ROWS), MYF(0));
1380
 
    return 1;
 
1388
    goto err;
1381
1389
  }
1382
1390
  while ((item=li++))
1383
1391
  {
1385
1393
    if (!res)                                   // If NULL
1386
1394
    {
1387
1395
      if (my_b_write(cache,(unsigned char*) "",1))
1388
 
        return 1;
 
1396
        goto err;
1389
1397
    }
1390
1398
    else if (my_b_write(cache,(unsigned char*) res->ptr(),res->length()))
1391
1399
    {
1392
 
      my_error(ER_ERROR_ON_WRITE, MYF(0), path.file_string().c_str(), errno);
1393
 
      return 1;
 
1400
      my_error(ER_ERROR_ON_WRITE, MYF(0), path, errno);
 
1401
      goto err;
1394
1402
    }
1395
1403
  }
1396
1404
  return(0);
 
1405
err:
 
1406
  return(1);
1397
1407
}
1398
1408
 
1399
1409
 
1451
1461
      switch (val_item->result_type())
1452
1462
      {
1453
1463
      case REAL_RESULT:
1454
 
        op= &select_max_min_finder_subselect::cmp_real;
1455
 
        break;
 
1464
        op= &select_max_min_finder_subselect::cmp_real;
 
1465
        break;
1456
1466
      case INT_RESULT:
1457
 
        op= &select_max_min_finder_subselect::cmp_int;
1458
 
        break;
 
1467
        op= &select_max_min_finder_subselect::cmp_int;
 
1468
        break;
1459
1469
      case STRING_RESULT:
1460
 
        op= &select_max_min_finder_subselect::cmp_str;
1461
 
        break;
 
1470
        op= &select_max_min_finder_subselect::cmp_str;
 
1471
        break;
1462
1472
      case DECIMAL_RESULT:
1463
1473
        op= &select_max_min_finder_subselect::cmp_decimal;
1464
1474
        break;
1465
1475
      case ROW_RESULT:
1466
1476
        // This case should never be choosen
1467
 
        assert(0);
1468
 
        op= 0;
 
1477
        assert(0);
 
1478
        op= 0;
1469
1479
      }
1470
1480
    }
1471
1481
    cache->store(val_item);
1554
1564
void Session::end_statement()
1555
1565
{
1556
1566
  /* Cleanup SQL processing state to reuse this statement in next query. */
1557
 
  lex->end();
1558
 
  query_cache_key= ""; // reset the cache key
1559
 
  resetResultsetMessage();
 
1567
  lex_end(lex);
1560
1568
}
1561
1569
 
1562
1570
bool Session::copy_db_to(char **p_db, size_t *p_db_length)
1563
1571
{
1564
 
  assert(_schema);
1565
 
  if (_schema and _schema->empty())
1566
 
  {
1567
 
    my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
1568
 
    return true;
1569
 
  }
1570
 
  else if (not _schema)
1571
 
  {
1572
 
    my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
1573
 
    return true;
1574
 
  }
1575
 
  assert(_schema);
1576
 
 
1577
 
  *p_db= strmake(_schema->c_str(), _schema->size());
1578
 
  *p_db_length= _schema->size();
1579
 
 
 
1572
  if (db.empty())
 
1573
  {
 
1574
    my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
 
1575
    return true;
 
1576
  }
 
1577
  *p_db= strmake(db.c_str(), db.length());
 
1578
  *p_db_length= db.length();
1580
1579
  return false;
1581
1580
}
1582
1581
 
1591
1590
  quick_group= 1;
1592
1591
  table_charset= 0;
1593
1592
  precomputed_group_by= 0;
 
1593
  bit_fields_as_long= 0;
1594
1594
}
1595
1595
 
1596
1596
void Tmp_Table_Param::cleanup(void)
1615
1615
  memset(&status_var, 0, sizeof(status_var));
1616
1616
}
1617
1617
 
1618
 
 
1619
 
void Session::set_db(const std::string &new_db)
 
1618
void Security_context::skip_grants()
 
1619
{
 
1620
  /* privileges for the user are unknown everything is allowed */
 
1621
}
 
1622
 
 
1623
 
 
1624
/****************************************************************************
 
1625
  Handling of open and locked tables states.
 
1626
 
 
1627
  This is used when we want to open/lock (and then close) some tables when
 
1628
  we already have a set of tables open and locked. We use these methods for
 
1629
  access to mysql.proc table to find definitions of stored routines.
 
1630
****************************************************************************/
 
1631
 
 
1632
void Session::reset_n_backup_open_tables_state(Open_tables_state *backup)
 
1633
{
 
1634
  backup->set_open_tables_state(this);
 
1635
  reset_open_tables_state();
 
1636
  backups_available= false;
 
1637
}
 
1638
 
 
1639
 
 
1640
void Session::restore_backup_open_tables_state(Open_tables_state *backup)
 
1641
{
 
1642
  /*
 
1643
    Before we will throw away current open tables state we want
 
1644
    to be sure that it was properly cleaned up.
 
1645
  */
 
1646
  assert(open_tables == 0 && temporary_tables == 0 &&
 
1647
              derived_tables == 0 &&
 
1648
              lock == 0);
 
1649
  set_open_tables_state(backup);
 
1650
}
 
1651
 
 
1652
bool Session::set_db(const char *new_db, size_t length)
1620
1653
{
1621
1654
  /* Do not reallocate memory if current chunk is big enough. */
1622
 
  if (new_db.length())
1623
 
  {
1624
 
    _schema.reset(new std::string(new_db));
1625
 
  }
 
1655
  if (length)
 
1656
    db= new_db;
1626
1657
  else
1627
 
  {
1628
 
    _schema.reset(new std::string(""));
1629
 
  }
1630
 
}
1631
 
 
 
1658
    db.clear();
 
1659
 
 
1660
  return false;
 
1661
}
 
1662
 
 
1663
 
 
1664
 
 
1665
 
 
1666
/**
 
1667
  Check the killed state of a user thread
 
1668
  @param session  user thread
 
1669
  @retval 0 the user thread is active
 
1670
  @retval 1 the user thread has been killed
 
1671
*/
 
1672
extern "C" int session_killed(const Session *session)
 
1673
{
 
1674
  return(session->killed);
 
1675
}
 
1676
 
 
1677
/**
 
1678
  Return the session id of a user session
 
1679
  @param pointer to Session object
 
1680
  @return session's id
 
1681
*/
 
1682
extern "C" unsigned long session_get_thread_id(const Session *session)
 
1683
{
 
1684
  return (unsigned long) session->getSessionId();
 
1685
}
 
1686
 
 
1687
 
 
1688
const struct charset_info_st *session_charset(Session *session)
 
1689
{
 
1690
  return(session->charset());
 
1691
}
 
1692
 
 
1693
char **session_query(Session *session)
 
1694
{
 
1695
  return(&session->query);
 
1696
}
 
1697
 
 
1698
int session_non_transactional_update(const Session *session)
 
1699
{
 
1700
  return(session->transaction.all.modified_non_trans_table);
 
1701
}
 
1702
 
 
1703
void session_mark_transaction_to_rollback(Session *session, bool all)
 
1704
{
 
1705
  mark_transaction_to_rollback(session, all);
 
1706
}
1632
1707
 
1633
1708
/**
1634
1709
  Mark transaction to rollback and mark error as fatal to a sub-statement.
1651
1726
  plugin_sessionvar_cleanup(this);
1652
1727
 
1653
1728
  /* If necessary, log any aborted or unauthorized connections */
1654
 
  if (getKilled() || client->wasAborted())
1655
 
  {
1656
 
    status_var.aborted_threads++;
1657
 
  }
 
1729
  if (killed || client->wasAborted())
 
1730
    statistic_increment(aborted_threads, &LOCK_status);
1658
1731
 
1659
1732
  if (client->wasAborted())
1660
1733
  {
1661
 
    if (not getKilled() && variables.log_warnings > 1)
 
1734
    if (! killed && variables.log_warnings > 1)
1662
1735
    {
1663
 
      SecurityContext *sctx= &security_ctx;
 
1736
      Security_context *sctx= &security_ctx;
1664
1737
 
1665
1738
      errmsg_printf(ERRMSG_LVL_WARN, ER(ER_NEW_ABORTING_CONNECTION)
1666
1739
                  , thread_id
1667
 
                  , (_schema->empty() ? "unconnected" : _schema->c_str())
1668
 
                  , sctx->getUser().empty() == false ? sctx->getUser().c_str() : "unauthenticated"
1669
 
                  , sctx->getIp().c_str()
 
1740
                  , (db.empty() ? "unconnected" : db.c_str())
 
1741
                  , sctx->user.empty() == false ? sctx->user.c_str() : "unauthenticated"
 
1742
                  , sctx->ip.c_str()
1670
1743
                  , (main_da.is_error() ? main_da.message() : ER(ER_UNKNOWN_ERROR)));
1671
1744
    }
1672
1745
  }
1673
1746
 
1674
1747
  /* Close out our connection to the client */
1675
1748
  if (should_lock)
1676
 
    session::Cache::singleton().mutex().lock();
1677
 
 
1678
 
  setKilled(Session::KILL_CONNECTION);
1679
 
 
 
1749
    (void) pthread_mutex_lock(&LOCK_thread_count);
 
1750
  killed= Session::KILL_CONNECTION;
1680
1751
  if (client->isConnected())
1681
1752
  {
1682
1753
    if (errcode)
1686
1757
    }
1687
1758
    client->close();
1688
1759
  }
1689
 
 
1690
1760
  if (should_lock)
1691
 
  {
1692
 
    session::Cache::singleton().mutex().unlock();
1693
 
  }
 
1761
    (void) pthread_mutex_unlock(&LOCK_thread_count);
1694
1762
}
1695
1763
 
1696
1764
void Session::reset_for_next_command()
1707
1775
  server_status&= ~ (SERVER_MORE_RESULTS_EXISTS |
1708
1776
                          SERVER_QUERY_NO_INDEX_USED |
1709
1777
                          SERVER_QUERY_NO_GOOD_INDEX_USED);
 
1778
  /*
 
1779
    If in autocommit mode and not in a transaction, reset
 
1780
    OPTION_STATUS_NO_TRANS_UPDATE to not get warnings
 
1781
    in ha_rollback_trans() about some tables couldn't be rolled back.
 
1782
  */
 
1783
  if (!(options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))
 
1784
  {
 
1785
    transaction.all.modified_non_trans_table= false;
 
1786
  }
1710
1787
 
1711
1788
  clear_error();
1712
1789
  main_da.reset_diagnostics_area();
1718
1795
  Close all temporary tables created by 'CREATE TEMPORARY TABLE' for thread
1719
1796
*/
1720
1797
 
1721
 
void Open_tables_state::close_temporary_tables()
 
1798
void Session::close_temporary_tables()
1722
1799
{
1723
1800
  Table *table;
1724
1801
  Table *tmp_next;
1725
1802
 
1726
 
  if (not temporary_tables)
 
1803
  if (!temporary_tables)
1727
1804
    return;
1728
1805
 
1729
1806
  for (table= temporary_tables; table; table= tmp_next)
1730
1807
  {
1731
 
    tmp_next= table->getNext();
1732
 
    nukeTable(table);
 
1808
    tmp_next= table->next;
 
1809
    close_temporary(table);
1733
1810
  }
1734
1811
  temporary_tables= NULL;
1735
1812
}
1738
1815
  unlink from session->temporary tables and close temporary table
1739
1816
*/
1740
1817
 
1741
 
void Open_tables_state::close_temporary_table(Table *table)
 
1818
void Session::close_temporary_table(Table *table)
1742
1819
{
1743
 
  if (table->getPrev())
 
1820
  if (table->prev)
1744
1821
  {
1745
 
    table->getPrev()->setNext(table->getNext());
1746
 
    if (table->getPrev()->getNext())
1747
 
    {
1748
 
      table->getNext()->setPrev(table->getPrev());
1749
 
    }
 
1822
    table->prev->next= table->next;
 
1823
    if (table->prev->next)
 
1824
      table->next->prev= table->prev;
1750
1825
  }
1751
1826
  else
1752
1827
  {
1757
1832
      passing non-zero value to end_slave via rli->save_temporary_tables
1758
1833
      when no temp tables opened, see an invariant below.
1759
1834
    */
1760
 
    temporary_tables= table->getNext();
 
1835
    temporary_tables= table->next;
1761
1836
    if (temporary_tables)
1762
 
    {
1763
 
      table->getNext()->setPrev(NULL);
1764
 
    }
 
1837
      table->next->prev= NULL;
1765
1838
  }
1766
 
  nukeTable(table);
 
1839
  close_temporary(table);
1767
1840
}
1768
1841
 
1769
1842
/*
1770
 
  Close and drop a temporary table
 
1843
  Close and delete a temporary table
1771
1844
 
1772
1845
  NOTE
1773
1846
  This dosn't unlink table from session->temporary
1774
1847
  If this is needed, use close_temporary_table()
1775
1848
*/
1776
1849
 
1777
 
void Open_tables_state::nukeTable(Table *table)
 
1850
void Session::close_temporary(Table *table)
1778
1851
{
1779
 
  plugin::StorageEngine *table_type= table->getShare()->db_type();
 
1852
  plugin::StorageEngine *table_type= table->s->db_type();
1780
1853
 
1781
1854
  table->free_io_cache();
1782
 
  table->delete_table();
1783
 
 
1784
 
  TableIdentifier identifier(table->getShare()->getSchemaName(), table->getShare()->getTableName(), table->getShare()->getPath());
1785
 
  rm_temporary_table(table_type, identifier);
1786
 
 
1787
 
  delete table->getMutableShare();
 
1855
  table->closefrm(false);
 
1856
 
 
1857
  rm_temporary_table(table_type, table->s->path.str);
 
1858
 
 
1859
  table->s->free_table_share();
1788
1860
 
1789
1861
  /* This makes me sad, but we're allocating it via malloc */
1790
 
  delete table;
 
1862
  free(table);
1791
1863
}
1792
1864
 
1793
1865
/** Clear most status variables. */
1794
1866
extern time_t flush_status_time;
 
1867
extern uint32_t max_used_connections;
1795
1868
 
1796
1869
void Session::refresh_status()
1797
1870
{
 
1871
  pthread_mutex_lock(&LOCK_status);
 
1872
 
 
1873
  /* Add thread's status variabes to global status */
 
1874
  add_to_status(&global_status_var, &status_var);
 
1875
 
1798
1876
  /* Reset thread's status variables */
1799
1877
  memset(&status_var, 0, sizeof(status_var));
1800
1878
 
 
1879
  /* Reset some global variables */
 
1880
  reset_status_vars();
 
1881
 
 
1882
  /* Reset the counters of all key caches (default and named). */
 
1883
  reset_key_cache_counters();
1801
1884
  flush_status_time= time((time_t*) 0);
1802
 
  current_global_counters.max_used_connections= 1; /* We set it to one, because we know we exist */
1803
 
  current_global_counters.connections= 0;
 
1885
  max_used_connections= 1; /* We set it to one, because we know we exist */
 
1886
  pthread_mutex_unlock(&LOCK_status);
1804
1887
}
1805
1888
 
1806
1889
user_var_entry *Session::getVariable(LEX_STRING &name, bool create_if_not_exists)
1807
1890
{
1808
 
  return getVariable(std::string(name.str, name.length), create_if_not_exists);
1809
 
}
1810
 
 
1811
 
user_var_entry *Session::getVariable(const std::string  &name, bool create_if_not_exists)
1812
 
{
1813
 
  UserVarsRange ppp= user_vars.equal_range(name);
1814
 
 
1815
 
  for (UserVars::iterator iter= ppp.first;
1816
 
       iter != ppp.second; ++iter)
1817
 
  {
1818
 
    return (*iter).second;
1819
 
  }
1820
 
 
1821
 
  if (not create_if_not_exists)
1822
 
    return NULL;
1823
 
 
1824
1891
  user_var_entry *entry= NULL;
1825
 
  entry= new (nothrow) user_var_entry(name.c_str(), query_id);
1826
 
 
1827
 
  if (entry == NULL)
1828
 
    return NULL;
1829
 
 
1830
 
  std::pair<UserVars::iterator, bool> returnable= user_vars.insert(make_pair(name, entry));
1831
 
 
1832
 
  if (not returnable.second)
 
1892
 
 
1893
  entry= (user_var_entry*) hash_search(&user_vars, (unsigned char*) name.str, name.length);
 
1894
 
 
1895
  if ((entry == NULL) && create_if_not_exists)
1833
1896
  {
1834
 
    delete entry;
 
1897
    if (!hash_inited(&user_vars))
 
1898
      return NULL;
 
1899
    entry= new (nothrow) user_var_entry(name.str, query_id);
 
1900
 
 
1901
    if (entry == NULL)
 
1902
      return NULL;
 
1903
 
 
1904
    if (my_hash_insert(&user_vars, (unsigned char*) entry))
 
1905
    {
 
1906
      assert(1);
 
1907
      free((char*) entry);
 
1908
      return 0;
 
1909
    }
 
1910
 
1835
1911
  }
1836
1912
 
1837
1913
  return entry;
1838
1914
}
1839
1915
 
1840
 
void Session::setVariable(const std::string &name, const std::string &value)
1841
 
{
1842
 
  user_var_entry *updateable_var= getVariable(name.c_str(), true);
1843
 
 
1844
 
  updateable_var->update_hash(false,
1845
 
                              (void*)value.c_str(),
1846
 
                              static_cast<uint32_t>(value.length()), STRING_RESULT,
1847
 
                              &my_charset_bin,
1848
 
                              DERIVATION_IMPLICIT, false);
1849
 
}
1850
 
 
1851
 
void Open_tables_state::mark_temp_tables_as_free_for_reuse()
1852
 
{
1853
 
  for (Table *table= temporary_tables ; table ; table= table->getNext())
 
1916
void Session::mark_temp_tables_as_free_for_reuse()
 
1917
{
 
1918
  for (Table *table= temporary_tables ; table ; table= table->next)
1854
1919
  {
1855
 
    if (table->query_id == getQueryId())
 
1920
    if (table->query_id == query_id)
1856
1921
    {
1857
1922
      table->query_id= 0;
1858
1923
      table->cursor->ha_reset();
1862
1927
 
1863
1928
void Session::mark_used_tables_as_free_for_reuse(Table *table)
1864
1929
{
1865
 
  for (; table ; table= table->getNext())
 
1930
  for (; table ; table= table->next)
1866
1931
  {
1867
 
    if (table->query_id == getQueryId())
 
1932
    if (table->query_id == query_id)
1868
1933
    {
1869
1934
      table->query_id= 0;
1870
1935
      table->cursor->ha_reset();
1883
1948
*/
1884
1949
void Session::close_thread_tables()
1885
1950
{
1886
 
  clearDerivedTables();
 
1951
  Table *table;
 
1952
 
 
1953
  /*
 
1954
    We are assuming here that session->derived_tables contains ONLY derived
 
1955
    tables for this substatement. i.e. instead of approach which uses
 
1956
    query_id matching for determining which of the derived tables belong
 
1957
    to this substatement we rely on the ability of substatements to
 
1958
    save/restore session->derived_tables during their execution.
 
1959
 
 
1960
    TODO: Probably even better approach is to simply associate list of
 
1961
          derived tables with (sub-)statement instead of thread and destroy
 
1962
          them at the end of its execution.
 
1963
  */
 
1964
  if (derived_tables)
 
1965
  {
 
1966
    Table *next;
 
1967
    /*
 
1968
      Close all derived tables generated in queries like
 
1969
      SELECT * FROM (SELECT * FROM t1)
 
1970
    */
 
1971
    for (table= derived_tables ; table ; table= next)
 
1972
    {
 
1973
      next= table->next;
 
1974
      table->free_tmp_table(this);
 
1975
    }
 
1976
    derived_tables= 0;
 
1977
  }
1887
1978
 
1888
1979
  /*
1889
1980
    Mark all temporary tables used by this statement as free for reuse.
1897
1988
    does not belong to statement for which we do close_thread_tables()).
1898
1989
    TODO: This should be fixed in later releases.
1899
1990
   */
 
1991
  if (backups_available == false)
1900
1992
  {
1901
1993
    TransactionServices &transaction_services= TransactionServices::singleton();
1902
1994
    main_da.can_overwrite_status= true;
1903
 
    transaction_services.autocommitOrRollback(this, is_error());
 
1995
    transaction_services.ha_autocommit_or_rollback(this, is_error());
1904
1996
    main_da.can_overwrite_status= false;
1905
1997
    transaction.stmt.reset();
1906
1998
  }
1916
2008
      handled either before writing a query log event (inside
1917
2009
      binlog_query()) or when preparing a pending event.
1918
2010
     */
1919
 
    unlockTables(lock);
 
2011
    mysql_unlock_tables(this, lock);
1920
2012
    lock= 0;
1921
2013
  }
1922
2014
  /*
1923
 
    Note that we need to hold table::Cache::singleton().mutex() while changing the
 
2015
    Note that we need to hold LOCK_open while changing the
1924
2016
    open_tables list. Another thread may work on it.
1925
 
    (See: table::Cache::singleton().removeTable(), mysql_wait_completed_table())
 
2017
    (See: remove_table_from_cache(), mysql_wait_completed_table())
1926
2018
    Closing a MERGE child before the parent would be fatal if the
1927
2019
    other thread tries to abort the MERGE lock in between.
1928
2020
  */
1954
2046
    if (open_tables_from_list(&tables, &counter))
1955
2047
      return true;
1956
2048
 
1957
 
    if (not lock_tables(tables, counter, &need_reopen))
 
2049
    if (!lock_tables(tables, counter, &need_reopen))
1958
2050
      break;
1959
 
    if (not need_reopen)
 
2051
    if (!need_reopen)
1960
2052
      return true;
1961
2053
    close_tables_for_reopen(&tables);
1962
2054
  }
1963
2055
  if ((mysql_handle_derived(lex, &mysql_derived_prepare) ||
1964
 
       (
 
2056
       (fill_derived_tables() &&
1965
2057
        mysql_handle_derived(lex, &mysql_derived_filling))))
1966
2058
    return true;
1967
2059
 
1968
2060
  return false;
1969
2061
}
1970
2062
 
1971
 
/*
1972
 
  @note "best_effort" is used in cases were if a failure occurred on this
1973
 
  operation it would not be surprising because we are only removing because there
1974
 
  might be an issue (lame engines).
1975
 
*/
1976
 
 
1977
 
bool Open_tables_state::rm_temporary_table(const TableIdentifier &identifier, bool best_effort)
1978
 
{
1979
 
  if (plugin::StorageEngine::dropTable(*static_cast<Session *>(this), identifier))
1980
 
  {
1981
 
    if (not best_effort)
1982
 
    {
1983
 
      std::string path;
1984
 
      identifier.getSQLPath(path);
1985
 
      errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
1986
 
                    path.c_str(), errno);
1987
 
    }
1988
 
 
1989
 
    return true;
1990
 
  }
1991
 
 
1992
 
  return false;
1993
 
}
1994
 
 
1995
 
bool Open_tables_state::rm_temporary_table(plugin::StorageEngine *base, const TableIdentifier &identifier)
1996
 
{
1997
 
  assert(base);
1998
 
 
1999
 
  if (plugin::StorageEngine::dropTable(*static_cast<Session *>(this), *base, identifier))
2000
 
  {
2001
 
    std::string path;
2002
 
    identifier.getSQLPath(path);
2003
 
    errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
2004
 
                  path.c_str(), errno);
2005
 
 
2006
 
    return true;
2007
 
  }
2008
 
 
2009
 
  return false;
2010
 
}
2011
 
 
2012
 
/**
2013
 
  @note this will be removed, I am looking through Hudson to see if it is finding
2014
 
  any tables that are missed during cleanup.
2015
 
*/
2016
 
void Open_tables_state::dumpTemporaryTableNames(const char *foo)
2017
 
{
2018
 
  Table *table;
2019
 
 
2020
 
  if (not temporary_tables)
2021
 
    return;
2022
 
 
2023
 
  cerr << "Begin Run: " << foo << "\n";
2024
 
  for (table= temporary_tables; table; table= table->getNext())
2025
 
  {
2026
 
    bool have_proto= false;
2027
 
 
2028
 
    message::Table *proto= table->getShare()->getTableProto();
2029
 
    if (table->getShare()->getTableProto())
2030
 
      have_proto= true;
2031
 
 
2032
 
    const char *answer= have_proto ? "true" : "false";
2033
 
 
2034
 
    if (have_proto)
2035
 
    {
2036
 
      cerr << "\tTable Name " << table->getShare()->getSchemaName() << "." << table->getShare()->getTableName() << " : " << answer << "\n";
2037
 
      cerr << "\t\t Proto " << proto->schema() << " " << proto->name() << "\n";
2038
 
    }
2039
 
    else
2040
 
    {
2041
 
      cerr << "\tTabl;e Name " << table->getShare()->getSchemaName() << "." << table->getShare()->getTableName() << " : " << answer << "\n";
2042
 
    }
2043
 
  }
2044
 
}
2045
 
 
2046
 
bool Session::TableMessages::storeTableMessage(const TableIdentifier &identifier, message::Table &table_message)
2047
 
{
2048
 
  table_message_cache.insert(make_pair(identifier.getPath(), table_message));
2049
 
 
2050
 
  return true;
2051
 
}
2052
 
 
2053
 
bool Session::TableMessages::removeTableMessage(const TableIdentifier &identifier)
2054
 
{
2055
 
  TableMessageCache::iterator iter;
2056
 
 
2057
 
  iter= table_message_cache.find(identifier.getPath());
2058
 
 
2059
 
  if (iter == table_message_cache.end())
2060
 
    return false;
2061
 
 
2062
 
  table_message_cache.erase(iter);
2063
 
 
2064
 
  return true;
2065
 
}
2066
 
 
2067
 
bool Session::TableMessages::getTableMessage(const TableIdentifier &identifier, message::Table &table_message)
2068
 
{
2069
 
  TableMessageCache::iterator iter;
2070
 
 
2071
 
  iter= table_message_cache.find(identifier.getPath());
2072
 
 
2073
 
  if (iter == table_message_cache.end())
2074
 
    return false;
2075
 
 
2076
 
  table_message.CopyFrom(((*iter).second));
2077
 
 
2078
 
  return true;
2079
 
}
2080
 
 
2081
 
bool Session::TableMessages::doesTableMessageExist(const TableIdentifier &identifier)
2082
 
{
2083
 
  TableMessageCache::iterator iter;
2084
 
 
2085
 
  iter= table_message_cache.find(identifier.getPath());
2086
 
 
2087
 
  if (iter == table_message_cache.end())
2088
 
  {
2089
 
    return false;
2090
 
  }
2091
 
 
2092
 
  return true;
2093
 
}
2094
 
 
2095
 
bool Session::TableMessages::renameTableMessage(const TableIdentifier &from, const TableIdentifier &to)
2096
 
{
2097
 
  TableMessageCache::iterator iter;
2098
 
 
2099
 
  table_message_cache[to.getPath()]= table_message_cache[from.getPath()];
2100
 
 
2101
 
  iter= table_message_cache.find(to.getPath());
2102
 
 
2103
 
  if (iter == table_message_cache.end())
2104
 
  {
2105
 
    return false;
2106
 
  }
2107
 
 
2108
 
  (*iter).second.set_schema(to.getSchemaName());
2109
 
  (*iter).second.set_name(to.getTableName());
2110
 
 
2111
 
  return true;
2112
 
}
2113
 
 
2114
 
table::Instance *Session::getInstanceTable()
2115
 
{
2116
 
  temporary_shares.push_back(new table::Instance()); // This will not go into the tableshare cache, so no key is used.
2117
 
 
2118
 
  table::Instance *tmp_share= temporary_shares.back();
2119
 
 
2120
 
  assert(tmp_share);
2121
 
 
2122
 
  return tmp_share;
2123
 
}
2124
 
 
2125
 
 
2126
 
/**
2127
 
  Create a reduced Table object with properly set up Field list from a
2128
 
  list of field definitions.
2129
 
 
2130
 
    The created table doesn't have a table Cursor associated with
2131
 
    it, has no keys, no group/distinct, no copy_funcs array.
2132
 
    The sole purpose of this Table object is to use the power of Field
2133
 
    class to read/write data to/from table->getInsertRecord(). Then one can store
2134
 
    the record in any container (RB tree, hash, etc).
2135
 
    The table is created in Session mem_root, so are the table's fields.
2136
 
    Consequently, if you don't BLOB fields, you don't need to free it.
2137
 
 
2138
 
  @param session         connection handle
2139
 
  @param field_list  list of column definitions
2140
 
 
2141
 
  @return
2142
 
    0 if out of memory, Table object in case of success
2143
 
*/
2144
 
table::Instance *Session::getInstanceTable(List<CreateField> &field_list)
2145
 
{
2146
 
  temporary_shares.push_back(new table::Instance(this, field_list)); // This will not go into the tableshare cache, so no key is used.
2147
 
 
2148
 
  table::Instance *tmp_share= temporary_shares.back();
2149
 
 
2150
 
  assert(tmp_share);
2151
 
 
2152
 
  return tmp_share;
2153
 
}
2154
 
 
2155
 
namespace display  {
2156
 
 
2157
 
static const std::string NONE= "NONE";
2158
 
static const std::string GOT_GLOBAL_READ_LOCK= "HAS GLOBAL READ LOCK";
2159
 
static const std::string MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT= "HAS GLOBAL READ LOCK WITH BLOCKING COMMIT";
2160
 
 
2161
 
const std::string &type(drizzled::Session::global_read_lock_t type)
2162
 
{
2163
 
  switch (type) {
2164
 
    default:
2165
 
    case Session::NONE:
2166
 
      return NONE;
2167
 
    case Session::GOT_GLOBAL_READ_LOCK:
2168
 
      return GOT_GLOBAL_READ_LOCK;
2169
 
    case Session::MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT:
2170
 
      return MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT;
2171
 
  }
2172
 
}
2173
 
 
2174
 
size_t max_string_length(drizzled::Session::global_read_lock_t)
2175
 
{
2176
 
  return MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT.size();
2177
 
}
2178
 
 
2179
 
} /* namespace display */
 
2063
bool Session::openTables(TableList *tables, uint32_t flags)
 
2064
{
 
2065
  uint32_t counter;
 
2066
  bool ret= fill_derived_tables();
 
2067
  assert(ret == false);
 
2068
  if (open_tables_from_list(&tables, &counter, flags) ||
 
2069
      mysql_handle_derived(lex, &mysql_derived_prepare))
 
2070
    return true;
 
2071
  return false;
 
2072
}
 
2073
 
 
2074
bool Session::rm_temporary_table(plugin::StorageEngine *base, TableIdentifier &identifier)
 
2075
{
 
2076
  bool error= false;
 
2077
 
 
2078
  assert(base);
 
2079
 
 
2080
  if (plugin::StorageEngine::deleteDefinitionFromPath(identifier))
 
2081
    error= true;
 
2082
 
 
2083
  if (base->doDropTable(*this, identifier.getPath()))
 
2084
  {
 
2085
    error= true;
 
2086
    errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
 
2087
                  identifier.getPath(), errno);
 
2088
  }
 
2089
  return error;
 
2090
}
 
2091
 
 
2092
bool Session::rm_temporary_table(plugin::StorageEngine *base, const char *path)
 
2093
{
 
2094
  bool error= false;
 
2095
 
 
2096
  assert(base);
 
2097
 
 
2098
  if (delete_table_proto_file(path))
 
2099
    error= true;
 
2100
 
 
2101
  if (base->doDropTable(*this, path))
 
2102
  {
 
2103
    error= true;
 
2104
    errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
 
2105
                  path, errno);
 
2106
  }
 
2107
  return error;
 
2108
}
2180
2109
 
2181
2110
} /* namespace drizzled */