~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/session.cc

  • Committer: Brian Aker
  • Date: 2009-06-05 23:10:06 UTC
  • mto: This revision was merged to the branch mainline in revision 1055.
  • Revision ID: brian@gaz-20090605231006-01nyw7pfpj2z2v8p
Remove guts in parser for LOCK TABLE.

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
18
 */
19
19
 
20
 
/**
21
 
 * @file Implementation of the Session class and API
22
 
 */
23
 
 
24
 
#include "config.h"
25
 
#include "drizzled/session.h"
26
 
#include "drizzled/session/cache.h"
 
20
#include <drizzled/server_includes.h>
 
21
#include <drizzled/session.h>
27
22
#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"
40
 
#include "drizzled/plugin/scheduler.h"
41
 
#include "drizzled/plugin/authentication.h"
42
 
#include "drizzled/plugin/logging.h"
43
 
#include "drizzled/plugin/transactional_storage_engine.h"
44
 
#include "drizzled/plugin/query_rewrite.h"
45
 
#include "drizzled/probes.h"
46
 
#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/table/instance.h"
53
 
 
54
 
#include "plugin/myisam/myisam.h"
55
 
#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
 
 
63
 
#include <fcntl.h>
64
 
#include <algorithm>
65
 
#include <climits>
66
 
#include <boost/filesystem.hpp>
67
 
 
68
 
#include "drizzled/util/backtrace.h"
69
 
 
70
 
using namespace std;
71
 
 
72
 
namespace fs=boost::filesystem;
73
 
namespace drizzled
74
 
{
 
23
#include <mysys/mysys_err.h>
 
24
#include <drizzled/error.h>
 
25
#include <drizzled/query_id.h>
 
26
#include <drizzled/data_home.h>
 
27
#include <drizzled/sql_base.h>
 
28
#include <drizzled/lock.h>
 
29
#include <drizzled/item/cache.h>
 
30
#include <drizzled/item/float.h>
 
31
#include <drizzled/item/return_int.h>
 
32
#include <drizzled/item/empty_string.h>
 
33
#include <drizzled/show.h>
 
34
#include <drizzled/scheduling.h>
75
35
 
76
36
/*
77
37
  The following is used to initialise Table_ident with a internal
81
41
char empty_c_string[1]= {0};    /* used for not defined db */
82
42
 
83
43
const char * const Session::DEFAULT_WHERE= "field list";
 
44
extern pthread_key_t THR_Session;
 
45
extern pthread_key_t THR_Mem_root;
 
46
 
 
47
/*****************************************************************************
 
48
** Instansiate templates
 
49
*****************************************************************************/
 
50
 
 
51
#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
 
52
/* Used templates */
 
53
template class List<Key>;
 
54
template class List_iterator<Key>;
 
55
template class List<Key_part_spec>;
 
56
template class List_iterator<Key_part_spec>;
 
57
template class List<Alter_drop>;
 
58
template class List_iterator<Alter_drop>;
 
59
template class List<Alter_column>;
 
60
template class List_iterator<Alter_column>;
 
61
#endif
 
62
 
 
63
/****************************************************************************
 
64
** User variables
 
65
****************************************************************************/
 
66
extern "C" unsigned char *get_var_key(user_var_entry *entry, size_t *length,
 
67
                              bool )
 
68
{
 
69
  *length= entry->name.length;
 
70
  return (unsigned char*) entry->name.str;
 
71
}
 
72
 
 
73
extern "C" void free_user_var(user_var_entry *entry)
 
74
{
 
75
  char *pos= (char*) entry+ALIGN_SIZE(sizeof(*entry));
 
76
  if (entry->value && entry->value != pos)
 
77
    free(entry->value);
 
78
  free((char*) entry);
 
79
}
84
80
 
85
81
bool Key_part_spec::operator==(const Key_part_spec& other) const
86
82
{
87
83
  return length == other.length &&
88
84
         field_name.length == other.field_name.length &&
89
 
    !my_strcasecmp(system_charset_info, field_name.str, other.field_name.str);
 
85
         !strcmp(field_name.str, other.field_name.str);
90
86
}
91
87
 
92
 
Open_tables_state::Open_tables_state(uint64_t version_arg) :
93
 
  version(version_arg)
 
88
/****************************************************************************
 
89
** Thread specific functions
 
90
****************************************************************************/
 
91
 
 
92
Open_tables_state::Open_tables_state(ulong version_arg)
 
93
  :version(version_arg), state_flags(0U)
94
94
{
95
 
  open_tables= temporary_tables= derived_tables= NULL;
96
 
  extra_lock= lock= NULL;
 
95
  reset_open_tables_state();
97
96
}
98
97
 
99
98
/*
100
99
  The following functions form part of the C plugin API
101
100
*/
102
 
int mysql_tmpfile(const char *prefix)
 
101
 
 
102
extern "C" int mysql_tmpfile(const char *prefix)
103
103
{
104
104
  char filename[FN_REFLEN];
105
 
  int fd = internal::create_temp_file(filename, drizzle_tmpdir.c_str(), prefix, MYF(MY_WME));
 
105
  File fd = create_temp_file(filename, drizzle_tmpdir, prefix, MYF(MY_WME));
106
106
  if (fd >= 0) {
107
107
    unlink(filename);
108
108
  }
110
110
  return fd;
111
111
}
112
112
 
 
113
 
 
114
extern "C"
 
115
int session_in_lock_tables(const Session *session)
 
116
{
 
117
  return test(session->in_lock_tables);
 
118
}
 
119
 
 
120
 
 
121
extern "C"
113
122
int session_tablespace_op(const Session *session)
114
123
{
115
124
  return test(session->tablespace_op);
116
125
}
117
126
 
 
127
 
118
128
/**
119
129
   Set the process info field of the Session structure.
120
130
 
123
133
 
124
134
   @see Session::set_proc_info
125
135
 */
126
 
void set_session_proc_info(Session *session, const char *info)
 
136
extern "C" void
 
137
set_session_proc_info(Session *session, const char *info)
127
138
{
128
139
  session->set_proc_info(info);
129
140
}
130
141
 
 
142
extern "C"
131
143
const char *get_session_proc_info(Session *session)
132
144
{
133
145
  return session->get_proc_info();
134
146
}
135
147
 
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
 
 
 
148
extern "C"
 
149
void **session_ha_data(const Session *session, const struct StorageEngine *engine)
 
150
{
 
151
  return (void **) &session->ha_data[engine->slot].ha_ptr;
 
152
}
 
153
 
 
154
extern "C"
147
155
int64_t session_test_options(const Session *session, int64_t test_options)
148
156
{
149
157
  return session->options & test_options;
150
158
}
151
159
 
 
160
extern "C"
152
161
int session_sql_command(const Session *session)
153
162
{
154
163
  return (int) session->lex->sql_command;
155
164
}
156
165
 
157
 
enum_tx_isolation session_tx_isolation(const Session *session)
158
 
{
159
 
  return (enum_tx_isolation)session->variables.tx_isolation;
160
 
}
161
 
 
162
 
Session::Session(plugin::Client *client_arg) :
163
 
  Open_tables_state(refresh_version),
164
 
  mem_root(&main_mem_root),
165
 
  xa_id(0),
166
 
  lex(&main_lex),
167
 
  query(new std::string),
168
 
  _schema(new std::string("")),
169
 
  catalog("LOCAL"),
170
 
  client(client_arg),
171
 
  scheduler(NULL),
172
 
  scheduler_arg(NULL),
173
 
  lock_id(&main_lock_id),
174
 
  user_time(0),
175
 
  ha_data(plugin::num_trx_monitored_objects),
176
 
  concurrent_execute_allowed(true),
177
 
  arg_of_last_insert_id_function(false),
178
 
  first_successful_insert_id_in_prev_stmt(0),
179
 
  first_successful_insert_id_in_cur_stmt(0),
180
 
  limit_found_rows(0),
181
 
  _global_read_lock(NONE),
182
 
  _killed(NOT_KILLED),
183
 
  some_tables_deleted(false),
184
 
  no_errors(false),
185
 
  password(false),
186
 
  is_fatal_error(false),
187
 
  transaction_rollback_request(false),
188
 
  is_fatal_sub_stmt_error(0),
189
 
  derived_tables_processing(false),
190
 
  tablespace_op(false),
191
 
  m_lip(NULL),
192
 
  cached_table(0),
193
 
  transaction_message(NULL),
194
 
  statement_message(NULL),
195
 
  session_event_observers(NULL),
196
 
  use_usage(false)
197
 
{
198
 
  client->setSession(this);
 
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(Protocol *protocol_arg)
 
179
   :Statement(&main_lex, &main_mem_root,
 
180
              /* statement id */ 0),
 
181
   Open_tables_state(refresh_version),
 
182
   lock_id(&main_lock_id),
 
183
   user_time(0),
 
184
   arg_of_last_insert_id_function(false),
 
185
   first_successful_insert_id_in_prev_stmt(0),
 
186
   first_successful_insert_id_in_cur_stmt(0),
 
187
   global_read_lock(0),
 
188
   is_fatal_error(0),
 
189
   transaction_rollback_request(0),
 
190
   is_fatal_sub_stmt_error(0),
 
191
   in_lock_tables(0),
 
192
   derived_tables_processing(false),
 
193
   m_lip(NULL),
 
194
   scheduler(0),
 
195
   cached_table(0)
 
196
{
 
197
  uint64_t tmp;
 
198
 
 
199
  memset(process_list_info, 0, PROCESS_LIST_WIDTH);
199
200
 
200
201
  /*
201
202
    Pass nominal parameters to init_alloc_root only to ensure that
202
203
    the destructor works OK in case of an error. The main_mem_root
203
204
    will be re-initialized in init_for_queries().
204
205
  */
205
 
  memory::init_sql_alloc(&main_mem_root, memory::ROOT_MIN_BLOCK_SIZE, 0);
206
 
  thread_stack= NULL;
207
 
  count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;
208
 
  col_access= 0;
209
 
  tmp_table= 0;
210
 
  used_tables= 0;
 
206
  init_sql_alloc(&main_mem_root, ALLOC_ROOT_MIN_BLOCK_SIZE, 0);
 
207
  thread_stack= 0;
 
208
  catalog= (char*)"std"; // the only catalog we have for now
 
209
  some_tables_deleted=no_errors=password= 0;
 
210
  count_cuted_fields= CHECK_FIELD_IGNORE;
 
211
  killed= NOT_KILLED;
 
212
  col_access=0;
 
213
  tmp_table=0;
 
214
  used_tables=0;
211
215
  cuted_fields= sent_row_count= row_count= 0L;
 
216
  limit_found_rows= 0;
212
217
  row_count_func= -1;
213
218
  statement_id_counter= 0UL;
214
219
  // Must be reset to handle error with Session's created for init of mysqld
220
225
  thread_id= 0;
221
226
  file_id = 0;
222
227
  query_id= 0;
223
 
  warn_query_id= 0;
224
 
  mysys_var= 0;
225
 
  scoreboard_index= -1;
 
228
  warn_id= 0;
 
229
  memset(ha_data, 0, sizeof(ha_data));
 
230
  replication_data= 0;
 
231
  mysys_var=0;
226
232
  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;
 
233
  client_capabilities= 0;                       // minimalistic client
 
234
  cleanup_done= abort_on_warning= no_warnings_for_error= false;
 
235
  peer_port= 0;                                 // For SHOW PROCESSLIST
 
236
  transaction.on= 1;
 
237
  compression= 0;
 
238
  pthread_mutex_init(&LOCK_delete, MY_MUTEX_INIT_FAST);
232
239
 
233
240
  /* Variables with default values */
234
241
  proc_info="login";
235
242
  where= Session::DEFAULT_WHERE;
236
 
  command= COM_CONNECT;
 
243
  command=COM_CONNECT;
237
244
 
238
245
  plugin_sessionvar_init(this);
239
246
  /*
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;
256
264
  warn_list.empty();
257
265
  memset(warn_count, 0, sizeof(warn_count));
258
266
  total_warn_count= 0;
 
267
  update_charset();
259
268
  memset(&status_var, 0, sizeof(status_var));
260
269
 
 
270
 
 
271
 
261
272
  /* Initialize sub structures */
262
 
  memory::init_sql_alloc(&warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE);
263
 
 
 
273
  init_sql_alloc(&warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE);
 
274
  hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0,
 
275
            (hash_get_key) get_var_key,
 
276
            (hash_free_key) free_user_var, 0);
 
277
 
 
278
  /* Protocol */
 
279
  protocol= protocol_arg;
 
280
  protocol->setSession(this);
 
281
 
 
282
  const Query_id& local_query_id= Query_id::get_query_id();
 
283
  tablespace_op= false;
 
284
  tmp= sql_rnd();
 
285
  protocol->setRandom(tmp + (uint64_t) &protocol,
 
286
                      tmp + (uint64_t)local_query_id.value());
264
287
  substitute_null_with_insert_id = false;
265
 
  lock_info.init(); /* safety: will be reset after start */
 
288
  thr_lock_info_init(&lock_info); /* safety: will be reset after start */
266
289
  thr_lock_owner_init(&main_lock_id, &lock_info);
267
290
 
268
291
  m_internal_handler= NULL;
269
 
  
270
 
  plugin::EventObserver::registerSessionEvents(*this); 
271
292
}
272
293
 
273
 
void Session::free_items()
274
 
{
275
 
  Item *next;
276
 
  /* This works because items are allocated with memory::sql_alloc() */
277
 
  for (; free_list; free_list= next)
278
 
  {
279
 
    next= free_list->next;
280
 
    free_list->delete_self();
281
 
  }
282
 
}
283
294
 
284
295
void Session::push_internal_handler(Internal_error_handler *handler)
285
296
{
291
302
  m_internal_handler= handler;
292
303
}
293
304
 
 
305
 
294
306
bool Session::handle_error(uint32_t sql_errno, const char *message,
295
307
                       DRIZZLE_ERROR::enum_warning_level level)
296
308
{
302
314
  return false;                                 // 'false', as per coding style
303
315
}
304
316
 
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
317
 
325
318
void Session::pop_internal_handler()
326
319
{
328
321
  m_internal_handler= NULL;
329
322
}
330
323
 
331
 
void Session::get_xid(DRIZZLE_XID *xid)
332
 
{
333
 
  *xid = *(DRIZZLE_XID *) &transaction.xid_state.xid;
334
 
}
 
324
#if defined(__cplusplus)
 
325
extern "C" {
 
326
#endif
 
327
 
 
328
void *session_alloc(Session *session, unsigned int size)
 
329
{
 
330
  return session->alloc(size);
 
331
}
 
332
 
 
333
void *session_calloc(Session *session, unsigned int size)
 
334
{
 
335
  return session->calloc(size);
 
336
}
 
337
 
 
338
char *session_strdup(Session *session, const char *str)
 
339
{
 
340
  return session->strdup(str);
 
341
}
 
342
 
 
343
char *session_strmake(Session *session, const char *str, unsigned int size)
 
344
{
 
345
  return session->strmake(str, size);
 
346
}
 
347
 
 
348
void *session_memdup(Session *session, const void* str, unsigned int size)
 
349
{
 
350
  return session->memdup(str, size);
 
351
}
 
352
 
 
353
void session_get_xid(const Session *session, DRIZZLE_XID *xid)
 
354
{
 
355
  *xid = *(DRIZZLE_XID *) &session->transaction.xid_state.xid;
 
356
}
 
357
 
 
358
#if defined(__cplusplus)
 
359
}
 
360
#endif
 
361
 
 
362
/*
 
363
  Init Session for query processing.
 
364
  This has to be called once before we call mysql_parse.
 
365
  See also comments in session.h.
 
366
*/
 
367
 
 
368
void Session::init_for_queries()
 
369
{
 
370
  set_time();
 
371
  ha_enable_transaction(this,true);
 
372
 
 
373
  reset_root_defaults(mem_root, variables.query_alloc_block_size,
 
374
                      variables.query_prealloc_size);
 
375
  reset_root_defaults(&transaction.mem_root,
 
376
                      variables.trans_alloc_block_size,
 
377
                      variables.trans_prealloc_size);
 
378
  transaction.xid_state.xid.null();
 
379
  transaction.xid_state.in_session=1;
 
380
}
 
381
 
335
382
 
336
383
/* Do operations that may take a long time */
337
384
 
339
386
{
340
387
  assert(cleanup_done == false);
341
388
 
342
 
  setKilled(KILL_CONNECTION);
 
389
  killed= KILL_CONNECTION;
343
390
#ifdef ENABLE_WHEN_BINLOG_WILL_BE_ABLE_TO_PREPARE
344
391
  if (transaction.xid_state.xa_state == XA_PREPARED)
345
392
  {
347
394
  }
348
395
#endif
349
396
  {
350
 
    TransactionServices &transaction_services= TransactionServices::singleton();
351
 
    transaction_services.rollbackTransaction(this, true);
 
397
    ha_rollback(this);
352
398
    xid_cache_delete(&transaction.xid_state);
353
399
  }
354
 
 
355
 
  for (UserVars::iterator iter= user_vars.begin();
356
 
       iter != user_vars.end();
357
 
       iter++)
 
400
  if (locked_tables)
358
401
  {
359
 
    user_var_entry *entry= (*iter).second;
360
 
    delete entry;
 
402
    lock=locked_tables; locked_tables=0;
 
403
    close_thread_tables();
361
404
  }
362
 
  user_vars.clear();
363
 
 
364
 
 
 
405
  hash_free(&user_vars);
365
406
  close_temporary_tables();
366
407
 
367
408
  if (global_read_lock)
368
 
  {
369
 
    unlockGlobalReadLock();
370
 
  }
 
409
    unlock_global_read_lock(this);
371
410
 
372
411
  cleanup_done= true;
373
412
}
374
413
 
375
414
Session::~Session()
376
415
{
377
 
  this->checkSentry();
 
416
  Session_CHECK_SENTRY(this);
 
417
  add_to_status(&global_status_var, &status_var);
378
418
 
379
 
  if (client->isConnected())
 
419
  if (protocol->isConnected())
380
420
  {
381
421
    if (global_system_variables.log_warnings)
382
 
        errmsg_printf(ERRMSG_LVL_WARN, ER(ER_FORCING_CLOSE),internal::my_progname,
 
422
        errmsg_printf(ERRMSG_LVL_WARN, ER(ER_FORCING_CLOSE),my_progname,
383
423
                      thread_id,
384
 
                      (getSecurityContext().getUser().c_str() ?
385
 
                       getSecurityContext().getUser().c_str() : ""));
 
424
                      (security_ctx.user.c_str() ?
 
425
                       security_ctx.user.c_str() : ""));
386
426
    disconnect(0, false);
387
427
  }
388
428
 
389
429
  /* Close connection */
390
 
  client->close();
391
 
  delete client;
 
430
  protocol->close();
 
431
  delete protocol;
392
432
 
393
433
  if (cleanup_done == false)
394
434
    cleanup();
395
435
 
396
 
  plugin::StorageEngine::closeConnection(this);
 
436
  ha_close_connection(this);
397
437
  plugin_sessionvar_cleanup(this);
398
438
 
399
 
  warn_root.free_root(MYF(0));
 
439
  if (db)
 
440
  {
 
441
    free(db);
 
442
    db= NULL;
 
443
  }
 
444
  free_root(&warn_root,MYF(0));
 
445
  free_root(&transaction.mem_root,MYF(0));
400
446
  mysys_var=0;                                  // Safety (shouldn't be needed)
401
447
  dbug_sentry= Session_SENTRY_GONE;
402
448
 
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
 
 
 
449
  free_root(&main_mem_root, MYF(0));
 
450
  pthread_setspecific(THR_Session,  0);
 
451
 
 
452
 
 
453
  /* Ensure that no one is using Session */
 
454
  pthread_mutex_unlock(&LOCK_delete);
 
455
  pthread_mutex_destroy(&LOCK_delete);
 
456
}
 
457
 
 
458
 
 
459
/*
 
460
  Add all status variables to another status variable array
 
461
 
 
462
  SYNOPSIS
 
463
   add_to_status()
 
464
   to_var       add to this array
 
465
   from_var     from this array
 
466
 
 
467
  NOTES
 
468
    This function assumes that all variables are long/ulong.
 
469
    If this assumption will change, then we have to explictely add
 
470
    the other variables after the while loop
 
471
*/
 
472
 
 
473
void add_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var)
 
474
{
 
475
  ulong *end= (ulong*) ((unsigned char*) to_var +
 
476
                        offsetof(STATUS_VAR, last_system_status_var) +
 
477
                        sizeof(ulong));
 
478
  ulong *to= (ulong*) to_var, *from= (ulong*) from_var;
 
479
 
 
480
  while (to != end)
 
481
    *(to++)+= *(from++);
 
482
}
 
483
 
 
484
/*
 
485
  Add the difference between two status variable arrays to another one.
 
486
 
 
487
  SYNOPSIS
 
488
    add_diff_to_status
 
489
    to_var       add to this array
 
490
    from_var     from this array
 
491
    dec_var      minus this array
 
492
 
 
493
  NOTE
 
494
    This function assumes that all variables are long/ulong.
 
495
*/
 
496
 
 
497
void add_diff_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var,
 
498
                        STATUS_VAR *dec_var)
 
499
{
 
500
  ulong *end= (ulong*) ((unsigned char*) to_var + offsetof(STATUS_VAR,
 
501
                                                  last_system_status_var) +
 
502
                        sizeof(ulong));
 
503
  ulong *to= (ulong*) to_var, *from= (ulong*) from_var, *dec= (ulong*) dec_var;
 
504
 
 
505
  while (to != end)
 
506
    *(to++)+= *(from++) - *(dec++);
 
507
}
 
508
 
 
509
 
 
510
void Session::awake(Session::killed_state state_to_set)
 
511
{
 
512
  Session_CHECK_SENTRY(this);
 
513
  safe_mutex_assert_owner(&LOCK_delete);
 
514
  Scheduler &thread_scheduler= get_thread_scheduler();
 
515
 
 
516
  killed= state_to_set;
433
517
  if (state_to_set != Session::KILL_QUERY)
434
518
  {
435
 
    DRIZZLE_CONNECTION_DONE(thread_id);
 
519
    thread_scheduler.post_kill_notification(this);
436
520
  }
437
 
 
438
521
  if (mysys_var)
439
522
  {
440
 
    boost_unique_lock_t scopedLock(mysys_var->mutex);
 
523
    pthread_mutex_lock(&mysys_var->mutex);
441
524
    /*
442
 
      "
443
525
      This broadcast could be up in the air if the victim thread
444
526
      exits the cond in the time between read and broadcast, but that is
445
527
      ok since all we want to do is to make the victim thread get out
460
542
    */
461
543
    if (mysys_var->current_cond && mysys_var->current_mutex)
462
544
    {
463
 
      mysys_var->current_mutex->lock();
464
 
      mysys_var->current_cond->notify_all();
465
 
      mysys_var->current_mutex->unlock();
 
545
      pthread_mutex_lock(mysys_var->current_mutex);
 
546
      pthread_cond_broadcast(mysys_var->current_cond);
 
547
      pthread_mutex_unlock(mysys_var->current_mutex);
466
548
    }
 
549
    pthread_mutex_unlock(&mysys_var->mutex);
467
550
  }
468
551
}
469
552
 
470
553
/*
471
554
  Remember the location of thread info, the structure needed for
472
 
  memory::sql_alloc() and the structure for the net buffer
 
555
  sql_alloc() and the structure for the net buffer
473
556
*/
474
 
bool Session::storeGlobals()
 
557
bool Session::store_globals()
475
558
{
476
559
  /*
477
560
    Assert that thread_stack is initialized: it's necessary to be able
479
562
  */
480
563
  assert(thread_stack);
481
564
 
482
 
  currentSession().release();
483
 
  currentSession().reset(this);
484
 
 
485
 
  currentMemRoot().release();
486
 
  currentMemRoot().reset(&mem_root);
487
 
 
 
565
  if (pthread_setspecific(THR_Session,  this) ||
 
566
      pthread_setspecific(THR_Mem_root, &mem_root))
 
567
    return 1;
488
568
  mysys_var=my_thread_var;
489
569
 
490
570
  /*
492
572
    This allows us to move Session to different threads if needed.
493
573
  */
494
574
  mysys_var->id= thread_id;
 
575
  real_id= pthread_self();                      // For debugging
495
576
 
496
577
  /*
497
578
    We have to call thr_lock_info_init() again here as Session may have been
498
579
    created in another thread
499
580
  */
500
 
  lock_info.init();
501
 
 
502
 
  return false;
 
581
  thr_lock_info_init(&lock_info);
 
582
  return 0;
503
583
}
504
584
 
505
 
/*
506
 
  Init Session for query processing.
507
 
  This has to be called once before we call mysql_parse.
508
 
  See also comments in session.h.
509
 
*/
510
 
 
511
585
void Session::prepareForQueries()
512
586
{
513
587
  if (variables.max_join_size == HA_POS_ERROR)
514
588
    options |= OPTION_BIG_SELECTS;
 
589
  if (client_capabilities & CLIENT_COMPRESS)
 
590
  {
 
591
    compression= 1;
 
592
    protocol->enableCompression();
 
593
  }
515
594
 
516
595
  version= refresh_version;
517
596
  set_proc_info(NULL);
518
597
  command= COM_SLEEP;
519
598
  set_time();
520
 
 
521
 
  mem_root->reset_root_defaults(variables.query_alloc_block_size,
522
 
                                variables.query_prealloc_size);
523
 
  transaction.xid_state.xid.null();
524
 
  transaction.xid_state.in_session=1;
525
 
  if (use_usage)
526
 
    resetUsage();
 
599
  init_for_queries();
527
600
}
528
601
 
529
602
bool Session::initGlobals()
530
603
{
531
 
  if (storeGlobals())
 
604
  if (store_globals())
532
605
  {
533
606
    disconnect(ER_OUT_OF_RESOURCES, true);
534
 
    status_var.aborted_connects++;
535
 
    return true;
536
 
  }
537
 
  return false;
538
 
}
539
 
 
540
 
void Session::run()
541
 
{
542
 
  if (initGlobals() || authenticate())
543
 
  {
544
 
    disconnect(0, true);
545
 
    return;
546
 
  }
547
 
 
548
 
  prepareForQueries();
549
 
 
550
 
  while (not client->haveError() && getKilled() != KILL_CONNECTION)
551
 
  {
552
 
    if (not executeStatement())
553
 
      break;
554
 
  }
555
 
 
556
 
  disconnect(0, true);
557
 
}
558
 
 
559
 
bool Session::schedule(Session::shared_ptr &arg)
560
 
{
561
 
  arg->scheduler= plugin::Scheduler::getScheduler();
562
 
  assert(arg->scheduler);
563
 
 
564
 
  connection_count.increment();
565
 
 
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());
584
 
    char error_message_buff[DRIZZLE_ERRMSG_SIZE];
585
 
 
586
 
    arg->setKilled(Session::KILL_CONNECTION);
587
 
 
588
 
    arg->status_var.aborted_connects++;
589
 
 
590
 
    /* Can't use my_error() since store_globals has not been called. */
591
 
    /* TODO replace will better error message */
592
 
    snprintf(error_message_buff, sizeof(error_message_buff),
593
 
             ER(ER_CANT_CREATE_THREAD), 1);
594
 
    arg->client->sendError(ER_CANT_CREATE_THREAD, error_message_buff);
595
 
 
596
 
    return true;
597
 
  }
598
 
 
599
 
  return false;
600
 
}
601
 
 
602
 
 
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)
615
 
{
616
 
  const char* old_msg = get_proc_info();
617
 
  safe_mutex_assert_owner(mutex);
618
 
  mysys_var->current_mutex = &mutex;
619
 
  mysys_var->current_cond = &cond;
620
 
  this->set_proc_info(msg);
621
 
  return old_msg;
622
 
}
623
 
 
624
 
void Session::exit_cond(const char* old_msg)
625
 
{
626
 
  /*
627
 
    Putting the mutex unlock in exit_cond() ensures that
628
 
    mysys_var->current_mutex is always unlocked _before_ mysys_var->mutex is
629
 
    locked (if that would not be the case, you'll get a deadlock if someone
630
 
    does a Session::awake() on you).
631
 
  */
632
 
  mysys_var->current_mutex->unlock();
633
 
  boost_unique_lock_t scopedLock(mysys_var->mutex);
634
 
  mysys_var->current_mutex = 0;
635
 
  mysys_var->current_cond = 0;
636
 
  this->set_proc_info(old_msg);
 
607
    statistic_increment(aborted_connects, &LOCK_status);
 
608
    Scheduler &thread_scheduler= get_thread_scheduler();
 
609
    thread_scheduler.end_thread(this, 0);
 
610
    return false;
 
611
  }
 
612
  return true;
637
613
}
638
614
 
639
615
bool Session::authenticate()
640
616
{
641
 
  lex->start(this);
642
 
  if (client->authenticate())
 
617
  lex_start(this);
 
618
  if (protocol->authenticate())
 
619
    return true;
 
620
 
 
621
  statistic_increment(aborted_connects, &LOCK_status);
 
622
  return false;
 
623
}
 
624
 
 
625
bool Session::checkUser(const char *passwd, uint32_t passwd_len, const char *in_db)
 
626
{
 
627
  LEX_STRING db_str= { (char *) in_db, in_db ? strlen(in_db) : 0 };
 
628
  bool is_authenticated;
 
629
 
 
630
  /*
 
631
    Clear session->db as it points to something, that will be freed when
 
632
    connection is closed. We don't want to accidentally free a wrong
 
633
    pointer if connect failed. Also in case of 'CHANGE USER' failure,
 
634
    current database will be switched to 'no database selected'.
 
635
  */
 
636
  reset_db(NULL, 0);
 
637
 
 
638
  if (passwd_len != 0 && passwd_len != SCRAMBLE_LENGTH)
 
639
  {
 
640
    my_error(ER_HANDSHAKE_ERROR, MYF(0), security_ctx.ip.c_str());
643
641
    return false;
644
 
 
645
 
  status_var.aborted_connects++;
646
 
 
647
 
  return true;
648
 
}
649
 
 
650
 
bool Session::checkUser(const std::string &passwd_str,
651
 
                        const std::string &in_db)
652
 
{
653
 
  bool is_authenticated=
654
 
    plugin::Authentication::isAuthenticated(getSecurityContext(),
655
 
                                            passwd_str);
 
642
  }
 
643
 
 
644
  is_authenticated= authenticate_user(this, passwd);
656
645
 
657
646
  if (is_authenticated != true)
658
647
  {
659
 
    status_var.access_denied++;
660
 
    /* isAuthenticated has pushed the error message */
 
648
    my_error(ER_ACCESS_DENIED_ERROR, MYF(0),
 
649
             security_ctx.user.c_str(),
 
650
             security_ctx.ip.c_str(),
 
651
             passwd_len ? ER(ER_YES) : ER(ER_NO));
 
652
 
661
653
    return false;
662
654
  }
663
655
 
 
656
  security_ctx.skip_grants();
 
657
 
664
658
  /* Change database if necessary */
665
 
  if (not in_db.empty())
 
659
  if (in_db && in_db[0])
666
660
  {
667
 
    SchemaIdentifier identifier(in_db);
668
 
    if (mysql_change_db(this, identifier))
 
661
    if (mysql_change_db(this, &db_str, false))
669
662
    {
670
663
      /* mysql_change_db() has pushed the error message. */
671
664
      return false;
672
665
    }
673
666
  }
674
667
  my_ok();
675
 
  password= not passwd_str.empty();
 
668
  password= test(passwd_len);          // remember for error messages
676
669
 
677
670
  /* Ready to handle queries */
678
671
  return true;
690
683
    (see my_message_sql)
691
684
  */
692
685
  lex->current_select= 0;
693
 
  clear_error();
694
 
  main_da.reset_diagnostics_area();
695
 
 
696
 
  if (client->readCommand(&l_packet, &packet_length) == false)
697
 
  {
698
 
    return false;
699
 
  }
700
 
 
701
 
  if (getKilled() == KILL_CONNECTION)
 
686
 
 
687
  if (protocol->readCommand(&l_packet, &packet_length) == false)
702
688
    return false;
703
689
 
704
690
  if (packet_length == 0)
705
691
    return true;
706
692
 
707
 
  l_command= static_cast<enum_server_command>(l_packet[0]);
 
693
  l_command= (enum enum_server_command) (unsigned char) l_packet[0];
708
694
 
709
695
  if (command >= COM_END)
710
696
    command= COM_END;                           // Wrong command
711
697
 
712
698
  assert(packet_length);
713
 
  return not dispatch_command(l_command, this, l_packet+1, (uint32_t) (packet_length-1));
 
699
  return ! dispatch_command(l_command, this, l_packet+1, (uint32_t) (packet_length-1));
714
700
}
715
701
 
716
702
bool Session::readAndStoreQuery(const char *in_packet, uint32_t in_packet_length)
722
708
    in_packet_length--;
723
709
  }
724
710
  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])))
 
711
  while (in_packet_length > 0 &&
 
712
         (pos[-1] == ';' || my_isspace(charset() ,pos[-1])))
726
713
  {
727
714
    pos--;
728
715
    in_packet_length--;
729
716
  }
730
717
 
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));
 
718
  /* We must allocate some extra memory for the cached query string */
 
719
  query_length= 0; /* Extra safety: Avoid races */
 
720
  query= (char*) memdup_w_gap((unsigned char*) in_packet, in_packet_length, db_length + 1);
 
721
  if (! query)
 
722
    return false;
 
723
 
 
724
  query[in_packet_length]=0;
 
725
  query_length= in_packet_length;
 
726
 
 
727
  /* Reclaim some memory */
 
728
  packet.shrink(variables.net_buffer_length);
 
729
  convert_buffer.shrink(variables.net_buffer_length);
739
730
 
740
731
  return true;
741
732
}
744
735
{
745
736
  bool do_release= 0;
746
737
  bool result= true;
747
 
  TransactionServices &transaction_services= TransactionServices::singleton();
748
738
 
749
739
  if (transaction.xid_state.xa_state != XA_NOTR)
750
740
  {
751
741
    my_error(ER_XAER_RMFAIL, MYF(0), xa_state_names[transaction.xid_state.xa_state]);
752
742
    return false;
753
743
  }
754
 
  switch (completion)
 
744
  switch (completion) 
755
745
  {
756
746
    case COMMIT:
757
747
      /*
760
750
       * (Which of course should never happen...)
761
751
       */
762
752
      server_status&= ~SERVER_STATUS_IN_TRANS;
763
 
      if (transaction_services.commitTransaction(this, true))
 
753
      if (ha_commit(this))
764
754
        result= false;
765
 
      options&= ~(OPTION_BEGIN);
 
755
      options&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
 
756
      transaction.all.modified_non_trans_table= false;
766
757
      break;
767
758
    case COMMIT_RELEASE:
768
759
      do_release= 1; /* fall through */
777
768
    case ROLLBACK_AND_CHAIN:
778
769
    {
779
770
      server_status&= ~SERVER_STATUS_IN_TRANS;
780
 
      if (transaction_services.rollbackTransaction(this, true))
 
771
      if (ha_rollback(this))
781
772
        result= false;
782
 
      options&= ~(OPTION_BEGIN);
 
773
      options&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
 
774
      transaction.all.modified_non_trans_table= false;
783
775
      if (result == true && (completion == ROLLBACK_AND_CHAIN))
784
776
        result= startTransaction();
785
777
      break;
790
782
  }
791
783
 
792
784
  if (result == false)
793
 
  {
794
785
    my_error(killed_errno(), MYF(0));
795
 
  }
796
786
  else if ((result == true) && do_release)
797
 
  {
798
 
    setKilled(Session::KILL_CONNECTION);
799
 
  }
 
787
    killed= Session::KILL_CONNECTION;
800
788
 
801
789
  return result;
802
790
}
804
792
bool Session::endActiveTransaction()
805
793
{
806
794
  bool result= true;
807
 
  TransactionServices &transaction_services= TransactionServices::singleton();
808
795
 
809
796
  if (transaction.xid_state.xa_state != XA_NOTR)
810
797
  {
811
798
    my_error(ER_XAER_RMFAIL, MYF(0), xa_state_names[transaction.xid_state.xa_state]);
812
799
    return false;
813
800
  }
814
 
  if (options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
 
801
  if (options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN | OPTION_TABLE_LOCK))
815
802
  {
 
803
    /* Safety if one did "drop table" on locked tables */
 
804
    if (! locked_tables)
 
805
      options&= ~OPTION_TABLE_LOCK;
816
806
    server_status&= ~SERVER_STATUS_IN_TRANS;
817
 
    if (transaction_services.commitTransaction(this, true))
 
807
    if (ha_commit(this))
818
808
      result= false;
819
809
  }
820
 
  options&= ~(OPTION_BEGIN);
 
810
  options&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
 
811
  transaction.all.modified_non_trans_table= false;
821
812
  return result;
822
813
}
823
814
 
824
 
bool Session::startTransaction(start_transaction_option_t opt)
 
815
bool Session::startTransaction()
825
816
{
826
817
  bool result= true;
827
818
 
 
819
  if (locked_tables)
 
820
  {
 
821
    lock= locked_tables;
 
822
    locked_tables= 0;                   // Will be automatically closed
 
823
    close_thread_tables();                      // Free tables
 
824
  }
828
825
  if (! endActiveTransaction())
829
 
  {
830
826
    result= false;
831
 
  }
832
827
  else
833
828
  {
834
829
    options|= OPTION_BEGIN;
835
830
    server_status|= SERVER_STATUS_IN_TRANS;
836
 
 
837
 
    if (plugin::TransactionalStorageEngine::notifyStartTransaction(this, opt))
838
 
    {
839
 
      result= false;
840
 
    }
 
831
    if (lex->start_transaction_opt & DRIZZLE_START_TRANS_OPT_WITH_CONS_SNAPSHOT)
 
832
      if (ha_start_consistent_snapshot(this))
 
833
        result= false;
841
834
  }
842
 
 
843
835
  return result;
844
836
}
845
837
 
 
838
/*
 
839
  Cleanup after query.
 
840
 
 
841
  SYNOPSIS
 
842
    Session::cleanup_after_query()
 
843
 
 
844
  DESCRIPTION
 
845
    This function is used to reset thread data to its default state.
 
846
 
 
847
  NOTE
 
848
    This function is not suitable for setting thread data to some
 
849
    non-default values, as there is only one replication thread, so
 
850
    different master threads may overwrite data of each other on
 
851
    slave.
 
852
*/
846
853
void Session::cleanup_after_query()
847
854
{
848
855
  /*
856
863
  if (first_successful_insert_id_in_cur_stmt > 0)
857
864
  {
858
865
    /* set what LAST_INSERT_ID() will return */
859
 
    first_successful_insert_id_in_prev_stmt= first_successful_insert_id_in_cur_stmt;
 
866
    first_successful_insert_id_in_prev_stmt=
 
867
      first_successful_insert_id_in_cur_stmt;
860
868
    first_successful_insert_id_in_cur_stmt= 0;
861
869
    substitute_null_with_insert_id= true;
862
870
  }
863
 
  arg_of_last_insert_id_function= false;
 
871
  arg_of_last_insert_id_function= 0;
864
872
  /* Free Items that were created during this execution */
865
873
  free_items();
866
874
  /* Reset where. */
867
875
  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
876
}
875
877
 
 
878
 
876
879
/**
877
880
  Create a LEX_STRING in this connection.
878
881
 
884
887
  @return  NULL on failure, or pointer to the LEX_STRING object
885
888
*/
886
889
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)
 
890
                                 const char* str, uint32_t length,
 
891
                                 bool allocate_lex_string)
896
892
{
897
893
  if (allocate_lex_string)
898
894
    if (!(lex_str= (LEX_STRING *)alloc(sizeof(LEX_STRING))))
899
895
      return 0;
900
 
  if (!(lex_str->str= mem_root->strmake_root(str, length)))
 
896
  if (!(lex_str->str= strmake_root(mem_root, str, length)))
901
897
    return 0;
902
898
  lex_str->length= length;
903
899
  return lex_str;
904
900
}
905
901
 
 
902
 
 
903
/*
 
904
  Convert a string to another character set
 
905
 
 
906
  SYNOPSIS
 
907
    convert_string()
 
908
    to                          Store new allocated string here
 
909
    to_cs                       New character set for allocated string
 
910
    from                        String to convert
 
911
    from_length                 Length of string to convert
 
912
    from_cs                     Original character set
 
913
 
 
914
  NOTES
 
915
    to will be 0-terminated to make it easy to pass to system funcs
 
916
 
 
917
  RETURN
 
918
    0   ok
 
919
    1   End of memory.
 
920
        In this case to->str will point to 0 and to->length will be 0.
 
921
*/
 
922
 
 
923
bool Session::convert_string(LEX_STRING *to, const CHARSET_INFO * const to_cs,
 
924
                         const char *from, uint32_t from_length,
 
925
                         const CHARSET_INFO * const from_cs)
 
926
{
 
927
  size_t new_length= to_cs->mbmaxlen * from_length;
 
928
  uint32_t dummy_errors;
 
929
  if (!(to->str= (char*) alloc(new_length+1)))
 
930
  {
 
931
    to->length= 0;                              // Safety fix
 
932
    return(1);                          // EOM
 
933
  }
 
934
  to->length= copy_and_convert((char*) to->str, new_length, to_cs,
 
935
                               from, from_length, from_cs, &dummy_errors);
 
936
  to->str[to->length]=0;                        // Safety
 
937
  return(0);
 
938
}
 
939
 
 
940
 
 
941
/*
 
942
  Convert string from source character set to target character set inplace.
 
943
 
 
944
  SYNOPSIS
 
945
    Session::convert_string
 
946
 
 
947
  DESCRIPTION
 
948
    Convert string using convert_buffer - buffer for character set
 
949
    conversion shared between all protocols.
 
950
 
 
951
  RETURN
 
952
    0   ok
 
953
   !0   out of memory
 
954
*/
 
955
 
 
956
bool Session::convert_string(String *s, const CHARSET_INFO * const from_cs,
 
957
                         const CHARSET_INFO * const to_cs)
 
958
{
 
959
  uint32_t dummy_errors;
 
960
  if (convert_buffer.copy(s->ptr(), s->length(), from_cs, to_cs, &dummy_errors))
 
961
    return true;
 
962
  /* If convert_buffer >> s copying is more efficient long term */
 
963
  if (convert_buffer.alloced_length() >= convert_buffer.length() * 2 ||
 
964
      !s->is_alloced())
 
965
  {
 
966
    return s->copy(convert_buffer);
 
967
  }
 
968
  s->swap(convert_buffer);
 
969
  return false;
 
970
}
 
971
 
 
972
 
 
973
/*
 
974
  Update some cache variables when character set changes
 
975
*/
 
976
 
 
977
void Session::update_charset()
 
978
{
 
979
  uint32_t not_used;
 
980
  charset_is_system_charset= !String::needs_conversion(0,charset(),
 
981
                                                       system_charset_info,
 
982
                                                       &not_used);
 
983
  charset_is_collation_connection=
 
984
    !String::needs_conversion(0,charset(),variables.getCollation(),
 
985
                              &not_used);
 
986
  charset_is_character_set_filesystem=
 
987
    !String::needs_conversion(0, charset(),
 
988
                              variables.character_set_filesystem, &not_used);
 
989
}
 
990
 
 
991
 
 
992
/* routings to adding tables to list of changed in transaction tables */
 
993
 
 
994
inline static void list_include(CHANGED_TableList** prev,
 
995
                                CHANGED_TableList* curr,
 
996
                                CHANGED_TableList* new_table)
 
997
{
 
998
  if (new_table)
 
999
  {
 
1000
    *prev = new_table;
 
1001
    (*prev)->next = curr;
 
1002
  }
 
1003
}
 
1004
 
 
1005
/* add table to list of changed in transaction tables */
 
1006
 
 
1007
void Session::add_changed_table(Table *table)
 
1008
{
 
1009
  assert((options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) &&
 
1010
              table->file->has_transactions());
 
1011
  add_changed_table(table->s->table_cache_key.str,
 
1012
                    (long) table->s->table_cache_key.length);
 
1013
}
 
1014
 
 
1015
 
 
1016
void Session::add_changed_table(const char *key, long key_length)
 
1017
{
 
1018
  CHANGED_TableList **prev_changed = &transaction.changed_tables;
 
1019
  CHANGED_TableList *curr = transaction.changed_tables;
 
1020
 
 
1021
  for (; curr; prev_changed = &(curr->next), curr = curr->next)
 
1022
  {
 
1023
    int cmp =  (long)curr->key_length - (long)key_length;
 
1024
    if (cmp < 0)
 
1025
    {
 
1026
      list_include(prev_changed, curr, changed_table_dup(key, key_length));
 
1027
      return;
 
1028
    }
 
1029
    else if (cmp == 0)
 
1030
    {
 
1031
      cmp = memcmp(curr->key, key, curr->key_length);
 
1032
      if (cmp < 0)
 
1033
      {
 
1034
        list_include(prev_changed, curr, changed_table_dup(key, key_length));
 
1035
        return;
 
1036
      }
 
1037
      else if (cmp == 0)
 
1038
      {
 
1039
        return;
 
1040
      }
 
1041
    }
 
1042
  }
 
1043
  *prev_changed = changed_table_dup(key, key_length);
 
1044
}
 
1045
 
 
1046
 
 
1047
CHANGED_TableList* Session::changed_table_dup(const char *key, long key_length)
 
1048
{
 
1049
  CHANGED_TableList* new_table =
 
1050
    (CHANGED_TableList*) trans_alloc(ALIGN_SIZE(sizeof(CHANGED_TableList))+
 
1051
                                      key_length + 1);
 
1052
  if (!new_table)
 
1053
  {
 
1054
    my_error(EE_OUTOFMEMORY, MYF(ME_BELL),
 
1055
             ALIGN_SIZE(sizeof(TableList)) + key_length + 1);
 
1056
    killed= KILL_CONNECTION;
 
1057
    return 0;
 
1058
  }
 
1059
 
 
1060
  new_table->key= ((char*)new_table)+ ALIGN_SIZE(sizeof(CHANGED_TableList));
 
1061
  new_table->next = 0;
 
1062
  new_table->key_length = key_length;
 
1063
  ::memcpy(new_table->key, key, key_length);
 
1064
  return new_table;
 
1065
}
 
1066
 
 
1067
 
906
1068
int Session::send_explain_fields(select_result *result)
907
1069
{
908
1070
  List<Item> field_list;
938
1100
  }
939
1101
  item->maybe_null= 1;
940
1102
  field_list.push_back(new Item_empty_string("Extra", 255, cs));
941
 
  return (result->send_fields(field_list));
942
 
}
943
 
 
944
 
void select_result::send_error(uint32_t errcode, const char *err)
945
 
{
946
 
  my_message(errcode, err, MYF(0));
 
1103
  return (result->send_fields(field_list,
 
1104
                              Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF));
947
1105
}
948
1106
 
949
1107
/************************************************************************
955
1113
  my_message(errcode, err, MYF(0));
956
1114
  if (file > 0)
957
1115
  {
958
 
    (void) cache->end_io_cache();
959
 
    (void) internal::my_close(file, MYF(0));
960
 
    (void) internal::my_delete(path.file_string().c_str(), MYF(0));             // Delete file on error
 
1116
    (void) end_io_cache(&cache);
 
1117
    (void) my_close(file,MYF(0));
 
1118
    (void) my_delete(path,MYF(0));              // Delete file on error
961
1119
    file= -1;
962
1120
  }
963
1121
}
965
1123
 
966
1124
bool select_to_file::send_eof()
967
1125
{
968
 
  int error= test(cache->end_io_cache());
969
 
  if (internal::my_close(file, MYF(MY_WME)))
 
1126
  int error= test(end_io_cache(&cache));
 
1127
  if (my_close(file,MYF(MY_WME)))
970
1128
    error= 1;
971
1129
  if (!error)
972
1130
  {
987
1145
  /* In case of error send_eof() may be not called: close the file here. */
988
1146
  if (file >= 0)
989
1147
  {
990
 
    (void) cache->end_io_cache();
991
 
    (void) internal::my_close(file, MYF(0));
 
1148
    (void) end_io_cache(&cache);
 
1149
    (void) my_close(file,MYF(0));
992
1150
    file= -1;
993
1151
  }
994
 
  path= "";
 
1152
  path[0]= '\0';
995
1153
  row_count= 0;
996
1154
}
997
1155
 
998
 
select_to_file::select_to_file(file_exchange *ex)
999
 
  : exchange(ex),
1000
 
    file(-1),
1001
 
    cache(static_cast<internal::IO_CACHE *>(memory::sql_calloc(sizeof(internal::IO_CACHE)))),
1002
 
    row_count(0L)
1003
 
{
1004
 
  path= "";
1005
 
}
1006
1156
 
1007
1157
select_to_file::~select_to_file()
1008
1158
{
1009
 
  cleanup();
 
1159
  if (file >= 0)
 
1160
  {                                     // This only happens in case of error
 
1161
    (void) end_io_cache(&cache);
 
1162
    (void) my_close(file,MYF(0));
 
1163
    file= -1;
 
1164
  }
1010
1165
}
1011
1166
 
1012
1167
/***************************************************************************
1035
1190
*/
1036
1191
 
1037
1192
 
1038
 
static int create_file(Session *session,
1039
 
                       fs::path &target_path,
1040
 
                       file_exchange *exchange,
1041
 
                       internal::IO_CACHE *cache)
 
1193
static File create_file(Session *session, char *path, file_exchange *exchange, IO_CACHE *cache)
1042
1194
{
1043
 
  fs::path to_file(exchange->file_name);
1044
 
  int file;
1045
 
 
1046
 
  if (not to_file.has_root_directory())
 
1195
  File file;
 
1196
  uint32_t option= MY_UNPACK_FILENAME | MY_RELATIVE_PATH;
 
1197
 
 
1198
#ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS
 
1199
  option|= MY_REPLACE_DIR;                      // Force use of db directory
 
1200
#endif
 
1201
 
 
1202
  if (!dirname_length(exchange->file_name))
1047
1203
  {
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;
 
1204
    strcpy(path, drizzle_real_data_home);
 
1205
    if (session->db)
 
1206
      strncat(path, session->db, FN_REFLEN-strlen(drizzle_real_data_home)-1);
 
1207
    (void) fn_format(path, exchange->file_name, path, "", option);
1064
1208
  }
1065
1209
  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))
 
1210
    (void) fn_format(path, exchange->file_name, drizzle_real_data_home, "", option);
 
1211
 
 
1212
  if (opt_secure_file_priv &&
 
1213
      strncmp(opt_secure_file_priv, path, strlen(opt_secure_file_priv)))
 
1214
  {
 
1215
    /* Write only allowed to dir or subdir specified by secure_file_priv */
 
1216
    my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
 
1217
    return -1;
 
1218
  }
 
1219
 
 
1220
  if (!access(path, F_OK))
1081
1221
  {
1082
1222
    my_error(ER_FILE_EXISTS_ERROR, MYF(0), exchange->file_name);
1083
1223
    return -1;
1084
1224
  }
1085
1225
  /* 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)
 
1226
  if ((file= my_create(path, 0666, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0)
1087
1227
    return file;
 
1228
#ifdef HAVE_FCHMOD
1088
1229
  (void) fchmod(file, 0666);                    // Because of umask()
1089
 
  if (cache->init_io_cache(file, 0L, internal::WRITE_CACHE, 0L, 1, MYF(MY_WME)))
 
1230
#else
 
1231
  (void) chmod(path, 0666);
 
1232
#endif
 
1233
  if (init_io_cache(cache, file, 0L, WRITE_CACHE, 0L, 1, MYF(MY_WME)))
1090
1234
  {
1091
 
    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
 
1235
    my_close(file, MYF(0));
 
1236
    my_delete(path, MYF(0));  // Delete file on error, it was just created
1093
1237
    return -1;
1094
1238
  }
1095
1239
  return file;
1103
1247
  bool string_results= false, non_string_results= false;
1104
1248
  unit= u;
1105
1249
  if ((uint32_t) strlen(exchange->file_name) + NAME_LEN >= FN_REFLEN)
1106
 
  {
1107
 
    path= exchange->file_name;
1108
 
  }
 
1250
    strncpy(path,exchange->file_name,FN_REFLEN-1);
1109
1251
 
1110
1252
  /* Check if there is any blobs in data */
1111
1253
  {
1115
1257
    {
1116
1258
      if (item->max_length >= MAX_BLOB_WIDTH)
1117
1259
      {
1118
 
        blob_flag=1;
1119
 
        break;
 
1260
        blob_flag=1;
 
1261
        break;
1120
1262
      }
1121
 
 
1122
1263
      if (item->result_type() == STRING_RESULT)
1123
1264
        string_results= true;
1124
1265
      else
1153
1294
    return 1;
1154
1295
  }
1155
1296
 
1156
 
  if ((file= create_file(session, path, exchange, cache)) < 0)
 
1297
  if ((file= create_file(session, path, exchange, &cache)) < 0)
1157
1298
    return 1;
1158
1299
 
1159
1300
  return 0;
1160
1301
}
1161
1302
 
 
1303
 
 
1304
#define NEED_ESCAPING(x) ((int) (unsigned char) (x) == escape_char    || \
 
1305
                          (enclosed ? (int) (unsigned char) (x) == field_sep_char      \
 
1306
                                    : (int) (unsigned char) (x) == field_term_char) || \
 
1307
                          (int) (unsigned char) (x) == line_sep_char  || \
 
1308
                          !(x))
 
1309
 
1162
1310
bool select_export::send_data(List<Item> &items)
1163
1311
{
1164
1312
  char buff[MAX_FIELD_WIDTH],null_buff[2],space[MAX_FIELD_WIDTH];
1169
1317
  if (unit->offset_limit_cnt)
1170
1318
  {                                             // using limit offset,count
1171
1319
    unit->offset_limit_cnt--;
1172
 
    return false;
 
1320
    return(0);
1173
1321
  }
1174
1322
  row_count++;
1175
1323
  Item *item;
1176
1324
  uint32_t used_length=0,items_left=items.elements;
1177
1325
  List_iterator_fast<Item> li(items);
1178
1326
 
1179
 
  if (my_b_write(cache,(unsigned char*) exchange->line_start->ptr(),
1180
 
                 exchange->line_start->length()))
1181
 
    return true;
1182
 
 
 
1327
  if (my_b_write(&cache,(unsigned char*) exchange->line_start->ptr(),
 
1328
                 exchange->line_start->length()))
 
1329
    goto err;
1183
1330
  while ((item=li++))
1184
1331
  {
1185
1332
    Item_result result_type=item->result_type();
1188
1335
    res=item->str_result(&tmp);
1189
1336
    if (res && enclosed)
1190
1337
    {
1191
 
      if (my_b_write(cache,(unsigned char*) exchange->enclosed->ptr(),
1192
 
                     exchange->enclosed->length()))
1193
 
        return true;
 
1338
      if (my_b_write(&cache,(unsigned char*) exchange->enclosed->ptr(),
 
1339
                     exchange->enclosed->length()))
 
1340
        goto err;
1194
1341
    }
1195
1342
    if (!res)
1196
1343
    {                                           // NULL
1197
1344
      if (!fixed_row_size)
1198
1345
      {
1199
 
        if (escape_char != -1)                  // Use \N syntax
1200
 
        {
1201
 
          null_buff[0]=escape_char;
1202
 
          null_buff[1]='N';
1203
 
          if (my_b_write(cache,(unsigned char*) null_buff,2))
1204
 
            return true;
1205
 
        }
1206
 
        else if (my_b_write(cache,(unsigned char*) "NULL",4))
1207
 
          return true;
 
1346
        if (escape_char != -1)                  // Use \N syntax
 
1347
        {
 
1348
          null_buff[0]=escape_char;
 
1349
          null_buff[1]='N';
 
1350
          if (my_b_write(&cache,(unsigned char*) null_buff,2))
 
1351
            goto err;
 
1352
        }
 
1353
        else if (my_b_write(&cache,(unsigned char*) "NULL",4))
 
1354
          goto err;
1208
1355
      }
1209
1356
      else
1210
1357
      {
1211
 
        used_length=0;                          // Fill with space
 
1358
        used_length=0;                          // Fill with space
1212
1359
      }
1213
1360
    }
1214
1361
    else
1215
1362
    {
1216
1363
      if (fixed_row_size)
1217
 
        used_length= min(res->length(), static_cast<size_t>(item->max_length));
 
1364
        used_length=cmin(res->length(),item->max_length);
1218
1365
      else
1219
 
        used_length= res->length();
1220
 
 
 
1366
        used_length=res->length();
1221
1367
      if ((result_type == STRING_RESULT || is_unsafe_field_sep) &&
1222
 
          escape_char != -1)
 
1368
           escape_char != -1)
1223
1369
      {
1224
1370
        char *pos, *start, *end;
1225
1371
        const CHARSET_INFO * const res_charset= res->charset();
1226
1372
        const CHARSET_INFO * const character_set_client= default_charset_info;
1227
1373
 
1228
1374
        bool check_second_byte= (res_charset == &my_charset_bin) &&
1229
 
          character_set_client->
1230
 
          escape_with_backslash_is_dangerous;
 
1375
                                 character_set_client->
 
1376
                                 escape_with_backslash_is_dangerous;
1231
1377
        assert(character_set_client->mbmaxlen == 2 ||
1232
1378
               !character_set_client->escape_with_backslash_is_dangerous);
1233
 
        for (start=pos=(char*) res->ptr(),end=pos+used_length ;
1234
 
             pos != end ;
1235
 
             pos++)
1236
 
        {
1237
 
          if (use_mb(res_charset))
1238
 
          {
1239
 
            int l;
1240
 
            if ((l=my_ismbchar(res_charset, pos, end)))
1241
 
            {
1242
 
              pos += l-1;
1243
 
              continue;
1244
 
            }
1245
 
          }
 
1379
        for (start=pos=(char*) res->ptr(),end=pos+used_length ;
 
1380
             pos != end ;
 
1381
             pos++)
 
1382
        {
 
1383
#ifdef USE_MB
 
1384
          if (use_mb(res_charset))
 
1385
          {
 
1386
            int l;
 
1387
            if ((l=my_ismbchar(res_charset, pos, end)))
 
1388
            {
 
1389
              pos += l-1;
 
1390
              continue;
 
1391
            }
 
1392
          }
 
1393
#endif
1246
1394
 
1247
1395
          /*
1248
1396
            Special case when dumping BINARY/VARBINARY/BLOB values
1276
1424
            assert before the loop makes that sure.
1277
1425
          */
1278
1426
 
1279
 
          if ((needs_escaping(*pos, enclosed) ||
 
1427
          if ((NEED_ESCAPING(*pos) ||
1280
1428
               (check_second_byte &&
1281
1429
                my_mbcharlen(character_set_client, (unsigned char) *pos) == 2 &&
1282
1430
                pos + 1 < end &&
1283
 
                needs_escaping(pos[1], enclosed))) &&
 
1431
                NEED_ESCAPING(pos[1]))) &&
1284
1432
              /*
1285
 
                Don't escape field_term_char by doubling - doubling is only
1286
 
                valid for ENCLOSED BY characters:
 
1433
               Don't escape field_term_char by doubling - doubling is only
 
1434
               valid for ENCLOSED BY characters:
1287
1435
              */
1288
1436
              (enclosed || !is_ambiguous_field_term ||
1289
1437
               (int) (unsigned char) *pos != field_term_char))
1290
1438
          {
1291
 
            char tmp_buff[2];
 
1439
            char tmp_buff[2];
1292
1440
            tmp_buff[0]= ((int) (unsigned char) *pos == field_sep_char &&
1293
1441
                          is_ambiguous_field_sep) ?
1294
 
              field_sep_char : escape_char;
1295
 
            tmp_buff[1]= *pos ? *pos : '0';
1296
 
            if (my_b_write(cache,(unsigned char*) start,(uint32_t) (pos-start)) ||
1297
 
                my_b_write(cache,(unsigned char*) tmp_buff,2))
1298
 
              return true;
1299
 
            start=pos+1;
1300
 
          }
1301
 
        }
1302
 
        if (my_b_write(cache,(unsigned char*) start,(uint32_t) (pos-start)))
1303
 
          return true;
 
1442
                          field_sep_char : escape_char;
 
1443
            tmp_buff[1]= *pos ? *pos : '0';
 
1444
            if (my_b_write(&cache,(unsigned char*) start,(uint32_t) (pos-start)) ||
 
1445
                my_b_write(&cache,(unsigned char*) tmp_buff,2))
 
1446
              goto err;
 
1447
            start=pos+1;
 
1448
          }
 
1449
        }
 
1450
        if (my_b_write(&cache,(unsigned char*) start,(uint32_t) (pos-start)))
 
1451
          goto err;
1304
1452
      }
1305
 
      else if (my_b_write(cache,(unsigned char*) res->ptr(),used_length))
1306
 
        return true;
 
1453
      else if (my_b_write(&cache,(unsigned char*) res->ptr(),used_length))
 
1454
        goto err;
1307
1455
    }
1308
1456
    if (fixed_row_size)
1309
1457
    {                                           // Fill with space
1310
1458
      if (item->max_length > used_length)
1311
1459
      {
1312
 
        /* QQ:  Fix by adding a my_b_fill() function */
1313
 
        if (!space_inited)
1314
 
        {
1315
 
          space_inited=1;
1316
 
          memset(space, ' ', sizeof(space));
1317
 
        }
1318
 
        uint32_t length=item->max_length-used_length;
1319
 
        for (; length > sizeof(space) ; length-=sizeof(space))
1320
 
        {
1321
 
          if (my_b_write(cache,(unsigned char*) space,sizeof(space)))
1322
 
            return true;
1323
 
        }
1324
 
        if (my_b_write(cache,(unsigned char*) space,length))
1325
 
          return true;
 
1460
        /* QQ:  Fix by adding a my_b_fill() function */
 
1461
        if (!space_inited)
 
1462
        {
 
1463
          space_inited=1;
 
1464
          memset(space, ' ', sizeof(space));
 
1465
        }
 
1466
        uint32_t length=item->max_length-used_length;
 
1467
        for (; length > sizeof(space) ; length-=sizeof(space))
 
1468
        {
 
1469
          if (my_b_write(&cache,(unsigned char*) space,sizeof(space)))
 
1470
            goto err;
 
1471
        }
 
1472
        if (my_b_write(&cache,(unsigned char*) space,length))
 
1473
          goto err;
1326
1474
      }
1327
1475
    }
1328
1476
    if (res && enclosed)
1329
1477
    {
1330
 
      if (my_b_write(cache, (unsigned char*) exchange->enclosed->ptr(),
 
1478
      if (my_b_write(&cache, (unsigned char*) exchange->enclosed->ptr(),
1331
1479
                     exchange->enclosed->length()))
1332
 
        return true;
 
1480
        goto err;
1333
1481
    }
1334
1482
    if (--items_left)
1335
1483
    {
1336
 
      if (my_b_write(cache, (unsigned char*) exchange->field_term->ptr(),
 
1484
      if (my_b_write(&cache, (unsigned char*) exchange->field_term->ptr(),
1337
1485
                     field_term_length))
1338
 
        return true;
 
1486
        goto err;
1339
1487
    }
1340
1488
  }
1341
 
  if (my_b_write(cache,(unsigned char*) exchange->line_term->ptr(),
1342
 
                 exchange->line_term->length()))
1343
 
  {
1344
 
    return true;
1345
 
  }
1346
 
 
1347
 
  return false;
 
1489
  if (my_b_write(&cache,(unsigned char*) exchange->line_term->ptr(),
 
1490
                 exchange->line_term->length()))
 
1491
    goto err;
 
1492
  return(0);
 
1493
err:
 
1494
  return(1);
1348
1495
}
1349
1496
 
1350
1497
 
1357
1504
select_dump::prepare(List<Item> &, Select_Lex_Unit *u)
1358
1505
{
1359
1506
  unit= u;
1360
 
  return (int) ((file= create_file(session, path, exchange, cache)) < 0);
 
1507
  return (int) ((file= create_file(session, path, exchange, &cache)) < 0);
1361
1508
}
1362
1509
 
1363
1510
 
1377
1524
  if (row_count++ > 1)
1378
1525
  {
1379
1526
    my_message(ER_TOO_MANY_ROWS, ER(ER_TOO_MANY_ROWS), MYF(0));
1380
 
    return 1;
 
1527
    goto err;
1381
1528
  }
1382
1529
  while ((item=li++))
1383
1530
  {
1384
1531
    res=item->str_result(&tmp);
1385
1532
    if (!res)                                   // If NULL
1386
1533
    {
1387
 
      if (my_b_write(cache,(unsigned char*) "",1))
1388
 
        return 1;
 
1534
      if (my_b_write(&cache,(unsigned char*) "",1))
 
1535
        goto err;
1389
1536
    }
1390
 
    else if (my_b_write(cache,(unsigned char*) res->ptr(),res->length()))
 
1537
    else if (my_b_write(&cache,(unsigned char*) res->ptr(),res->length()))
1391
1538
    {
1392
 
      my_error(ER_ERROR_ON_WRITE, MYF(0), path.file_string().c_str(), errno);
1393
 
      return 1;
 
1539
      my_error(ER_ERROR_ON_WRITE, MYF(0), path, my_errno);
 
1540
      goto err;
1394
1541
    }
1395
1542
  }
1396
1543
  return(0);
 
1544
err:
 
1545
  return(1);
1397
1546
}
1398
1547
 
1399
1548
 
1451
1600
      switch (val_item->result_type())
1452
1601
      {
1453
1602
      case REAL_RESULT:
1454
 
        op= &select_max_min_finder_subselect::cmp_real;
1455
 
        break;
 
1603
        op= &select_max_min_finder_subselect::cmp_real;
 
1604
        break;
1456
1605
      case INT_RESULT:
1457
 
        op= &select_max_min_finder_subselect::cmp_int;
1458
 
        break;
 
1606
        op= &select_max_min_finder_subselect::cmp_int;
 
1607
        break;
1459
1608
      case STRING_RESULT:
1460
 
        op= &select_max_min_finder_subselect::cmp_str;
1461
 
        break;
 
1609
        op= &select_max_min_finder_subselect::cmp_str;
 
1610
        break;
1462
1611
      case DECIMAL_RESULT:
1463
1612
        op= &select_max_min_finder_subselect::cmp_decimal;
1464
1613
        break;
1465
1614
      case ROW_RESULT:
1466
1615
        // This case should never be choosen
1467
 
        assert(0);
1468
 
        op= 0;
 
1616
        assert(0);
 
1617
        op= 0;
1469
1618
      }
1470
1619
    }
1471
1620
    cache->store(val_item);
1547
1696
  return(0);
1548
1697
}
1549
1698
 
 
1699
 
 
1700
/*
 
1701
  Statement functions
 
1702
*/
 
1703
 
 
1704
Statement::Statement(LEX *lex_arg, MEM_ROOT *mem_root_arg, ulong id_arg)
 
1705
  :Query_arena(mem_root_arg),
 
1706
  id(id_arg),
 
1707
  mark_used_columns(MARK_COLUMNS_READ),
 
1708
  lex(lex_arg),
 
1709
  query(0),
 
1710
  query_length(0),
 
1711
  db(NULL),
 
1712
  db_length(0)
 
1713
{
 
1714
}
 
1715
 
 
1716
 
1550
1717
/*
1551
1718
  Don't free mem_root, as mem_root is freed in the end of dispatch_command
1552
1719
  (once for any command).
1554
1721
void Session::end_statement()
1555
1722
{
1556
1723
  /* Cleanup SQL processing state to reuse this statement in next query. */
1557
 
  lex->end();
1558
 
  query_cache_key= ""; // reset the cache key
1559
 
  resetResultsetMessage();
 
1724
  lex_end(lex);
1560
1725
}
1561
1726
 
 
1727
 
1562
1728
bool Session::copy_db_to(char **p_db, size_t *p_db_length)
1563
1729
{
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
 
 
 
1730
  if (db == NULL)
 
1731
  {
 
1732
    my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
 
1733
    return true;
 
1734
  }
 
1735
  *p_db= strmake(db, db_length);
 
1736
  *p_db_length= db_length;
1580
1737
  return false;
1581
1738
}
1582
1739
 
 
1740
 
1583
1741
/****************************************************************************
1584
1742
  Tmp_Table_Param
1585
1743
****************************************************************************/
1591
1749
  quick_group= 1;
1592
1750
  table_charset= 0;
1593
1751
  precomputed_group_by= 0;
 
1752
  bit_fields_as_long= 0;
1594
1753
}
1595
1754
 
1596
1755
void Tmp_Table_Param::cleanup(void)
1603
1762
  }
1604
1763
}
1605
1764
 
 
1765
 
 
1766
void session_increment_bytes_sent(ulong length)
 
1767
{
 
1768
  Session *session=current_session;
 
1769
  if (likely(session != 0))
 
1770
  { /* current_session==0 when disconnect() calls net_send_error() */
 
1771
    session->status_var.bytes_sent+= length;
 
1772
  }
 
1773
}
 
1774
 
 
1775
 
 
1776
void session_increment_bytes_received(ulong length)
 
1777
{
 
1778
  current_session->status_var.bytes_received+= length;
 
1779
}
 
1780
 
 
1781
 
 
1782
void session_increment_net_big_packet_count(ulong length)
 
1783
{
 
1784
  current_session->status_var.net_big_packet_count+= length;
 
1785
}
 
1786
 
1606
1787
void Session::send_kill_message() const
1607
1788
{
1608
1789
  int err= killed_errno();
1615
1796
  memset(&status_var, 0, sizeof(status_var));
1616
1797
}
1617
1798
 
1618
 
 
1619
 
void Session::set_db(const std::string &new_db)
 
1799
void Security_context::skip_grants()
 
1800
{
 
1801
  /* privileges for the user are unknown everything is allowed */
 
1802
}
 
1803
 
 
1804
 
 
1805
/****************************************************************************
 
1806
  Handling of open and locked tables states.
 
1807
 
 
1808
  This is used when we want to open/lock (and then close) some tables when
 
1809
  we already have a set of tables open and locked. We use these methods for
 
1810
  access to mysql.proc table to find definitions of stored routines.
 
1811
****************************************************************************/
 
1812
 
 
1813
void Session::reset_n_backup_open_tables_state(Open_tables_state *backup)
 
1814
{
 
1815
  backup->set_open_tables_state(this);
 
1816
  reset_open_tables_state();
 
1817
  state_flags|= Open_tables_state::BACKUPS_AVAIL;
 
1818
}
 
1819
 
 
1820
 
 
1821
void Session::restore_backup_open_tables_state(Open_tables_state *backup)
 
1822
{
 
1823
  /*
 
1824
    Before we will throw away current open tables state we want
 
1825
    to be sure that it was properly cleaned up.
 
1826
  */
 
1827
  assert(open_tables == 0 && temporary_tables == 0 &&
 
1828
              derived_tables == 0 &&
 
1829
              lock == 0 && locked_tables == 0);
 
1830
  set_open_tables_state(backup);
 
1831
}
 
1832
 
 
1833
 
 
1834
bool Session::set_db(const char *new_db, size_t new_db_len)
1620
1835
{
1621
1836
  /* 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
 
  }
 
1837
  if (db && new_db && db_length >= new_db_len)
 
1838
    memcpy(db, new_db, new_db_len+1);
1626
1839
  else
1627
1840
  {
1628
 
    _schema.reset(new std::string(""));
 
1841
    if (db)
 
1842
      free(db);
 
1843
    if (new_db)
 
1844
    {
 
1845
      db= (char *)malloc(new_db_len + 1);
 
1846
      if (db != NULL)
 
1847
      {
 
1848
        memcpy(db, new_db, new_db_len);
 
1849
        db[new_db_len]= 0;
 
1850
      }
 
1851
    }
 
1852
    else
 
1853
      db= NULL;
1629
1854
  }
 
1855
  db_length= db ? new_db_len : 0;
 
1856
  return new_db && !db;
 
1857
}
 
1858
 
 
1859
 
 
1860
/**
 
1861
  Check the killed state of a user thread
 
1862
  @param session  user thread
 
1863
  @retval 0 the user thread is active
 
1864
  @retval 1 the user thread has been killed
 
1865
*/
 
1866
extern "C" int session_killed(const Session *session)
 
1867
{
 
1868
  return(session->killed);
 
1869
}
 
1870
 
 
1871
/**
 
1872
  Return the thread id of a user thread
 
1873
  @param session user thread
 
1874
  @return thread id
 
1875
*/
 
1876
extern "C" unsigned long session_get_thread_id(const Session *session)
 
1877
{
 
1878
  return((unsigned long)session->thread_id);
 
1879
}
 
1880
 
 
1881
 
 
1882
extern "C"
 
1883
LEX_STRING *session_make_lex_string(Session *session, LEX_STRING *lex_str,
 
1884
                                const char *str, unsigned int size,
 
1885
                                int allocate_lex_string)
 
1886
{
 
1887
  return session->make_lex_string(lex_str, str, size,
 
1888
                              (bool) allocate_lex_string);
 
1889
}
 
1890
 
 
1891
extern "C" const struct charset_info_st *session_charset(Session *session)
 
1892
{
 
1893
  return(session->charset());
 
1894
}
 
1895
 
 
1896
extern "C" char **session_query(Session *session)
 
1897
{
 
1898
  return(&session->query);
 
1899
}
 
1900
 
 
1901
extern "C" int session_non_transactional_update(const Session *session)
 
1902
{
 
1903
  return(session->transaction.all.modified_non_trans_table);
 
1904
}
 
1905
 
 
1906
extern "C" void session_mark_transaction_to_rollback(Session *session, bool all)
 
1907
{
 
1908
  mark_transaction_to_rollback(session, all);
1630
1909
}
1631
1910
 
1632
1911
 
1636
1915
  @param  session   Thread handle
1637
1916
  @param  all   true <=> rollback main transaction.
1638
1917
*/
 
1918
 
1639
1919
void mark_transaction_to_rollback(Session *session, bool all)
1640
1920
{
1641
1921
  if (session)
1651
1931
  plugin_sessionvar_cleanup(this);
1652
1932
 
1653
1933
  /* If necessary, log any aborted or unauthorized connections */
1654
 
  if (getKilled() || client->wasAborted())
1655
 
  {
1656
 
    status_var.aborted_threads++;
1657
 
  }
 
1934
  if (killed || protocol->wasAborted())
 
1935
    statistic_increment(aborted_threads, &LOCK_status);
1658
1936
 
1659
 
  if (client->wasAborted())
 
1937
  if (protocol->wasAborted())
1660
1938
  {
1661
 
    if (not getKilled() && variables.log_warnings > 1)
 
1939
    if (! killed && variables.log_warnings > 1)
1662
1940
    {
1663
 
      SecurityContext *sctx= &security_ctx;
 
1941
      Security_context *sctx= &security_ctx;
1664
1942
 
1665
1943
      errmsg_printf(ERRMSG_LVL_WARN, ER(ER_NEW_ABORTING_CONNECTION)
1666
1944
                  , thread_id
1667
 
                  , (_schema->empty() ? "unconnected" : _schema->c_str())
1668
 
                  , sctx->getUser().empty() == false ? sctx->getUser().c_str() : "unauthenticated"
1669
 
                  , sctx->getIp().c_str()
 
1945
                  , (db ? db : "unconnected")
 
1946
                  , sctx->user.empty() == false ? sctx->user.c_str() : "unauthenticated"
 
1947
                  , sctx->ip.c_str()
1670
1948
                  , (main_da.is_error() ? main_da.message() : ER(ER_UNKNOWN_ERROR)));
1671
1949
    }
1672
1950
  }
1673
1951
 
1674
1952
  /* Close out our connection to the client */
1675
1953
  if (should_lock)
1676
 
    session::Cache::singleton().mutex().lock();
1677
 
 
1678
 
  setKilled(Session::KILL_CONNECTION);
1679
 
 
1680
 
  if (client->isConnected())
 
1954
    (void) pthread_mutex_lock(&LOCK_thread_count);
 
1955
  killed= Session::KILL_CONNECTION;
 
1956
  if (protocol->isConnected())
1681
1957
  {
1682
1958
    if (errcode)
1683
1959
    {
1684
1960
      /*my_error(errcode, ER(errcode));*/
1685
 
      client->sendError(errcode, ER(errcode));
 
1961
      protocol->sendError(errcode, ER(errcode)); /* purecov: inspected */
1686
1962
    }
1687
 
    client->close();
 
1963
    protocol->close();
1688
1964
  }
1689
 
 
1690
1965
  if (should_lock)
1691
 
  {
1692
 
    session::Cache::singleton().mutex().unlock();
1693
 
  }
 
1966
    (void) pthread_mutex_unlock(&LOCK_thread_count);
1694
1967
}
1695
1968
 
 
1969
/**
 
1970
 Reset Session part responsible for command processing state.
 
1971
 
 
1972
   This needs to be called before execution of every statement
 
1973
   (prepared or conventional).
 
1974
   It is not called by substatements of routines.
 
1975
 
 
1976
  @todo
 
1977
   Make it a method of Session and align its name with the rest of
 
1978
   reset/end/start/init methods.
 
1979
  @todo
 
1980
   Call it after we use Session for queries, not before.
 
1981
*/
 
1982
 
1696
1983
void Session::reset_for_next_command()
1697
1984
{
1698
1985
  free_list= 0;
1703
1990
  */
1704
1991
  auto_inc_intervals_in_cur_stmt_for_binlog.empty();
1705
1992
 
1706
 
  is_fatal_error= false;
 
1993
  is_fatal_error= 0;
1707
1994
  server_status&= ~ (SERVER_MORE_RESULTS_EXISTS |
1708
1995
                          SERVER_QUERY_NO_INDEX_USED |
1709
1996
                          SERVER_QUERY_NO_GOOD_INDEX_USED);
 
1997
  /*
 
1998
    If in autocommit mode and not in a transaction, reset
 
1999
    OPTION_STATUS_NO_TRANS_UPDATE | OPTION_KEEP_LOG to not get warnings
 
2000
    in ha_rollback_trans() about some tables couldn't be rolled back.
 
2001
  */
 
2002
  if (!(options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))
 
2003
  {
 
2004
    options&= ~OPTION_KEEP_LOG;
 
2005
    transaction.all.modified_non_trans_table= false;
 
2006
  }
1710
2007
 
1711
2008
  clear_error();
1712
2009
  main_da.reset_diagnostics_area();
1716
2013
 
1717
2014
/*
1718
2015
  Close all temporary tables created by 'CREATE TEMPORARY TABLE' for thread
 
2016
  creates one DROP TEMPORARY Table binlog event for each pseudo-thread
1719
2017
*/
1720
2018
 
1721
 
void Open_tables_state::close_temporary_tables()
 
2019
void Session::close_temporary_tables()
1722
2020
{
1723
2021
  Table *table;
1724
2022
  Table *tmp_next;
1725
2023
 
1726
 
  if (not temporary_tables)
 
2024
  if (!temporary_tables)
1727
2025
    return;
1728
2026
 
1729
2027
  for (table= temporary_tables; table; table= tmp_next)
1730
2028
  {
1731
 
    tmp_next= table->getNext();
1732
 
    nukeTable(table);
 
2029
    tmp_next= table->next;
 
2030
    close_temporary(table, 1, 1);
1733
2031
  }
1734
2032
  temporary_tables= NULL;
1735
2033
}
1736
2034
 
1737
 
/*
1738
 
  unlink from session->temporary tables and close temporary table
1739
 
*/
1740
 
 
1741
 
void Open_tables_state::close_temporary_table(Table *table)
1742
 
{
1743
 
  if (table->getPrev())
1744
 
  {
1745
 
    table->getPrev()->setNext(table->getNext());
1746
 
    if (table->getPrev()->getNext())
1747
 
    {
1748
 
      table->getNext()->setPrev(table->getPrev());
1749
 
    }
1750
 
  }
1751
 
  else
1752
 
  {
1753
 
    /* removing the item from the list */
1754
 
    assert(table == temporary_tables);
1755
 
    /*
1756
 
      slave must reset its temporary list pointer to zero to exclude
1757
 
      passing non-zero value to end_slave via rli->save_temporary_tables
1758
 
      when no temp tables opened, see an invariant below.
1759
 
    */
1760
 
    temporary_tables= table->getNext();
1761
 
    if (temporary_tables)
1762
 
    {
1763
 
      table->getNext()->setPrev(NULL);
1764
 
    }
1765
 
  }
1766
 
  nukeTable(table);
1767
 
}
1768
 
 
1769
 
/*
1770
 
  Close and drop a temporary table
1771
 
 
1772
 
  NOTE
1773
 
  This dosn't unlink table from session->temporary
1774
 
  If this is needed, use close_temporary_table()
1775
 
*/
1776
 
 
1777
 
void Open_tables_state::nukeTable(Table *table)
1778
 
{
1779
 
  plugin::StorageEngine *table_type= table->getShare()->db_type();
1780
 
 
1781
 
  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();
1788
 
 
1789
 
  /* This makes me sad, but we're allocating it via malloc */
1790
 
  delete table;
1791
 
}
1792
2035
 
1793
2036
/** Clear most status variables. */
1794
2037
extern time_t flush_status_time;
 
2038
extern uint32_t max_used_connections;
1795
2039
 
1796
2040
void Session::refresh_status()
1797
2041
{
 
2042
  pthread_mutex_lock(&LOCK_status);
 
2043
 
 
2044
  /* Add thread's status variabes to global status */
 
2045
  add_to_status(&global_status_var, &status_var);
 
2046
 
1798
2047
  /* Reset thread's status variables */
1799
2048
  memset(&status_var, 0, sizeof(status_var));
1800
2049
 
 
2050
  /* Reset some global variables */
 
2051
  reset_status_vars();
 
2052
 
 
2053
  /* Reset the counters of all key caches (default and named). */
 
2054
  process_key_caches(reset_key_cache_counters);
1801
2055
  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;
 
2056
  max_used_connections= 1; /* We set it to one, because we know we exist */
 
2057
  pthread_mutex_unlock(&LOCK_status);
1804
2058
}
1805
2059
 
 
2060
#define extra_size sizeof(double)
 
2061
 
1806
2062
user_var_entry *Session::getVariable(LEX_STRING &name, bool create_if_not_exists)
1807
2063
{
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
2064
  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)
 
2065
 
 
2066
  assert(name.length == strlen (name.str));
 
2067
  entry= (user_var_entry*) hash_search(&user_vars, (unsigned char*) name.str, name.length);
 
2068
 
 
2069
  if ((entry == NULL) && create_if_not_exists)
1833
2070
  {
1834
 
    delete entry;
 
2071
    uint32_t size=ALIGN_SIZE(sizeof(user_var_entry))+name.length+1+extra_size;
 
2072
    if (!hash_inited(&user_vars))
 
2073
      return 0;
 
2074
    if (!(entry = (user_var_entry*) malloc(size)))
 
2075
      return 0;
 
2076
    entry->name.str=(char*) entry+ ALIGN_SIZE(sizeof(user_var_entry))+
 
2077
      extra_size;
 
2078
    entry->name.length=name.length;
 
2079
    entry->value=0;
 
2080
    entry->length=0;
 
2081
    entry->update_query_id=0;
 
2082
    entry->collation.set(NULL, DERIVATION_IMPLICIT);
 
2083
    entry->unsigned_flag= 0;
 
2084
    /*
 
2085
      If we are here, we were called from a SET or a query which sets a
 
2086
      variable. Imagine it is this:
 
2087
      INSERT INTO t SELECT @a:=10, @a:=@a+1.
 
2088
      Then when we have a Item_func_get_user_var (because of the @a+1) so we
 
2089
      think we have to write the value of @a to the binlog. But before that,
 
2090
      we have a Item_func_set_user_var to create @a (@a:=10), in this we mark
 
2091
      the variable as "already logged" (line below) so that it won't be logged
 
2092
      by Item_func_get_user_var (because that's not necessary).
 
2093
    */
 
2094
    entry->used_query_id= query_id;
 
2095
    entry->type=STRING_RESULT;
 
2096
    memcpy(entry->name.str, name.str, name.length+1);
 
2097
    if (my_hash_insert(&user_vars, (unsigned char*) entry))
 
2098
    {
 
2099
      assert(1);
 
2100
      free((char*) entry);
 
2101
      return 0;
 
2102
    }
 
2103
 
1835
2104
  }
1836
2105
 
1837
2106
  return entry;
1838
2107
}
1839
2108
 
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())
 
2109
/**
 
2110
  Mark all temporary tables which were used by the current statement or
 
2111
  substatement as free for reuse, but only if the query_id can be cleared.
 
2112
 
 
2113
  @param session thread context
 
2114
 
 
2115
  @remark For temp tables associated with a open SQL HANDLER the query_id
 
2116
          is not reset until the HANDLER is closed.
 
2117
*/
 
2118
 
 
2119
void Session::mark_temp_tables_as_free_for_reuse()
 
2120
{
 
2121
  for (Table *table= temporary_tables ; table ; table= table->next)
1854
2122
  {
1855
 
    if (table->query_id == getQueryId())
 
2123
    if (table->query_id == query_id)
1856
2124
    {
1857
2125
      table->query_id= 0;
1858
 
      table->cursor->ha_reset();
 
2126
      table->file->ha_reset();
1859
2127
    }
1860
2128
  }
1861
2129
}
1862
2130
 
 
2131
 
 
2132
/*
 
2133
  Mark all tables in the list which were used by current substatement
 
2134
  as free for reuse.
 
2135
 
 
2136
  SYNOPSIS
 
2137
    mark_used_tables_as_free_for_reuse()
 
2138
      session   - thread context
 
2139
      table - head of the list of tables
 
2140
 
 
2141
  DESCRIPTION
 
2142
    Marks all tables in the list which were used by current substatement
 
2143
    (they are marked by its query_id) as free for reuse.
 
2144
 
 
2145
  NOTE
 
2146
    The reason we reset query_id is that it's not enough to just test
 
2147
    if table->query_id != session->query_id to know if a table is in use.
 
2148
 
 
2149
    For example
 
2150
    SELECT f1_that_uses_t1() FROM t1;
 
2151
    In f1_that_uses_t1() we will see one instance of t1 where query_id is
 
2152
    set to query_id of original query.
 
2153
*/
 
2154
 
1863
2155
void Session::mark_used_tables_as_free_for_reuse(Table *table)
1864
2156
{
1865
 
  for (; table ; table= table->getNext())
 
2157
  for (; table ; table= table->next)
1866
2158
  {
1867
 
    if (table->query_id == getQueryId())
 
2159
    if (table->query_id == query_id)
1868
2160
    {
1869
2161
      table->query_id= 0;
1870
 
      table->cursor->ha_reset();
 
2162
      table->file->ha_reset();
1871
2163
    }
1872
2164
  }
1873
2165
}
1874
2166
 
 
2167
 
1875
2168
/*
1876
 
  Unlocks tables and frees derived tables.
1877
 
  Put all normal tables used by thread in free list.
1878
 
 
1879
 
  It will only close/mark as free for reuse tables opened by this
1880
 
  substatement, it will also check if we are closing tables after
1881
 
  execution of complete query (i.e. we are on upper level) and will
1882
 
  leave prelocked mode if needed.
 
2169
  Close all tables used by the current substatement, or all tables
 
2170
  used by this thread if we are on the upper level.
 
2171
 
 
2172
  SYNOPSIS
 
2173
    close_thread_tables()
 
2174
    session                     Thread handler
 
2175
 
 
2176
  IMPLEMENTATION
 
2177
    Unlocks tables and frees derived tables.
 
2178
    Put all normal tables used by thread in free list.
 
2179
 
 
2180
    It will only close/mark as free for reuse tables opened by this
 
2181
    substatement, it will also check if we are closing tables after
 
2182
    execution of complete query (i.e. we are on upper level) and will
 
2183
    leave prelocked mode if needed.
1883
2184
*/
 
2185
 
1884
2186
void Session::close_thread_tables()
1885
2187
{
1886
 
  clearDerivedTables();
 
2188
  Table *table;
 
2189
 
 
2190
  /*
 
2191
    We are assuming here that session->derived_tables contains ONLY derived
 
2192
    tables for this substatement. i.e. instead of approach which uses
 
2193
    query_id matching for determining which of the derived tables belong
 
2194
    to this substatement we rely on the ability of substatements to
 
2195
    save/restore session->derived_tables during their execution.
 
2196
 
 
2197
    TODO: Probably even better approach is to simply associate list of
 
2198
          derived tables with (sub-)statement instead of thread and destroy
 
2199
          them at the end of its execution.
 
2200
  */
 
2201
  if (derived_tables)
 
2202
  {
 
2203
    Table *next;
 
2204
    /*
 
2205
      Close all derived tables generated in queries like
 
2206
      SELECT * FROM (SELECT * FROM t1)
 
2207
    */
 
2208
    for (table= derived_tables ; table ; table= next)
 
2209
    {
 
2210
      next= table->next;
 
2211
      table->free_tmp_table(this);
 
2212
    }
 
2213
    derived_tables= 0;
 
2214
  }
1887
2215
 
1888
2216
  /*
1889
2217
    Mark all temporary tables used by this statement as free for reuse.
1897
2225
    does not belong to statement for which we do close_thread_tables()).
1898
2226
    TODO: This should be fixed in later releases.
1899
2227
   */
 
2228
  if (!(state_flags & Open_tables_state::BACKUPS_AVAIL))
1900
2229
  {
1901
 
    TransactionServices &transaction_services= TransactionServices::singleton();
1902
2230
    main_da.can_overwrite_status= true;
1903
 
    transaction_services.autocommitOrRollback(this, is_error());
 
2231
    ha_autocommit_or_rollback(this, is_error());
1904
2232
    main_da.can_overwrite_status= false;
1905
2233
    transaction.stmt.reset();
1906
2234
  }
1907
2235
 
 
2236
  if (locked_tables)
 
2237
  {
 
2238
 
 
2239
    /* Ensure we are calling ha_reset() for all used tables */
 
2240
    mark_used_tables_as_free_for_reuse(open_tables);
 
2241
 
 
2242
    /*
 
2243
      We are under simple LOCK TABLES so should not do anything else.
 
2244
    */
 
2245
    return;
 
2246
  }
 
2247
 
1908
2248
  if (lock)
1909
2249
  {
1910
2250
    /*
1916
2256
      handled either before writing a query log event (inside
1917
2257
      binlog_query()) or when preparing a pending event.
1918
2258
     */
1919
 
    unlockTables(lock);
 
2259
    mysql_unlock_tables(this, lock);
1920
2260
    lock= 0;
1921
2261
  }
1922
2262
  /*
1923
 
    Note that we need to hold table::Cache::singleton().mutex() while changing the
 
2263
    Note that we need to hold LOCK_open while changing the
1924
2264
    open_tables list. Another thread may work on it.
1925
 
    (See: table::Cache::singleton().removeTable(), mysql_wait_completed_table())
 
2265
    (See: remove_table_from_cache(), mysql_wait_completed_table())
1926
2266
    Closing a MERGE child before the parent would be fatal if the
1927
2267
    other thread tries to abort the MERGE lock in between.
1928
2268
  */
1929
2269
  if (open_tables)
1930
2270
    close_open_tables();
1931
2271
}
1932
 
 
1933
 
void Session::close_tables_for_reopen(TableList **tables)
1934
 
{
1935
 
  /*
1936
 
    If table list consists only from tables from prelocking set, table list
1937
 
    for new attempt should be empty, so we have to update list's root pointer.
1938
 
  */
1939
 
  if (lex->first_not_own_table() == *tables)
1940
 
    *tables= 0;
1941
 
  lex->chop_off_not_own_tables();
1942
 
  for (TableList *tmp= *tables; tmp; tmp= tmp->next_global)
1943
 
    tmp->table= 0;
1944
 
  close_thread_tables();
1945
 
}
1946
 
 
1947
 
bool Session::openTablesLock(TableList *tables)
1948
 
{
1949
 
  uint32_t counter;
1950
 
  bool need_reopen;
1951
 
 
1952
 
  for ( ; ; )
1953
 
  {
1954
 
    if (open_tables_from_list(&tables, &counter))
1955
 
      return true;
1956
 
 
1957
 
    if (not lock_tables(tables, counter, &need_reopen))
1958
 
      break;
1959
 
    if (not need_reopen)
1960
 
      return true;
1961
 
    close_tables_for_reopen(&tables);
1962
 
  }
1963
 
  if ((mysql_handle_derived(lex, &mysql_derived_prepare) ||
1964
 
       (
1965
 
        mysql_handle_derived(lex, &mysql_derived_filling))))
1966
 
    return true;
1967
 
 
1968
 
  return false;
1969
 
}
1970
 
 
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 */
2180
 
 
2181
 
} /* namespace drizzled */