~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/session.cc

Merge trunk and resolve all conflicts.

Show diffs side-by-side

added added

removed removed

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