~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/session.cc

  • Committer: Monty Taylor
  • Date: 2009-03-18 18:45:23 UTC
  • mto: (950.1.1 mordred)
  • mto: This revision was merged to the branch mainline in revision 943.
  • Revision ID: mordred@inaugust.com-20090318184523-mfbjyj5wkipv4n3b
Moved big tests to big suite. Added make target "make test-big" to allow for easy running of the big tests.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
3
 *
4
 
 *  Copyright (C) 2008 Sun Microsystems, Inc.
 
4
 *  Copyright (C) 2008 Sun Microsystems
5
5
 *
6
6
 *  This program is free software; you can redistribute it and/or modify
7
7
 *  it under the terms of the GNU General Public License as published by
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
 
 
26
 
#include <drizzled/copy_field.h>
 
20
#include <drizzled/server_includes.h>
 
21
#include <drizzled/session.h>
 
22
#include <sys/stat.h>
 
23
#include <mysys/mysys_err.h>
 
24
#include <drizzled/error.h>
 
25
#include <drizzled/query_id.h>
27
26
#include <drizzled/data_home.h>
28
 
#include <drizzled/display.h>
29
 
#include <drizzled/drizzled.h>
30
 
#include <drizzled/error.h>
31
 
#include <drizzled/gettext.h>
32
 
#include <drizzled/identifier.h>
33
 
#include <drizzled/internal/iocache.h>
34
 
#include <drizzled/internal/thread_var.h>
35
 
#include <drizzled/internal_error_handler.h>
 
27
#include <drizzled/sql_base.h>
 
28
#include <drizzled/lock.h>
36
29
#include <drizzled/item/cache.h>
37
 
#include <drizzled/item/empty_string.h>
38
30
#include <drizzled/item/float.h>
39
31
#include <drizzled/item/return_int.h>
40
 
#include <drizzled/lock.h>
41
 
#include <drizzled/plugin/authentication.h>
42
 
#include <drizzled/plugin/client.h>
43
 
#include <drizzled/plugin/event_observer.h>
44
 
#include <drizzled/plugin/logging.h>
45
 
#include <drizzled/plugin/query_rewrite.h>
46
 
#include <drizzled/plugin/scheduler.h>
47
 
#include <drizzled/plugin/transactional_storage_engine.h>
48
 
#include <drizzled/probes.h>
49
 
#include <drizzled/pthread_globals.h>
50
 
#include <drizzled/query_id.h>
51
 
#include <drizzled/refresh_version.h>
52
 
#include <drizzled/select_dump.h>
53
 
#include <drizzled/select_exists_subselect.h>
54
 
#include <drizzled/select_export.h>
55
 
#include <drizzled/select_max_min_finder_subselect.h>
56
 
#include <drizzled/select_singlerow_subselect.h>
57
 
#include <drizzled/select_subselect.h>
58
 
#include <drizzled/select_to_file.h>
59
 
#include <drizzled/session.h>
60
 
#include <drizzled/session/cache.h>
 
32
#include <drizzled/item/empty_string.h>
61
33
#include <drizzled/show.h>
62
 
#include <drizzled/sql_base.h>
63
 
#include <drizzled/table/singular.h>
64
 
#include <drizzled/table_proto.h>
65
 
#include <drizzled/tmp_table_param.h>
66
 
#include <drizzled/transaction_services.h>
67
 
#include <drizzled/user_var_entry.h>
68
 
#include <drizzled/util/functors.h>
69
 
#include <plugin/myisam/myisam.h>
70
 
 
71
 
#include <algorithm>
72
 
#include <climits>
73
 
#include <fcntl.h>
74
 
#include <sys/stat.h>
75
 
 
76
 
#include <boost/filesystem.hpp>
77
 
#include <boost/checked_delete.hpp>
78
 
 
79
 
#include <drizzled/util/backtrace.h>
80
 
 
81
 
#include <drizzled/schema.h>
82
 
 
83
 
using namespace std;
84
 
 
85
 
namespace fs=boost::filesystem;
86
 
namespace drizzled
87
 
{
88
 
 
 
34
#include <drizzled/plugin_scheduling.h>
 
35
#include <libdrizzleclient/errmsg.h>
 
36
 
 
37
extern scheduling_st thread_scheduler;
89
38
/*
90
39
  The following is used to initialise Table_ident with a internal
91
40
  table name
94
43
char empty_c_string[1]= {0};    /* used for not defined db */
95
44
 
96
45
const char * const Session::DEFAULT_WHERE= "field list";
 
46
extern pthread_key_t THR_Session;
 
47
extern pthread_key_t THR_Mem_root;
 
48
 
 
49
 
 
50
/*****************************************************************************
 
51
** Instansiate templates
 
52
*****************************************************************************/
 
53
 
 
54
#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
 
55
/* Used templates */
 
56
template class List<Key>;
 
57
template class List_iterator<Key>;
 
58
template class List<Key_part_spec>;
 
59
template class List_iterator<Key_part_spec>;
 
60
template class List<Alter_drop>;
 
61
template class List_iterator<Alter_drop>;
 
62
template class List<Alter_column>;
 
63
template class List_iterator<Alter_column>;
 
64
#endif
 
65
 
 
66
 
 
67
/****************************************************************************
 
68
** User variables
 
69
****************************************************************************/
 
70
 
 
71
extern "C" unsigned char *get_var_key(user_var_entry *entry, size_t *length,
 
72
                              bool )
 
73
{
 
74
  *length= entry->name.length;
 
75
  return (unsigned char*) entry->name.str;
 
76
}
 
77
 
 
78
extern "C" void free_user_var(user_var_entry *entry)
 
79
{
 
80
  char *pos= (char*) entry+ALIGN_SIZE(sizeof(*entry));
 
81
  if (entry->value && entry->value != pos)
 
82
    free(entry->value);
 
83
  free((char*) entry);
 
84
}
97
85
 
98
86
bool Key_part_spec::operator==(const Key_part_spec& other) const
99
87
{
100
88
  return length == other.length &&
101
89
         field_name.length == other.field_name.length &&
102
 
    !my_strcasecmp(system_charset_info, field_name.str, other.field_name.str);
103
 
}
104
 
 
105
 
Open_tables_state::Open_tables_state(uint64_t version_arg) :
106
 
  version(version_arg)
107
 
{
108
 
  open_tables= temporary_tables= derived_tables= NULL;
109
 
  extra_lock= lock= NULL;
 
90
         !strcmp(field_name.str, other.field_name.str);
 
91
}
 
92
 
 
93
/**
 
94
  Construct an (almost) deep copy of this key. Only those
 
95
  elements that are known to never change are not copied.
 
96
  If out of memory, a partial copy is returned and an error is set
 
97
  in Session.
 
98
*/
 
99
 
 
100
Key::Key(const Key &rhs, MEM_ROOT *mem_root)
 
101
  :type(rhs.type),
 
102
  key_create_info(rhs.key_create_info),
 
103
  columns(rhs.columns, mem_root),
 
104
  name(rhs.name),
 
105
  generated(rhs.generated)
 
106
{
 
107
  list_copy_and_replace_each_value(columns, mem_root);
 
108
}
 
109
 
 
110
/**
 
111
  Construct an (almost) deep copy of this foreign key. Only those
 
112
  elements that are known to never change are not copied.
 
113
  If out of memory, a partial copy is returned and an error is set
 
114
  in Session.
 
115
*/
 
116
 
 
117
Foreign_key::Foreign_key(const Foreign_key &rhs, MEM_ROOT *mem_root)
 
118
  :Key(rhs),
 
119
  ref_table(rhs.ref_table),
 
120
  ref_columns(rhs.ref_columns),
 
121
  delete_opt(rhs.delete_opt),
 
122
  update_opt(rhs.update_opt),
 
123
  match_opt(rhs.match_opt)
 
124
{
 
125
  list_copy_and_replace_each_value(ref_columns, mem_root);
 
126
}
 
127
 
 
128
/*
 
129
  Test if a foreign key (= generated key) is a prefix of the given key
 
130
  (ignoring key name, key type and order of columns)
 
131
 
 
132
  NOTES:
 
133
    This is only used to test if an index for a FOREIGN KEY exists
 
134
 
 
135
  IMPLEMENTATION
 
136
    We only compare field names
 
137
 
 
138
  RETURN
 
139
    0   Generated key is a prefix of other key
 
140
    1   Not equal
 
141
*/
 
142
 
 
143
bool foreign_key_prefix(Key *a, Key *b)
 
144
{
 
145
  /* Ensure that 'a' is the generated key */
 
146
  if (a->generated)
 
147
  {
 
148
    if (b->generated && a->columns.elements > b->columns.elements)
 
149
      std::swap(a, b);                       // Put shorter key in 'a'
 
150
  }
 
151
  else
 
152
  {
 
153
    if (!b->generated)
 
154
      return true;                              // No foreign key
 
155
    std::swap(a, b);                       // Put generated key in 'a'
 
156
  }
 
157
 
 
158
  /* Test if 'a' is a prefix of 'b' */
 
159
  if (a->columns.elements > b->columns.elements)
 
160
    return true;                                // Can't be prefix
 
161
 
 
162
  List_iterator<Key_part_spec> col_it1(a->columns);
 
163
  List_iterator<Key_part_spec> col_it2(b->columns);
 
164
  const Key_part_spec *col1, *col2;
 
165
 
 
166
#ifdef ENABLE_WHEN_INNODB_CAN_HANDLE_SWAPED_FOREIGN_KEY_COLUMNS
 
167
  while ((col1= col_it1++))
 
168
  {
 
169
    bool found= 0;
 
170
    col_it2.rewind();
 
171
    while ((col2= col_it2++))
 
172
    {
 
173
      if (*col1 == *col2)
 
174
      {
 
175
        found= true;
 
176
        break;
 
177
      }
 
178
    }
 
179
    if (!found)
 
180
      return true;                              // Error
 
181
  }
 
182
  return false;                                 // Is prefix
 
183
#else
 
184
  while ((col1= col_it1++))
 
185
  {
 
186
    col2= col_it2++;
 
187
    if (!(*col1 == *col2))
 
188
      return true;
 
189
  }
 
190
  return false;                                 // Is prefix
 
191
#endif
 
192
}
 
193
 
 
194
 
 
195
/*
 
196
  Check if the foreign key options are compatible with columns
 
197
  on which the FK is created.
 
198
 
 
199
  RETURN
 
200
    0   Key valid
 
201
    1   Key invalid
 
202
*/
 
203
bool Foreign_key::validate(List<Create_field> &table_fields)
 
204
{
 
205
  Create_field  *sql_field;
 
206
  Key_part_spec *column;
 
207
  List_iterator<Key_part_spec> cols(columns);
 
208
  List_iterator<Create_field> it(table_fields);
 
209
  while ((column= cols++))
 
210
  {
 
211
    it.rewind();
 
212
    while ((sql_field= it++) &&
 
213
           my_strcasecmp(system_charset_info,
 
214
                         column->field_name.str,
 
215
                         sql_field->field_name)) {}
 
216
    if (!sql_field)
 
217
    {
 
218
      my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), column->field_name.str);
 
219
      return true;
 
220
    }
 
221
    if (type == Key::FOREIGN_KEY && sql_field->vcol_info)
 
222
    {
 
223
      if (delete_opt == FK_OPTION_SET_NULL)
 
224
      {
 
225
        my_error(ER_WRONG_FK_OPTION_FOR_VIRTUAL_COLUMN, MYF(0),
 
226
                 "ON DELETE SET NULL");
 
227
        return true;
 
228
      }
 
229
      if (update_opt == FK_OPTION_SET_NULL)
 
230
      {
 
231
        my_error(ER_WRONG_FK_OPTION_FOR_VIRTUAL_COLUMN, MYF(0),
 
232
                 "ON UPDATE SET NULL");
 
233
        return true;
 
234
      }
 
235
      if (update_opt == FK_OPTION_CASCADE)
 
236
      {
 
237
        my_error(ER_WRONG_FK_OPTION_FOR_VIRTUAL_COLUMN, MYF(0),
 
238
                 "ON UPDATE CASCADE");
 
239
        return true;
 
240
      }
 
241
    }
 
242
  }
 
243
  return false;
 
244
}
 
245
 
 
246
 
 
247
/****************************************************************************
 
248
** Thread specific functions
 
249
****************************************************************************/
 
250
 
 
251
Open_tables_state::Open_tables_state(ulong version_arg)
 
252
  :version(version_arg), state_flags(0U)
 
253
{
 
254
  reset_open_tables_state();
110
255
}
111
256
 
112
257
/*
113
258
  The following functions form part of the C plugin API
114
259
*/
115
 
int tmpfile(const char *prefix)
 
260
 
 
261
extern "C" int mysql_tmpfile(const char *prefix)
116
262
{
117
263
  char filename[FN_REFLEN];
118
 
  int fd = internal::create_temp_file(filename, drizzle_tmpdir.c_str(), prefix, MYF(MY_WME));
 
264
  File fd = create_temp_file(filename, drizzle_tmpdir, prefix,
 
265
                             O_CREAT | O_EXCL | O_RDWR,
 
266
                             MYF(MY_WME));
119
267
  if (fd >= 0) {
120
268
    unlink(filename);
121
269
  }
123
271
  return fd;
124
272
}
125
273
 
126
 
void **Session::getEngineData(const plugin::MonitoredInTransaction *monitored)
127
 
{
128
 
  return static_cast<void **>(&ha_data[monitored->getId()].ha_ptr);
129
 
}
130
 
 
131
 
ResourceContext *Session::getResourceContext(const plugin::MonitoredInTransaction *monitored,
132
 
                                             size_t index)
133
 
{
134
 
  return &ha_data[monitored->getId()].resource_context[index];
135
 
}
136
 
 
 
274
 
 
275
extern "C"
 
276
int session_in_lock_tables(const Session *session)
 
277
{
 
278
  return test(session->in_lock_tables);
 
279
}
 
280
 
 
281
 
 
282
extern "C"
 
283
int session_tablespace_op(const Session *session)
 
284
{
 
285
  return test(session->tablespace_op);
 
286
}
 
287
 
 
288
 
 
289
/**
 
290
   Set the process info field of the Session structure.
 
291
 
 
292
   This function is used by plug-ins. Internally, the
 
293
   Session::set_proc_info() function should be used.
 
294
 
 
295
   @see Session::set_proc_info
 
296
 */
 
297
extern "C" void
 
298
set_session_proc_info(Session *session, const char *info)
 
299
{
 
300
  session->set_proc_info(info);
 
301
}
 
302
 
 
303
extern "C"
 
304
const char *get_session_proc_info(Session *session)
 
305
{
 
306
  return session->get_proc_info();
 
307
}
 
308
 
 
309
extern "C"
 
310
void **session_ha_data(const Session *session, const struct handlerton *hton)
 
311
{
 
312
  return (void **) &session->ha_data[hton->slot].ha_ptr;
 
313
}
 
314
 
 
315
extern "C"
137
316
int64_t session_test_options(const Session *session, int64_t test_options)
138
317
{
139
318
  return session->options & test_options;
140
319
}
141
320
 
142
 
Session::Session(plugin::Client *client_arg, catalog::Instance::shared_ptr catalog_arg) :
143
 
  Open_tables_state(refresh_version),
144
 
  mem_root(&main_mem_root),
145
 
  xa_id(0),
146
 
  lex(&main_lex),
147
 
  query(new std::string),
148
 
  _schema(new std::string("")),
149
 
  client(client_arg),
150
 
  scheduler(NULL),
151
 
  scheduler_arg(NULL),
152
 
  lock_id(&main_lock_id),
153
 
  thread_stack(NULL),
154
 
  security_ctx(identifier::User::make_shared()),
155
 
  _where(Session::DEFAULT_WHERE),
156
 
  dbug_sentry(Session_SENTRY_MAGIC),
157
 
  mysys_var(0),
158
 
  command(COM_CONNECT),
159
 
  file_id(0),
160
 
  _epoch(boost::gregorian::date(1970,1,1)),
161
 
  _connect_time(boost::posix_time::microsec_clock::universal_time()),
162
 
  utime_after_lock(0),
163
 
  ha_data(plugin::num_trx_monitored_objects),
164
 
  query_id(0),
165
 
  warn_query_id(0),
166
 
  concurrent_execute_allowed(true),
167
 
  arg_of_last_insert_id_function(false),
168
 
  first_successful_insert_id_in_prev_stmt(0),
169
 
  first_successful_insert_id_in_cur_stmt(0),
170
 
  limit_found_rows(0),
171
 
  options(session_startup_options),
172
 
  row_count_func(-1),
173
 
  sent_row_count(0),
174
 
  examined_row_count(0),
175
 
  used_tables(0),
176
 
  total_warn_count(0),
177
 
  col_access(0),
178
 
  statement_id_counter(0),
179
 
  row_count(0),
180
 
  thread_id(0),
181
 
  tmp_table(0),
182
 
  _global_read_lock(NONE),
183
 
  count_cuted_fields(CHECK_FIELD_ERROR_FOR_NULL),
184
 
  _killed(NOT_KILLED),
185
 
  some_tables_deleted(false),
186
 
  no_errors(false),
187
 
  password(false),
188
 
  is_fatal_error(false),
189
 
  transaction_rollback_request(false),
190
 
  is_fatal_sub_stmt_error(0),
191
 
  tablespace_op(false),
192
 
  derived_tables_processing(false),
193
 
  m_lip(NULL),
194
 
  cached_table(0),
195
 
  transaction_message(NULL),
196
 
  statement_message(NULL),
197
 
  session_event_observers(NULL),
198
 
  _catalog(catalog_arg),
199
 
  use_usage(false)
200
 
{
201
 
  client->setSession(this);
 
321
extern "C"
 
322
int session_sql_command(const Session *session)
 
323
{
 
324
  return (int) session->lex->sql_command;
 
325
}
 
326
 
 
327
extern "C"
 
328
int session_tx_isolation(const Session *session)
 
329
{
 
330
  return (int) session->variables.tx_isolation;
 
331
}
 
332
 
 
333
extern "C"
 
334
void session_inc_row_count(Session *session)
 
335
{
 
336
  session->row_count++;
 
337
}
 
338
 
 
339
Session::Session()
 
340
   :Statement(&main_lex, &main_mem_root,
 
341
              /* statement id */ 0),
 
342
   Open_tables_state(refresh_version),
 
343
   lock_id(&main_lock_id),
 
344
   user_time(0),
 
345
   arg_of_last_insert_id_function(false),
 
346
   first_successful_insert_id_in_prev_stmt(0),
 
347
   first_successful_insert_id_in_cur_stmt(0),
 
348
   global_read_lock(0),
 
349
   is_fatal_error(0),
 
350
   transaction_rollback_request(0),
 
351
   is_fatal_sub_stmt_error(0),
 
352
   in_lock_tables(0),
 
353
   derived_tables_processing(false),
 
354
   m_lip(NULL),
 
355
   scheduler(0)
 
356
{
 
357
  uint64_t tmp;
202
358
 
203
359
  /*
204
360
    Pass nominal parameters to init_alloc_root only to ensure that
205
361
    the destructor works OK in case of an error. The main_mem_root
206
362
    will be re-initialized in init_for_queries().
207
363
  */
208
 
  memory::init_sql_alloc(&main_mem_root, memory::ROOT_MIN_BLOCK_SIZE, 0);
 
364
  init_sql_alloc(&main_mem_root, ALLOC_ROOT_MIN_BLOCK_SIZE, 0);
 
365
  thread_stack= 0;
 
366
  catalog= (char*)"std"; // the only catalog we have for now
 
367
  some_tables_deleted=no_errors=password= 0;
 
368
  count_cuted_fields= CHECK_FIELD_IGNORE;
 
369
  killed= NOT_KILLED;
 
370
  col_access=0;
 
371
  thread_specific_used= false;
 
372
  tmp_table=0;
 
373
  used_tables=0;
209
374
  cuted_fields= sent_row_count= row_count= 0L;
 
375
  limit_found_rows= 0;
 
376
  row_count_func= -1;
 
377
  statement_id_counter= 0UL;
210
378
  // Must be reset to handle error with Session's created for init of mysqld
211
379
  lex->current_select= 0;
 
380
  start_time=(time_t) 0;
 
381
  start_utime= 0L;
 
382
  utime_after_lock= 0L;
212
383
  memset(&variables, 0, sizeof(variables));
213
 
  scoreboard_index= -1;
214
 
  cleanup_done= abort_on_warning= no_warnings_for_error= false;  
215
 
 
216
 
  /* query_cache init */
217
 
  query_cache_key= "";
218
 
  resultset= NULL;
 
384
  thread_id= 0;
 
385
  file_id = 0;
 
386
  query_id= 0;
 
387
  warn_id= 0;
 
388
  db_charset= global_system_variables.collation_database;
 
389
  memset(ha_data, 0, sizeof(ha_data));
 
390
  replication_data= 0;
 
391
  mysys_var=0;
 
392
  dbug_sentry=Session_SENTRY_MAGIC;
 
393
  net.vio= 0;
 
394
  client_capabilities= 0;                       // minimalistic client
 
395
  system_thread= NON_SYSTEM_THREAD;
 
396
  cleanup_done= abort_on_warning= no_warnings_for_error= 0;
 
397
  peer_port= 0;                                 // For SHOW PROCESSLIST
 
398
  transaction.on= 1;
 
399
  pthread_mutex_init(&LOCK_delete, MY_MUTEX_INIT_FAST);
219
400
 
220
401
  /* Variables with default values */
221
402
  proc_info="login";
222
 
 
223
 
  plugin_sessionvar_init(this);
224
 
  /*
225
 
    variables= global_system_variables above has reset
226
 
    variables.pseudo_thread_id to 0. We need to correct it here to
227
 
    avoid temporary tables replication failure.
228
 
  */
229
 
  variables.pseudo_thread_id= thread_id;
230
 
  server_status= SERVER_STATUS_AUTOCOMMIT;
231
 
 
232
 
  if (variables.max_join_size == HA_POS_ERROR)
233
 
    options |= OPTION_BIG_SELECTS;
234
 
  else
235
 
    options &= ~OPTION_BIG_SELECTS;
236
 
 
237
 
  open_options=ha_open_options;
238
 
  update_lock_default= TL_WRITE;
239
 
  session_tx_isolation= (enum_tx_isolation) variables.tx_isolation;
240
 
  warn_list.clear();
241
 
  memset(warn_count, 0, sizeof(warn_count));
242
 
  memset(&status_var, 0, sizeof(status_var));
243
 
 
 
403
  where= Session::DEFAULT_WHERE;
 
404
  server_id = ::server_id;
 
405
  command=COM_CONNECT;
 
406
  *scramble= '\0';
 
407
 
 
408
  init();
244
409
  /* Initialize sub structures */
245
 
  memory::init_sql_alloc(&warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE);
246
 
 
 
410
  init_sql_alloc(&warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE);
 
411
  hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0,
 
412
            (hash_get_key) get_var_key,
 
413
            (hash_free_key) free_user_var, 0);
 
414
 
 
415
  /* Protocol */
 
416
  protocol= &protocol_text;                     // Default protocol
 
417
  protocol_text.init(this);
 
418
 
 
419
  const Query_id& local_query_id= Query_id::get_query_id();
 
420
  tablespace_op= false;
 
421
  tmp= sql_rnd();
 
422
  drizzleclient_randominit(&rand, tmp + (uint64_t) &rand,
 
423
                           tmp + (uint64_t)local_query_id.value());
247
424
  substitute_null_with_insert_id = false;
248
 
  lock_info.init(); /* safety: will be reset after start */
 
425
  thr_lock_info_init(&lock_info); /* safety: will be reset after start */
249
426
  thr_lock_owner_init(&main_lock_id, &lock_info);
250
427
 
251
428
  m_internal_handler= NULL;
252
 
  
253
 
  plugin::EventObserver::registerSessionEvents(*this); 
254
429
}
255
430
 
256
 
void Session::free_items()
257
 
{
258
 
  Item *next;
259
 
  /* This works because items are allocated with memory::sql_alloc() */
260
 
  for (; free_list; free_list= next)
261
 
  {
262
 
    next= free_list->next;
263
 
    free_list->delete_self();
264
 
  }
265
 
}
266
431
 
267
432
void Session::push_internal_handler(Internal_error_handler *handler)
268
433
{
274
439
  m_internal_handler= handler;
275
440
}
276
441
 
277
 
bool Session::handle_error(drizzled::error_t sql_errno, const char *message,
278
 
                           DRIZZLE_ERROR::enum_warning_level level)
 
442
 
 
443
bool Session::handle_error(uint32_t sql_errno, const char *message,
 
444
                       DRIZZLE_ERROR::enum_warning_level level)
279
445
{
280
446
  if (m_internal_handler)
281
447
  {
285
451
  return false;                                 // 'false', as per coding style
286
452
}
287
453
 
288
 
void Session::setAbort(bool arg)
289
 
{
290
 
  mysys_var->abort= arg;
291
 
}
292
 
 
293
 
void Session::lockOnSys()
294
 
{
295
 
  if (not mysys_var)
296
 
    return;
297
 
 
298
 
  setAbort(true);
299
 
  boost_unique_lock_t scopedLock(mysys_var->mutex);
300
 
  if (mysys_var->current_cond)
301
 
  {
302
 
    mysys_var->current_mutex->lock();
303
 
    mysys_var->current_cond->notify_all();
304
 
    mysys_var->current_mutex->unlock();
305
 
  }
306
 
}
307
454
 
308
455
void Session::pop_internal_handler()
309
456
{
311
458
  m_internal_handler= NULL;
312
459
}
313
460
 
314
 
void Session::get_xid(DrizzleXid *xid)
315
 
{
316
 
  *xid = *(DrizzleXid *) &transaction.xid_state.xid;
317
 
}
 
461
#if defined(__cplusplus)
 
462
extern "C" {
 
463
#endif
 
464
 
 
465
void *session_alloc(Session *session, unsigned int size)
 
466
{
 
467
  return session->alloc(size);
 
468
}
 
469
 
 
470
void *session_calloc(Session *session, unsigned int size)
 
471
{
 
472
  return session->calloc(size);
 
473
}
 
474
 
 
475
char *session_strdup(Session *session, const char *str)
 
476
{
 
477
  return session->strdup(str);
 
478
}
 
479
 
 
480
char *session_strmake(Session *session, const char *str, unsigned int size)
 
481
{
 
482
  return session->strmake(str, size);
 
483
}
 
484
 
 
485
void *session_memdup(Session *session, const void* str, unsigned int size)
 
486
{
 
487
  return session->memdup(str, size);
 
488
}
 
489
 
 
490
void session_get_xid(const Session *session, DRIZZLE_XID *xid)
 
491
{
 
492
  *xid = *(DRIZZLE_XID *) &session->transaction.xid_state.xid;
 
493
}
 
494
 
 
495
#if defined(__cplusplus)
 
496
}
 
497
#endif
 
498
 
 
499
/*
 
500
  Init common variables that has to be reset on start and on change_user
 
501
*/
 
502
 
 
503
void Session::init(void)
 
504
{
 
505
  pthread_mutex_lock(&LOCK_global_system_variables);
 
506
  plugin_sessionvar_init(this);
 
507
  /*
 
508
    variables= global_system_variables above has reset
 
509
    variables.pseudo_thread_id to 0. We need to correct it here to
 
510
    avoid temporary tables replication failure.
 
511
  */
 
512
  variables.pseudo_thread_id= thread_id;
 
513
  pthread_mutex_unlock(&LOCK_global_system_variables);
 
514
  server_status= SERVER_STATUS_AUTOCOMMIT;
 
515
  options= session_startup_options;
 
516
 
 
517
  if (variables.max_join_size == HA_POS_ERROR)
 
518
    options |= OPTION_BIG_SELECTS;
 
519
  else
 
520
    options &= ~OPTION_BIG_SELECTS;
 
521
 
 
522
  transaction.all.modified_non_trans_table= transaction.stmt.modified_non_trans_table= false;
 
523
  open_options=ha_open_options;
 
524
  update_lock_default= TL_WRITE;
 
525
  session_tx_isolation= (enum_tx_isolation) variables.tx_isolation;
 
526
  warn_list.empty();
 
527
  memset(warn_count, 0, sizeof(warn_count));
 
528
  total_warn_count= 0;
 
529
  update_charset();
 
530
  memset(&status_var, 0, sizeof(status_var));
 
531
}
 
532
 
 
533
 
 
534
/*
 
535
  Init Session for query processing.
 
536
  This has to be called once before we call mysql_parse.
 
537
  See also comments in session.h.
 
538
*/
 
539
 
 
540
void Session::init_for_queries()
 
541
{
 
542
  set_time();
 
543
  ha_enable_transaction(this,true);
 
544
 
 
545
  reset_root_defaults(mem_root, variables.query_alloc_block_size,
 
546
                      variables.query_prealloc_size);
 
547
  reset_root_defaults(&transaction.mem_root,
 
548
                      variables.trans_alloc_block_size,
 
549
                      variables.trans_prealloc_size);
 
550
  transaction.xid_state.xid.null();
 
551
  transaction.xid_state.in_session=1;
 
552
}
 
553
 
318
554
 
319
555
/* Do operations that may take a long time */
320
556
 
321
557
void Session::cleanup(void)
322
558
{
323
 
  assert(cleanup_done == false);
 
559
  assert(cleanup_done == 0);
324
560
 
325
 
  setKilled(KILL_CONNECTION);
 
561
  killed= KILL_CONNECTION;
326
562
#ifdef ENABLE_WHEN_BINLOG_WILL_BE_ABLE_TO_PREPARE
327
563
  if (transaction.xid_state.xa_state == XA_PREPARED)
328
564
  {
330
566
  }
331
567
#endif
332
568
  {
333
 
    TransactionServices &transaction_services= TransactionServices::singleton();
334
 
    transaction_services.rollbackTransaction(*this, true);
 
569
    ha_rollback(this);
335
570
    xid_cache_delete(&transaction.xid_state);
336
571
  }
337
 
 
338
 
  for (UserVars::iterator iter= user_vars.begin();
339
 
       iter != user_vars.end();
340
 
       iter++)
 
572
  if (locked_tables)
341
573
  {
342
 
    user_var_entry *entry= (*iter).second;
343
 
    boost::checked_delete(entry);
 
574
    lock=locked_tables; locked_tables=0;
 
575
    close_thread_tables(this);
344
576
  }
345
 
  user_vars.clear();
346
 
 
347
 
 
 
577
  hash_free(&user_vars);
348
578
  close_temporary_tables();
349
579
 
350
580
  if (global_read_lock)
351
 
  {
352
 
    unlockGlobalReadLock();
353
 
  }
 
581
    unlock_global_read_lock(this);
354
582
 
355
 
  cleanup_done= true;
 
583
  cleanup_done=1;
 
584
  return;
356
585
}
357
586
 
358
587
Session::~Session()
359
588
{
360
 
  this->checkSentry();
 
589
  Session_CHECK_SENTRY(this);
 
590
  add_to_status(&global_status_var, &status_var);
361
591
 
362
 
  if (client and client->isConnected())
 
592
  if (drizzleclient_vio_ok())
363
593
  {
364
 
    assert(security_ctx);
365
594
    if (global_system_variables.log_warnings)
366
 
    {
367
 
      errmsg_printf(error::WARN, ER(ER_FORCING_CLOSE),
368
 
                    internal::my_progname,
369
 
                    thread_id,
370
 
                    security_ctx->username().c_str());
371
 
    }
372
 
 
373
 
    disconnect();
 
595
        errmsg_printf(ERRMSG_LVL_WARN, ER(ER_FORCING_CLOSE),my_progname,
 
596
                      thread_id,
 
597
                      (security_ctx.user.c_str() ?
 
598
                       security_ctx.user.c_str() : ""));
 
599
    disconnect(0, false);
374
600
  }
375
601
 
376
602
  /* Close connection */
377
 
  if (client)
 
603
  if (net.vio)
378
604
  {
379
 
    client->close();
380
 
    boost::checked_delete(client);
381
 
    client= NULL;
 
605
    drizzleclient_net_close(&net);
 
606
    drizzleclient_net_end(&net);
382
607
  }
383
 
 
384
 
  if (cleanup_done == false)
 
608
  if (!cleanup_done)
385
609
    cleanup();
386
610
 
387
 
  plugin::StorageEngine::closeConnection(this);
 
611
  ha_close_connection(this);
388
612
  plugin_sessionvar_cleanup(this);
389
613
 
390
 
  warn_root.free_root(MYF(0));
 
614
  if (db)
 
615
  {
 
616
    free(db);
 
617
    db= NULL;
 
618
  }
 
619
  free_root(&warn_root,MYF(0));
 
620
  free_root(&transaction.mem_root,MYF(0));
391
621
  mysys_var=0;                                  // Safety (shouldn't be needed)
392
622
  dbug_sentry= Session_SENTRY_GONE;
393
623
 
394
 
  main_mem_root.free_root(MYF(0));
395
 
  currentMemRoot().release();
396
 
  currentSession().release();
397
 
 
398
 
  plugin::Logging::postEndDo(this);
399
 
  plugin::EventObserver::deregisterSessionEvents(*this); 
400
 
}
401
 
 
402
 
void Session::setClient(plugin::Client *client_arg)
403
 
{
404
 
  client= client_arg;
405
 
  client->setSession(this);
406
 
}
407
 
 
408
 
void Session::awake(Session::killed_state_t state_to_set)
409
 
{
410
 
  if ((state_to_set == Session::KILL_QUERY) and (command == COM_SLEEP))
411
 
    return;
412
 
 
413
 
  this->checkSentry();
414
 
 
415
 
  setKilled(state_to_set);
416
 
  scheduler->killSession(this);
417
 
 
 
624
  free_root(&main_mem_root, MYF(0));
 
625
  pthread_setspecific(THR_Session,  0);
 
626
 
 
627
  /* Ensure that no one is using Session */
 
628
  pthread_mutex_unlock(&LOCK_delete);
 
629
  pthread_mutex_destroy(&LOCK_delete);
 
630
}
 
631
 
 
632
 
 
633
/*
 
634
  Add all status variables to another status variable array
 
635
 
 
636
  SYNOPSIS
 
637
   add_to_status()
 
638
   to_var       add to this array
 
639
   from_var     from this array
 
640
 
 
641
  NOTES
 
642
    This function assumes that all variables are long/ulong.
 
643
    If this assumption will change, then we have to explictely add
 
644
    the other variables after the while loop
 
645
*/
 
646
 
 
647
void add_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var)
 
648
{
 
649
  ulong *end= (ulong*) ((unsigned char*) to_var +
 
650
                        offsetof(STATUS_VAR, last_system_status_var) +
 
651
                        sizeof(ulong));
 
652
  ulong *to= (ulong*) to_var, *from= (ulong*) from_var;
 
653
 
 
654
  while (to != end)
 
655
    *(to++)+= *(from++);
 
656
}
 
657
 
 
658
/*
 
659
  Add the difference between two status variable arrays to another one.
 
660
 
 
661
  SYNOPSIS
 
662
    add_diff_to_status
 
663
    to_var       add to this array
 
664
    from_var     from this array
 
665
    dec_var      minus this array
 
666
 
 
667
  NOTE
 
668
    This function assumes that all variables are long/ulong.
 
669
*/
 
670
 
 
671
void add_diff_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var,
 
672
                        STATUS_VAR *dec_var)
 
673
{
 
674
  ulong *end= (ulong*) ((unsigned char*) to_var + offsetof(STATUS_VAR,
 
675
                                                  last_system_status_var) +
 
676
                        sizeof(ulong));
 
677
  ulong *to= (ulong*) to_var, *from= (ulong*) from_var, *dec= (ulong*) dec_var;
 
678
 
 
679
  while (to != end)
 
680
    *(to++)+= *(from++) - *(dec++);
 
681
}
 
682
 
 
683
 
 
684
void Session::awake(Session::killed_state state_to_set)
 
685
{
 
686
  Session_CHECK_SENTRY(this);
 
687
  safe_mutex_assert_owner(&LOCK_delete);
 
688
 
 
689
  killed= state_to_set;
418
690
  if (state_to_set != Session::KILL_QUERY)
419
691
  {
420
 
    DRIZZLE_CONNECTION_DONE(thread_id);
 
692
    thread_scheduler.post_kill_notification(this);
421
693
  }
422
 
 
423
694
  if (mysys_var)
424
695
  {
425
 
    boost_unique_lock_t scopedLock(mysys_var->mutex);
 
696
    pthread_mutex_lock(&mysys_var->mutex);
 
697
    if (!system_thread)         // Don't abort locks
 
698
      mysys_var->abort=1;
426
699
    /*
427
 
      "
428
700
      This broadcast could be up in the air if the victim thread
429
701
      exits the cond in the time between read and broadcast, but that is
430
702
      ok since all we want to do is to make the victim thread get out
445
717
    */
446
718
    if (mysys_var->current_cond && mysys_var->current_mutex)
447
719
    {
448
 
      mysys_var->current_mutex->lock();
449
 
      mysys_var->current_cond->notify_all();
450
 
      mysys_var->current_mutex->unlock();
 
720
      pthread_mutex_lock(mysys_var->current_mutex);
 
721
      pthread_cond_broadcast(mysys_var->current_cond);
 
722
      pthread_mutex_unlock(mysys_var->current_mutex);
451
723
    }
 
724
    pthread_mutex_unlock(&mysys_var->mutex);
452
725
  }
 
726
  return;
453
727
}
454
728
 
455
729
/*
456
730
  Remember the location of thread info, the structure needed for
457
 
  memory::sql_alloc() and the structure for the net buffer
 
731
  sql_alloc() and the structure for the net buffer
458
732
*/
459
 
bool Session::storeGlobals()
 
733
bool Session::store_globals()
460
734
{
461
735
  /*
462
736
    Assert that thread_stack is initialized: it's necessary to be able
464
738
  */
465
739
  assert(thread_stack);
466
740
 
467
 
  currentSession().release();
468
 
  currentSession().reset(this);
469
 
 
470
 
  currentMemRoot().release();
471
 
  currentMemRoot().reset(&mem_root);
472
 
 
 
741
  if (pthread_setspecific(THR_Session,  this) ||
 
742
      pthread_setspecific(THR_Mem_root, &mem_root))
 
743
    return 1;
473
744
  mysys_var=my_thread_var;
474
 
 
475
745
  /*
476
746
    Let mysqld define the thread id (not mysys)
477
747
    This allows us to move Session to different threads if needed.
478
748
  */
479
749
  mysys_var->id= thread_id;
 
750
  real_id= pthread_self();                      // For debugging
480
751
 
481
752
  /*
482
753
    We have to call thr_lock_info_init() again here as Session may have been
483
754
    created in another thread
484
755
  */
485
 
  lock_info.init();
486
 
 
487
 
  return false;
 
756
  thr_lock_info_init(&lock_info);
 
757
  return 0;
488
758
}
489
759
 
490
 
/*
491
 
  Init Session for query processing.
492
 
  This has to be called once before we call mysql_parse.
493
 
  See also comments in session.h.
494
 
*/
495
 
 
496
760
void Session::prepareForQueries()
497
761
{
498
762
  if (variables.max_join_size == HA_POS_ERROR)
499
763
    options |= OPTION_BIG_SELECTS;
 
764
  if (client_capabilities & CLIENT_COMPRESS)
 
765
    net.compress= true;
500
766
 
501
767
  version= refresh_version;
502
 
  set_proc_info(NULL);
 
768
  set_proc_info(0);
503
769
  command= COM_SLEEP;
504
770
  set_time();
 
771
  init_for_queries();
505
772
 
506
 
  mem_root->reset_root_defaults(variables.query_alloc_block_size,
507
 
                                variables.query_prealloc_size);
508
 
  transaction.xid_state.xid.null();
509
 
  transaction.xid_state.in_session=1;
510
 
  if (use_usage)
511
 
    resetUsage();
 
773
  /* In the past this would only run of the user did not have SUPER_ACL */
 
774
  if (sys_init_connect.value_length)
 
775
  {
 
776
    execute_init_command(this, &sys_init_connect, &LOCK_sys_init_connect);
 
777
    if (is_error())
 
778
    {
 
779
      Security_context *sctx= &security_ctx;
 
780
      killed= Session::KILL_CONNECTION;
 
781
      errmsg_printf(ERRMSG_LVL_WARN
 
782
                  , ER(ER_NEW_ABORTING_CONNECTION)
 
783
                  , thread_id
 
784
                  , (db ? db : "unconnected")
 
785
                  , sctx->user.empty() == false ? sctx->user.c_str() : "unauthenticated"
 
786
                  , sctx->ip.c_str(), "init_connect command failed");
 
787
      errmsg_printf(ERRMSG_LVL_WARN, "%s", main_da.message());
 
788
    }
 
789
    set_proc_info(0);
 
790
    set_time();
 
791
    init_for_queries();
 
792
  }
512
793
}
513
794
 
514
795
bool Session::initGlobals()
515
796
{
516
 
  if (storeGlobals())
517
 
  {
518
 
    disconnect(ER_OUT_OF_RESOURCES);
519
 
    status_var.aborted_connects++;
520
 
    return true;
521
 
  }
522
 
  return false;
523
 
}
524
 
 
525
 
void Session::run()
526
 
{
527
 
  if (initGlobals() || authenticate())
528
 
  {
529
 
    disconnect();
530
 
    return;
531
 
  }
532
 
 
533
 
  prepareForQueries();
534
 
 
535
 
  while (not client->haveError() && getKilled() != KILL_CONNECTION)
536
 
  {
537
 
    if (not executeStatement())
538
 
      break;
539
 
  }
540
 
 
541
 
  disconnect();
542
 
}
543
 
 
544
 
bool Session::schedule(Session::shared_ptr &arg)
545
 
{
546
 
  arg->scheduler= plugin::Scheduler::getScheduler();
547
 
  assert(arg->scheduler);
548
 
 
549
 
  ++connection_count;
550
 
 
551
 
  long current_connections= connection_count;
552
 
 
553
 
  if (current_connections > 0 and static_cast<uint64_t>(current_connections) > current_global_counters.max_used_connections)
554
 
  {
555
 
    current_global_counters.max_used_connections= static_cast<uint64_t>(connection_count);
556
 
  }
557
 
 
558
 
  current_global_counters.connections++;
559
 
  arg->thread_id= arg->variables.pseudo_thread_id= global_thread_id++;
560
 
 
561
 
  session::Cache::singleton().insert(arg);
562
 
 
563
 
  if (unlikely(plugin::EventObserver::connectSession(*arg)))
564
 
  {
565
 
    // We should do something about an error...
566
 
  }
567
 
 
568
 
  if (plugin::Scheduler::getScheduler()->addSession(arg))
569
 
  {
570
 
    DRIZZLE_CONNECTION_START(arg->getSessionId());
571
 
    char error_message_buff[DRIZZLE_ERRMSG_SIZE];
572
 
 
573
 
    arg->setKilled(Session::KILL_CONNECTION);
574
 
 
575
 
    arg->status_var.aborted_connects++;
576
 
 
577
 
    /* Can't use my_error() since store_globals has not been called. */
578
 
    /* TODO replace will better error message */
579
 
    snprintf(error_message_buff, sizeof(error_message_buff),
580
 
             ER(ER_CANT_CREATE_THREAD), 1);
581
 
    arg->client->sendError(ER_CANT_CREATE_THREAD, error_message_buff);
582
 
 
583
 
    return true;
584
 
  }
585
 
 
586
 
  return false;
587
 
}
588
 
 
589
 
 
590
 
/*
591
 
  Is this session viewable by the current user?
592
 
*/
593
 
bool Session::isViewable(identifier::User::const_reference user_arg) const
594
 
{
595
 
  return plugin::Authorization::isAuthorized(user_arg, *this, false);
596
 
}
597
 
 
598
 
 
599
 
const char* Session::enter_cond(boost::condition_variable_any &cond, boost::mutex &mutex, const char* msg)
600
 
{
601
 
  const char* old_msg = get_proc_info();
602
 
  safe_mutex_assert_owner(mutex);
603
 
  mysys_var->current_mutex = &mutex;
604
 
  mysys_var->current_cond = &cond;
605
 
  this->set_proc_info(msg);
606
 
  return old_msg;
607
 
}
608
 
 
609
 
void Session::exit_cond(const char* old_msg)
610
 
{
611
 
  /*
612
 
    Putting the mutex unlock in exit_cond() ensures that
613
 
    mysys_var->current_mutex is always unlocked _before_ mysys_var->mutex is
614
 
    locked (if that would not be the case, you'll get a deadlock if someone
615
 
    does a Session::awake() on you).
616
 
  */
617
 
  mysys_var->current_mutex->unlock();
618
 
  boost_unique_lock_t scopedLock(mysys_var->mutex);
619
 
  mysys_var->current_mutex = 0;
620
 
  mysys_var->current_cond = 0;
621
 
  this->set_proc_info(old_msg);
 
797
  if (store_globals())
 
798
  {
 
799
    disconnect(ER_OUT_OF_RESOURCES, true);
 
800
    statistic_increment(aborted_connects, &LOCK_status);
 
801
    thread_scheduler.end_thread(this, 0);
 
802
    return false;
 
803
  }
 
804
  return true;
622
805
}
623
806
 
624
807
bool Session::authenticate()
625
808
{
626
 
  if (client->authenticate())
 
809
  /* Use "connect_timeout" value during connection phase */
 
810
  drizzleclient_net_set_read_timeout(&net, connect_timeout);
 
811
  drizzleclient_net_set_write_timeout(&net, connect_timeout);
 
812
 
 
813
  lex_start(this);
 
814
 
 
815
  bool connection_is_valid= check_connection();
 
816
  drizzleclient_net_end_statement(this);
 
817
 
 
818
  if (! connection_is_valid)
 
819
  {     
 
820
    /* We got wrong permissions from check_connection() */
 
821
    statistic_increment(aborted_connects, &LOCK_status);
627
822
    return false;
628
 
 
629
 
  status_var.aborted_connects++;
630
 
 
 
823
  }
 
824
 
 
825
  /* Connect completed, set read/write timeouts back to default */
 
826
  drizzleclient_net_set_read_timeout(&net, variables.net_read_timeout);
 
827
  drizzleclient_net_set_write_timeout(&net, variables.net_write_timeout);
631
828
  return true;
632
829
}
633
830
 
634
 
bool Session::checkUser(const std::string &passwd_str,
635
 
                        const std::string &in_db)
636
 
{
637
 
  bool is_authenticated=
638
 
    plugin::Authentication::isAuthenticated(*user(), passwd_str);
 
831
bool Session::check_connection()
 
832
{
 
833
  uint32_t pkt_len= 0;
 
834
  char *end;
 
835
 
 
836
  // TCP/IP connection
 
837
  {
 
838
    char ip[NI_MAXHOST];
 
839
 
 
840
    if (drizzleclient_net_peer_addr(&net, ip, &peer_port, NI_MAXHOST))
 
841
    {
 
842
      my_error(ER_BAD_HOST_ERROR, MYF(0), security_ctx.ip.c_str());
 
843
      return false;
 
844
    }
 
845
 
 
846
    security_ctx.ip.assign(ip);
 
847
  }
 
848
  drizzleclient_net_keepalive(&net, true);
 
849
 
 
850
  uint32_t server_capabilites;
 
851
  {
 
852
    /* buff[] needs to big enough to hold the server_version variable */
 
853
    char buff[SERVER_VERSION_LENGTH + SCRAMBLE_LENGTH + 64];
 
854
 
 
855
    server_capabilites= CLIENT_BASIC_FLAGS;
 
856
 
 
857
    if (opt_using_transactions)
 
858
      server_capabilites|= CLIENT_TRANSACTIONS;
 
859
#ifdef HAVE_COMPRESS
 
860
    server_capabilites|= CLIENT_COMPRESS;
 
861
#endif /* HAVE_COMPRESS */
 
862
 
 
863
    end= buff + strlen(server_version);
 
864
    if ((end - buff) >= SERVER_VERSION_LENGTH)
 
865
      end= buff + (SERVER_VERSION_LENGTH - 1);
 
866
    memcpy(buff, server_version, end - buff);
 
867
    *end= 0;
 
868
    end++;
 
869
 
 
870
    int4store((unsigned char*) end, thread_id);
 
871
    end+= 4;
 
872
    /*
 
873
      So as check_connection is the only entry point to authorization
 
874
      procedure, scramble is set here. This gives us new scramble for
 
875
      each handshake.
 
876
    */
 
877
    drizzleclient_create_random_string(scramble, SCRAMBLE_LENGTH, &rand);
 
878
    /*
 
879
      Old clients does not understand long scrambles, but can ignore packet
 
880
      tail: that's why first part of the scramble is placed here, and second
 
881
      part at the end of packet.
 
882
    */
 
883
    end= strncpy(end, scramble, SCRAMBLE_LENGTH_323);
 
884
    end+= SCRAMBLE_LENGTH_323;
 
885
 
 
886
    *end++= 0; /* an empty byte for some reason */
 
887
 
 
888
    int2store(end, server_capabilites);
 
889
    /* write server characteristics: up to 16 bytes allowed */
 
890
    end[2]=(char) default_charset_info->number;
 
891
    int2store(end+3, server_status);
 
892
    memset(end+5, 0, 13);
 
893
    end+= 18;
 
894
    /* write scramble tail */
 
895
    size_t scramble_len= SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323;
 
896
    end= strncpy(end, scramble + SCRAMBLE_LENGTH_323, scramble_len);
 
897
    end+= scramble_len;
 
898
 
 
899
    *end++= 0; /* an empty byte for some reason */
 
900
 
 
901
    /* At this point we write connection message and read reply */
 
902
    if (drizzleclient_net_write_command(&net
 
903
          , (unsigned char) protocol_version
 
904
          , (unsigned char*) ""
 
905
          , 0
 
906
          , (unsigned char*) buff
 
907
          , (size_t) (end-buff)) 
 
908
        ||      (pkt_len= drizzleclient_net_read(&net)) == packet_error 
 
909
        || pkt_len < MIN_HANDSHAKE_SIZE)
 
910
    {
 
911
      my_error(ER_HANDSHAKE_ERROR, MYF(0), security_ctx.ip.c_str());
 
912
      return false;
 
913
    }
 
914
  }
 
915
  if (packet.alloc(variables.net_buffer_length))
 
916
    return false; /* The error is set by alloc(). */
 
917
 
 
918
  client_capabilities= uint2korr(net.read_pos);
 
919
 
 
920
 
 
921
  client_capabilities|= ((uint32_t) uint2korr(net.read_pos + 2)) << 16;
 
922
  max_client_packet_length= uint4korr(net.read_pos + 4);
 
923
  update_charset();
 
924
  end= (char*) net.read_pos + 32;
 
925
 
 
926
  /*
 
927
    Disable those bits which are not supported by the server.
 
928
    This is a precautionary measure, if the client lies. See Bug#27944.
 
929
  */
 
930
  client_capabilities&= server_capabilites;
 
931
 
 
932
  if (end >= (char*) net.read_pos + pkt_len + 2)
 
933
  {
 
934
    my_error(ER_HANDSHAKE_ERROR, MYF(0), security_ctx.ip.c_str());
 
935
    return false;
 
936
  }
 
937
 
 
938
  if (client_capabilities & CLIENT_INTERACTIVE)
 
939
    variables.net_wait_timeout= variables.net_interactive_timeout;
 
940
  if ((client_capabilities & CLIENT_TRANSACTIONS) && opt_using_transactions)
 
941
    net.return_status= &server_status;
 
942
 
 
943
  char *user= end;
 
944
  char *passwd= strchr(user, '\0')+1;
 
945
  uint32_t user_len= passwd - user - 1;
 
946
  char *l_db= passwd;
 
947
  char db_buff[NAME_LEN + 1];           // buffer to store db in utf8
 
948
  char user_buff[USERNAME_LENGTH + 1];  // buffer to store user in utf8
 
949
  uint32_t dummy_errors;
 
950
 
 
951
  /*
 
952
    Old clients send null-terminated string as password; new clients send
 
953
    the size (1 byte) + string (not null-terminated). Hence in case of empty
 
954
    password both send '\0'.
 
955
 
 
956
    This strlen() can't be easily deleted without changing protocol.
 
957
 
 
958
    Cast *passwd to an unsigned char, so that it doesn't extend the sign for
 
959
    *passwd > 127 and become 2**32-127+ after casting to uint.
 
960
  */
 
961
  uint32_t passwd_len= client_capabilities & CLIENT_SECURE_CONNECTION ?
 
962
    (unsigned char)(*passwd++) : strlen(passwd);
 
963
  l_db= client_capabilities & CLIENT_CONNECT_WITH_DB ? l_db + passwd_len + 1 : 0;
 
964
 
 
965
  /* strlen() can't be easily deleted without changing protocol */
 
966
  uint32_t db_len= l_db ? strlen(l_db) : 0;
 
967
 
 
968
  if (passwd + passwd_len + db_len > (char *) net.read_pos + pkt_len)
 
969
  {
 
970
    my_error(ER_HANDSHAKE_ERROR, MYF(0), security_ctx.ip.c_str());
 
971
    return false;
 
972
  }
 
973
 
 
974
  /* Since 4.1 all database names are stored in utf8 */
 
975
  if (l_db)
 
976
  {
 
977
    db_buff[copy_and_convert(db_buff, sizeof(db_buff)-1,
 
978
                             system_charset_info,
 
979
                             l_db, db_len,
 
980
                             charset(), &dummy_errors)]= 0;
 
981
    l_db= db_buff;
 
982
  }
 
983
 
 
984
  user_buff[user_len= copy_and_convert(user_buff, sizeof(user_buff)-1,
 
985
                                       system_charset_info, user, user_len,
 
986
                                       charset(), &dummy_errors)]= '\0';
 
987
  user= user_buff;
 
988
 
 
989
  /* If username starts and ends in "'", chop them off */
 
990
  if (user_len > 1 && user[0] == '\'' && user[user_len - 1] == '\'')
 
991
  {
 
992
    user[user_len-1]= 0;
 
993
    user++;
 
994
    user_len-= 2;
 
995
  }
 
996
 
 
997
  security_ctx.user.assign(user);
 
998
 
 
999
  return check_user(passwd, passwd_len, l_db);
 
1000
}
 
1001
 
 
1002
bool Session::check_user(const char *passwd, uint32_t passwd_len, const char *in_db)
 
1003
{
 
1004
  LEX_STRING db_str= { (char *) in_db, in_db ? strlen(in_db) : 0 };
 
1005
  bool is_authenticated;
 
1006
 
 
1007
  /*
 
1008
    Clear session->db as it points to something, that will be freed when
 
1009
    connection is closed. We don't want to accidentally free a wrong
 
1010
    pointer if connect failed. Also in case of 'CHANGE USER' failure,
 
1011
    current database will be switched to 'no database selected'.
 
1012
  */
 
1013
  reset_db(NULL, 0);
 
1014
 
 
1015
  if (passwd_len != 0 && passwd_len != SCRAMBLE_LENGTH)
 
1016
  {
 
1017
    my_error(ER_HANDSHAKE_ERROR, MYF(0), security_ctx.ip.c_str());
 
1018
    return false;
 
1019
  }
 
1020
 
 
1021
  is_authenticated= authenticate_user(this, passwd);
639
1022
 
640
1023
  if (is_authenticated != true)
641
1024
  {
642
 
    status_var.access_denied++;
643
 
    /* isAuthenticated has pushed the error message */
 
1025
    my_error(ER_ACCESS_DENIED_ERROR, MYF(0),
 
1026
             security_ctx.user.c_str(),
 
1027
             security_ctx.ip.c_str(),
 
1028
             passwd_len ? ER(ER_YES) : ER(ER_NO));
 
1029
 
644
1030
    return false;
645
1031
  }
646
1032
 
 
1033
  security_ctx.skip_grants();
 
1034
 
647
1035
  /* Change database if necessary */
648
 
  if (not in_db.empty())
 
1036
  if (in_db && in_db[0])
649
1037
  {
650
 
    identifier::Schema identifier(in_db);
651
 
    if (schema::change(*this, identifier))
 
1038
    if (mysql_change_db(this, &db_str, false))
652
1039
    {
653
 
      /* change_db() has pushed the error message. */
 
1040
      /* mysql_change_db() has pushed the error message. */
654
1041
      return false;
655
1042
    }
656
1043
  }
657
1044
  my_ok();
658
 
  password= not passwd_str.empty();
 
1045
  password= test(passwd_len);          // remember for error messages
659
1046
 
660
1047
  /* Ready to handle queries */
661
1048
  return true;
663
1050
 
664
1051
bool Session::executeStatement()
665
1052
{
 
1053
  bool return_value;
666
1054
  char *l_packet= 0;
667
1055
  uint32_t packet_length;
668
1056
 
673
1061
    (see my_message_sql)
674
1062
  */
675
1063
  lex->current_select= 0;
676
 
  clear_error();
 
1064
 
 
1065
  /*
 
1066
    This thread will do a blocking read from the client which
 
1067
    will be interrupted when the next command is received from
 
1068
    the client, the connection is closed or "net_wait_timeout"
 
1069
    number of seconds has passed
 
1070
  */
 
1071
  drizzleclient_net_set_read_timeout(&net, variables.net_wait_timeout);
 
1072
 
 
1073
  /*
 
1074
    XXX: this code is here only to clear possible errors of init_connect.
 
1075
    Consider moving to init_connect() instead.
 
1076
  */
 
1077
  clear_error();                                // Clear error message
677
1078
  main_da.reset_diagnostics_area();
678
1079
 
679
 
  if (client->readCommand(&l_packet, &packet_length) == false)
680
 
  {
681
 
    return false;
682
 
  }
683
 
 
684
 
  if (getKilled() == KILL_CONNECTION)
685
 
    return false;
686
 
 
687
 
  if (packet_length == 0)
688
 
    return true;
689
 
 
690
 
  l_command= static_cast<enum_server_command>(l_packet[0]);
 
1080
  net_new_transaction(&net);
 
1081
 
 
1082
  packet_length= drizzleclient_net_read(&net);
 
1083
  if (packet_length == packet_error)
 
1084
  {
 
1085
    /* Check if we can continue without closing the connection */
 
1086
 
 
1087
    if(net.last_errno== CR_NET_PACKET_TOO_LARGE)
 
1088
      my_error(ER_NET_PACKET_TOO_LARGE, MYF(0));
 
1089
    /* Assert is invalid for dirty connection shutdown
 
1090
     *     assert(session->is_error());
 
1091
     */
 
1092
    drizzleclient_net_end_statement(this);
 
1093
 
 
1094
    if (net.error != 3)
 
1095
    {
 
1096
      return_value= false;                       // We have to close it.
 
1097
      goto out;
 
1098
    }
 
1099
 
 
1100
    net.error= 0;
 
1101
    return_value= true;
 
1102
    goto out;
 
1103
  }
 
1104
 
 
1105
  l_packet= (char*) net.read_pos;
 
1106
  /*
 
1107
    'packet_length' contains length of data, as it was stored in packet
 
1108
    header. In case of malformed header, drizzleclient_net_read returns zero.
 
1109
    If packet_length is not zero, drizzleclient_net_read ensures that the returned
 
1110
    number of bytes was actually read from network.
 
1111
    There is also an extra safety measure in drizzleclient_net_read:
 
1112
    it sets packet[packet_length]= 0, but only for non-zero packets.
 
1113
  */
 
1114
  if (packet_length == 0)                       /* safety */
 
1115
  {
 
1116
    /* Initialize with COM_SLEEP packet */
 
1117
    l_packet[0]= (unsigned char) COM_SLEEP;
 
1118
    packet_length= 1;
 
1119
  }
 
1120
  /* Do not rely on drizzleclient_net_read, extra safety against programming errors. */
 
1121
  l_packet[packet_length]= '\0';                  /* safety */
 
1122
 
 
1123
  l_command= (enum enum_server_command) (unsigned char) l_packet[0];
691
1124
 
692
1125
  if (command >= COM_END)
693
1126
    command= COM_END;                           // Wrong command
694
1127
 
 
1128
  /* Restore read timeout value */
 
1129
  drizzleclient_net_set_read_timeout(&net, variables.net_read_timeout);
 
1130
 
695
1131
  assert(packet_length);
696
 
  return not dispatch_command(l_command, this, l_packet+1, (uint32_t) (packet_length-1));
 
1132
  return_value= ! dispatch_command(l_command, this, l_packet+1, (uint32_t) (packet_length-1));
 
1133
 
 
1134
out:
 
1135
  return return_value;
697
1136
}
698
1137
 
699
1138
bool Session::readAndStoreQuery(const char *in_packet, uint32_t in_packet_length)
705
1144
    in_packet_length--;
706
1145
  }
707
1146
  const char *pos= in_packet + in_packet_length; /* Point at end null */
708
 
  while (in_packet_length > 0 && (pos[-1] == ';' || my_isspace(charset() ,pos[-1])))
 
1147
  while (in_packet_length > 0 &&
 
1148
         (pos[-1] == ';' || my_isspace(charset() ,pos[-1])))
709
1149
  {
710
1150
    pos--;
711
1151
    in_packet_length--;
712
1152
  }
713
1153
 
714
 
  std::string *new_query= new std::string(in_packet, in_packet + in_packet_length);
715
 
  // We can not be entirely sure _schema has a value
716
 
  if (_schema)
717
 
  {
718
 
    plugin::QueryRewriter::rewriteQuery(*_schema, *new_query);
719
 
  }
720
 
  query.reset(new_query);
721
 
  _state.reset(new session::State(in_packet, in_packet_length));
 
1154
  /* We must allocate some extra memory for the cached query string */
 
1155
  query_length= 0; /* Extra safety: Avoid races */
 
1156
  query= (char*) memdup_w_gap((unsigned char*) in_packet, in_packet_length, db_length + 1);
 
1157
  if (! query)
 
1158
    return false;
 
1159
 
 
1160
  query[in_packet_length]=0;
 
1161
  query_length= in_packet_length;
 
1162
 
 
1163
  /* Reclaim some memory */
 
1164
  packet.shrink(variables.net_buffer_length);
 
1165
  convert_buffer.shrink(variables.net_buffer_length);
722
1166
 
723
1167
  return true;
724
1168
}
727
1171
{
728
1172
  bool do_release= 0;
729
1173
  bool result= true;
730
 
  TransactionServices &transaction_services= TransactionServices::singleton();
731
1174
 
732
1175
  if (transaction.xid_state.xa_state != XA_NOTR)
733
1176
  {
734
1177
    my_error(ER_XAER_RMFAIL, MYF(0), xa_state_names[transaction.xid_state.xa_state]);
735
1178
    return false;
736
1179
  }
737
 
  switch (completion)
 
1180
  switch (completion) 
738
1181
  {
739
1182
    case COMMIT:
740
1183
      /*
743
1186
       * (Which of course should never happen...)
744
1187
       */
745
1188
      server_status&= ~SERVER_STATUS_IN_TRANS;
746
 
      if (transaction_services.commitTransaction(*this, true))
 
1189
      if (ha_commit(this))
747
1190
        result= false;
748
 
      options&= ~(OPTION_BEGIN);
 
1191
      options&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
 
1192
      transaction.all.modified_non_trans_table= false;
749
1193
      break;
750
1194
    case COMMIT_RELEASE:
751
1195
      do_release= 1; /* fall through */
760
1204
    case ROLLBACK_AND_CHAIN:
761
1205
    {
762
1206
      server_status&= ~SERVER_STATUS_IN_TRANS;
763
 
      if (transaction_services.rollbackTransaction(*this, true))
 
1207
      if (ha_rollback(this))
764
1208
        result= false;
765
 
      options&= ~(OPTION_BEGIN);
 
1209
      options&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
 
1210
      transaction.all.modified_non_trans_table= false;
766
1211
      if (result == true && (completion == ROLLBACK_AND_CHAIN))
767
1212
        result= startTransaction();
768
1213
      break;
773
1218
  }
774
1219
 
775
1220
  if (result == false)
776
 
  {
777
 
    my_error(static_cast<drizzled::error_t>(killed_errno()), MYF(0));
778
 
  }
 
1221
    my_error(killed_errno(), MYF(0));
779
1222
  else if ((result == true) && do_release)
780
 
  {
781
 
    setKilled(Session::KILL_CONNECTION);
782
 
  }
 
1223
    killed= Session::KILL_CONNECTION;
783
1224
 
784
1225
  return result;
785
1226
}
787
1228
bool Session::endActiveTransaction()
788
1229
{
789
1230
  bool result= true;
790
 
  TransactionServices &transaction_services= TransactionServices::singleton();
791
1231
 
792
1232
  if (transaction.xid_state.xa_state != XA_NOTR)
793
1233
  {
794
1234
    my_error(ER_XAER_RMFAIL, MYF(0), xa_state_names[transaction.xid_state.xa_state]);
795
1235
    return false;
796
1236
  }
797
 
  if (options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
 
1237
  if (options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN | OPTION_TABLE_LOCK))
798
1238
  {
 
1239
    /* Safety if one did "drop table" on locked tables */
 
1240
    if (! locked_tables)
 
1241
      options&= ~OPTION_TABLE_LOCK;
799
1242
    server_status&= ~SERVER_STATUS_IN_TRANS;
800
 
    if (transaction_services.commitTransaction(*this, true))
 
1243
    if (ha_commit(this))
801
1244
      result= false;
802
1245
  }
803
 
  options&= ~(OPTION_BEGIN);
 
1246
  options&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
 
1247
  transaction.all.modified_non_trans_table= false;
804
1248
  return result;
805
1249
}
806
1250
 
807
 
bool Session::startTransaction(start_transaction_option_t opt)
 
1251
bool Session::startTransaction()
808
1252
{
809
1253
  bool result= true;
810
1254
 
811
 
  assert(! inTransaction());
812
 
 
813
 
  options|= OPTION_BEGIN;
814
 
  server_status|= SERVER_STATUS_IN_TRANS;
815
 
 
816
 
  if (plugin::TransactionalStorageEngine::notifyStartTransaction(this, opt))
 
1255
  if (locked_tables)
817
1256
  {
 
1257
    lock= locked_tables;
 
1258
    locked_tables= 0;                   // Will be automatically closed
 
1259
    close_thread_tables(this);                  // Free tables
 
1260
  }
 
1261
  if (! endActiveTransaction())
818
1262
    result= false;
 
1263
  else
 
1264
  {
 
1265
    options|= OPTION_BEGIN;
 
1266
    server_status|= SERVER_STATUS_IN_TRANS;
 
1267
    if (lex->start_transaction_opt & DRIZZLE_START_TRANS_OPT_WITH_CONS_SNAPSHOT)
 
1268
      if (ha_start_consistent_snapshot(this))
 
1269
        result= false;
819
1270
  }
820
 
 
821
1271
  return result;
822
1272
}
823
1273
 
 
1274
/*
 
1275
  Cleanup after query.
 
1276
 
 
1277
  SYNOPSIS
 
1278
    Session::cleanup_after_query()
 
1279
 
 
1280
  DESCRIPTION
 
1281
    This function is used to reset thread data to its default state.
 
1282
 
 
1283
  NOTE
 
1284
    This function is not suitable for setting thread data to some
 
1285
    non-default values, as there is only one replication thread, so
 
1286
    different master threads may overwrite data of each other on
 
1287
    slave.
 
1288
*/
824
1289
void Session::cleanup_after_query()
825
1290
{
826
1291
  /*
834
1299
  if (first_successful_insert_id_in_cur_stmt > 0)
835
1300
  {
836
1301
    /* set what LAST_INSERT_ID() will return */
837
 
    first_successful_insert_id_in_prev_stmt= first_successful_insert_id_in_cur_stmt;
 
1302
    first_successful_insert_id_in_prev_stmt=
 
1303
      first_successful_insert_id_in_cur_stmt;
838
1304
    first_successful_insert_id_in_cur_stmt= 0;
839
1305
    substitute_null_with_insert_id= true;
840
1306
  }
841
 
 
842
 
  arg_of_last_insert_id_function= false;
843
 
 
 
1307
  arg_of_last_insert_id_function= 0;
844
1308
  /* Free Items that were created during this execution */
845
1309
  free_items();
846
 
 
847
 
  /* Reset _where. */
848
 
  _where= Session::DEFAULT_WHERE;
849
 
 
850
 
  /* Reset the temporary shares we built */
851
 
  for_each(temporary_shares.begin(),
852
 
           temporary_shares.end(),
853
 
           DeletePtr());
854
 
  temporary_shares.clear();
 
1310
  /* Reset where. */
 
1311
  where= Session::DEFAULT_WHERE;
855
1312
}
856
1313
 
 
1314
 
857
1315
/**
858
1316
  Create a LEX_STRING in this connection.
859
1317
 
865
1323
  @return  NULL on failure, or pointer to the LEX_STRING object
866
1324
*/
867
1325
LEX_STRING *Session::make_lex_string(LEX_STRING *lex_str,
868
 
                                     const std::string &str,
869
 
                                     bool allocate_lex_string)
870
 
{
871
 
  return make_lex_string(lex_str, str.c_str(), str.length(), allocate_lex_string);
872
 
}
873
 
 
874
 
LEX_STRING *Session::make_lex_string(LEX_STRING *lex_str,
875
 
                                     const char* str, uint32_t length,
876
 
                                     bool allocate_lex_string)
 
1326
                                 const char* str, uint32_t length,
 
1327
                                 bool allocate_lex_string)
877
1328
{
878
1329
  if (allocate_lex_string)
879
 
    if (!(lex_str= (LEX_STRING *)getMemRoot()->allocate(sizeof(LEX_STRING))))
 
1330
    if (!(lex_str= (LEX_STRING *)alloc(sizeof(LEX_STRING))))
880
1331
      return 0;
881
 
  if (!(lex_str->str= mem_root->strmake_root(str, length)))
 
1332
  if (!(lex_str->str= strmake_root(mem_root, str, length)))
882
1333
    return 0;
883
1334
  lex_str->length= length;
884
1335
  return lex_str;
885
1336
}
886
1337
 
 
1338
 
 
1339
/*
 
1340
  Convert a string to another character set
 
1341
 
 
1342
  SYNOPSIS
 
1343
    convert_string()
 
1344
    to                          Store new allocated string here
 
1345
    to_cs                       New character set for allocated string
 
1346
    from                        String to convert
 
1347
    from_length                 Length of string to convert
 
1348
    from_cs                     Original character set
 
1349
 
 
1350
  NOTES
 
1351
    to will be 0-terminated to make it easy to pass to system funcs
 
1352
 
 
1353
  RETURN
 
1354
    0   ok
 
1355
    1   End of memory.
 
1356
        In this case to->str will point to 0 and to->length will be 0.
 
1357
*/
 
1358
 
 
1359
bool Session::convert_string(LEX_STRING *to, const CHARSET_INFO * const to_cs,
 
1360
                         const char *from, uint32_t from_length,
 
1361
                         const CHARSET_INFO * const from_cs)
 
1362
{
 
1363
  size_t new_length= to_cs->mbmaxlen * from_length;
 
1364
  uint32_t dummy_errors;
 
1365
  if (!(to->str= (char*) alloc(new_length+1)))
 
1366
  {
 
1367
    to->length= 0;                              // Safety fix
 
1368
    return(1);                          // EOM
 
1369
  }
 
1370
  to->length= copy_and_convert((char*) to->str, new_length, to_cs,
 
1371
                               from, from_length, from_cs, &dummy_errors);
 
1372
  to->str[to->length]=0;                        // Safety
 
1373
  return(0);
 
1374
}
 
1375
 
 
1376
 
 
1377
/*
 
1378
  Convert string from source character set to target character set inplace.
 
1379
 
 
1380
  SYNOPSIS
 
1381
    Session::convert_string
 
1382
 
 
1383
  DESCRIPTION
 
1384
    Convert string using convert_buffer - buffer for character set
 
1385
    conversion shared between all protocols.
 
1386
 
 
1387
  RETURN
 
1388
    0   ok
 
1389
   !0   out of memory
 
1390
*/
 
1391
 
 
1392
bool Session::convert_string(String *s, const CHARSET_INFO * const from_cs,
 
1393
                         const CHARSET_INFO * const to_cs)
 
1394
{
 
1395
  uint32_t dummy_errors;
 
1396
  if (convert_buffer.copy(s->ptr(), s->length(), from_cs, to_cs, &dummy_errors))
 
1397
    return true;
 
1398
  /* If convert_buffer >> s copying is more efficient long term */
 
1399
  if (convert_buffer.alloced_length() >= convert_buffer.length() * 2 ||
 
1400
      !s->is_alloced())
 
1401
  {
 
1402
    return s->copy(convert_buffer);
 
1403
  }
 
1404
  s->swap(convert_buffer);
 
1405
  return false;
 
1406
}
 
1407
 
 
1408
 
 
1409
/*
 
1410
  Update some cache variables when character set changes
 
1411
*/
 
1412
 
 
1413
void Session::update_charset()
 
1414
{
 
1415
  uint32_t not_used;
 
1416
  charset_is_system_charset= !String::needs_conversion(0,charset(),
 
1417
                                                       system_charset_info,
 
1418
                                                       &not_used);
 
1419
  charset_is_collation_connection=
 
1420
    !String::needs_conversion(0,charset(),variables.getCollation(),
 
1421
                              &not_used);
 
1422
  charset_is_character_set_filesystem=
 
1423
    !String::needs_conversion(0, charset(),
 
1424
                              variables.character_set_filesystem, &not_used);
 
1425
}
 
1426
 
 
1427
 
 
1428
/* routings to adding tables to list of changed in transaction tables */
 
1429
 
 
1430
inline static void list_include(CHANGED_TableList** prev,
 
1431
                                CHANGED_TableList* curr,
 
1432
                                CHANGED_TableList* new_table)
 
1433
{
 
1434
  if (new_table)
 
1435
  {
 
1436
    *prev = new_table;
 
1437
    (*prev)->next = curr;
 
1438
  }
 
1439
}
 
1440
 
 
1441
/* add table to list of changed in transaction tables */
 
1442
 
 
1443
void Session::add_changed_table(Table *table)
 
1444
{
 
1445
  assert((options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) &&
 
1446
              table->file->has_transactions());
 
1447
  add_changed_table(table->s->table_cache_key.str,
 
1448
                    (long) table->s->table_cache_key.length);
 
1449
  return;
 
1450
}
 
1451
 
 
1452
 
 
1453
void Session::add_changed_table(const char *key, long key_length)
 
1454
{
 
1455
  CHANGED_TableList **prev_changed = &transaction.changed_tables;
 
1456
  CHANGED_TableList *curr = transaction.changed_tables;
 
1457
 
 
1458
  for (; curr; prev_changed = &(curr->next), curr = curr->next)
 
1459
  {
 
1460
    int cmp =  (long)curr->key_length - (long)key_length;
 
1461
    if (cmp < 0)
 
1462
    {
 
1463
      list_include(prev_changed, curr, changed_table_dup(key, key_length));
 
1464
      return;
 
1465
    }
 
1466
    else if (cmp == 0)
 
1467
    {
 
1468
      cmp = memcmp(curr->key, key, curr->key_length);
 
1469
      if (cmp < 0)
 
1470
      {
 
1471
        list_include(prev_changed, curr, changed_table_dup(key, key_length));
 
1472
        return;
 
1473
      }
 
1474
      else if (cmp == 0)
 
1475
      {
 
1476
        return;
 
1477
      }
 
1478
    }
 
1479
  }
 
1480
  *prev_changed = changed_table_dup(key, key_length);
 
1481
  return;
 
1482
}
 
1483
 
 
1484
 
 
1485
CHANGED_TableList* Session::changed_table_dup(const char *key, long key_length)
 
1486
{
 
1487
  CHANGED_TableList* new_table =
 
1488
    (CHANGED_TableList*) trans_alloc(ALIGN_SIZE(sizeof(CHANGED_TableList))+
 
1489
                                      key_length + 1);
 
1490
  if (!new_table)
 
1491
  {
 
1492
    my_error(EE_OUTOFMEMORY, MYF(ME_BELL),
 
1493
             ALIGN_SIZE(sizeof(TableList)) + key_length + 1);
 
1494
    killed= KILL_CONNECTION;
 
1495
    return 0;
 
1496
  }
 
1497
 
 
1498
  new_table->key= ((char*)new_table)+ ALIGN_SIZE(sizeof(CHANGED_TableList));
 
1499
  new_table->next = 0;
 
1500
  new_table->key_length = key_length;
 
1501
  ::memcpy(new_table->key, key, key_length);
 
1502
  return new_table;
 
1503
}
 
1504
 
 
1505
 
887
1506
int Session::send_explain_fields(select_result *result)
888
1507
{
889
1508
  List<Item> field_list;
919
1538
  }
920
1539
  item->maybe_null= 1;
921
1540
  field_list.push_back(new Item_empty_string("Extra", 255, cs));
922
 
  return (result->send_fields(field_list));
923
 
}
924
 
 
925
 
void select_result::send_error(drizzled::error_t errcode, const char *err)
926
 
{
927
 
  my_message(errcode, err, MYF(0));
928
 
}
 
1541
  return (result->send_fields(field_list,
 
1542
                              Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF));
 
1543
}
 
1544
 
 
1545
 
 
1546
struct Item_change_record: public ilink
 
1547
{
 
1548
  Item **place;
 
1549
  Item *old_value;
 
1550
  /* Placement new was hidden by `new' in ilink (TODO: check): */
 
1551
  static void *operator new(size_t ,
 
1552
                            void *mem)
 
1553
    { return mem; }
 
1554
  static void operator delete(void *,
 
1555
                              size_t )
 
1556
    {}
 
1557
  static void operator delete(void *,
 
1558
                              void *)
 
1559
    { /* never called */ }
 
1560
};
 
1561
 
 
1562
 
 
1563
/*
 
1564
  Register an item tree tree transformation, performed by the query
 
1565
  optimizer. We need a pointer to runtime_memroot because it may be !=
 
1566
  session->mem_root (this may no longer be a true statement)
 
1567
*/
 
1568
 
 
1569
void Session::nocheck_register_item_tree_change(Item **place, Item *old_value,
 
1570
                                            MEM_ROOT *runtime_memroot)
 
1571
{
 
1572
  Item_change_record *change;
 
1573
  /*
 
1574
    Now we use one node per change, which adds some memory overhead,
 
1575
    but still is rather fast as we use alloc_root for allocations.
 
1576
    A list of item tree changes of an average query should be short.
 
1577
  */
 
1578
  void *change_mem= alloc_root(runtime_memroot, sizeof(*change));
 
1579
  if (change_mem == 0)
 
1580
  {
 
1581
    /*
 
1582
      OOM, session->fatal_error() is called by the error handler of the
 
1583
      memroot. Just return.
 
1584
    */
 
1585
    return;
 
1586
  }
 
1587
  change= new (change_mem) Item_change_record;
 
1588
  change->place= place;
 
1589
  change->old_value= old_value;
 
1590
  change_list.append(change);
 
1591
}
 
1592
 
 
1593
 
 
1594
void Session::rollback_item_tree_changes()
 
1595
{
 
1596
  I_List_iterator<Item_change_record> it(change_list);
 
1597
  Item_change_record *change;
 
1598
 
 
1599
  while ((change= it++))
 
1600
    *change->place= change->old_value;
 
1601
  /* We can forget about changes memory: it's allocated in runtime memroot */
 
1602
  change_list.empty();
 
1603
  return;
 
1604
}
 
1605
 
929
1606
 
930
1607
/************************************************************************
931
1608
  Handling writing to file
932
1609
************************************************************************/
933
1610
 
934
 
void select_to_file::send_error(drizzled::error_t errcode,const char *err)
 
1611
void select_to_file::send_error(uint32_t errcode,const char *err)
935
1612
{
936
1613
  my_message(errcode, err, MYF(0));
937
1614
  if (file > 0)
938
1615
  {
939
 
    (void) cache->end_io_cache();
940
 
    (void) internal::my_close(file, MYF(0));
941
 
    (void) internal::my_delete(path.file_string().c_str(), MYF(0));             // Delete file on error
 
1616
    (void) end_io_cache(&cache);
 
1617
    (void) my_close(file,MYF(0));
 
1618
    (void) my_delete(path,MYF(0));              // Delete file on error
942
1619
    file= -1;
943
1620
  }
944
1621
}
946
1623
 
947
1624
bool select_to_file::send_eof()
948
1625
{
949
 
  int error= test(cache->end_io_cache());
950
 
  if (internal::my_close(file, MYF(MY_WME)))
 
1626
  int error= test(end_io_cache(&cache));
 
1627
  if (my_close(file,MYF(MY_WME)))
951
1628
    error= 1;
952
1629
  if (!error)
953
1630
  {
968
1645
  /* In case of error send_eof() may be not called: close the file here. */
969
1646
  if (file >= 0)
970
1647
  {
971
 
    (void) cache->end_io_cache();
972
 
    (void) internal::my_close(file, MYF(0));
 
1648
    (void) end_io_cache(&cache);
 
1649
    (void) my_close(file,MYF(0));
973
1650
    file= -1;
974
1651
  }
975
 
  path= "";
 
1652
  path[0]= '\0';
976
1653
  row_count= 0;
977
1654
}
978
1655
 
979
 
select_to_file::select_to_file(file_exchange *ex)
980
 
  : exchange(ex),
981
 
    file(-1),
982
 
    cache(static_cast<internal::IO_CACHE *>(memory::sql_calloc(sizeof(internal::IO_CACHE)))),
983
 
    row_count(0L)
984
 
{
985
 
  path= "";
986
 
}
987
1656
 
988
1657
select_to_file::~select_to_file()
989
1658
{
990
 
  cleanup();
 
1659
  if (file >= 0)
 
1660
  {                                     // This only happens in case of error
 
1661
    (void) end_io_cache(&cache);
 
1662
    (void) my_close(file,MYF(0));
 
1663
    file= -1;
 
1664
  }
991
1665
}
992
1666
 
993
1667
/***************************************************************************
1016
1690
*/
1017
1691
 
1018
1692
 
1019
 
static int create_file(Session *session,
1020
 
                       fs::path &target_path,
1021
 
                       file_exchange *exchange,
1022
 
                       internal::IO_CACHE *cache)
 
1693
static File create_file(Session *session, char *path, file_exchange *exchange, IO_CACHE *cache)
1023
1694
{
1024
 
  fs::path to_file(exchange->file_name);
1025
 
  int file;
1026
 
 
1027
 
  if (not to_file.has_root_directory())
 
1695
  File file;
 
1696
  uint32_t option= MY_UNPACK_FILENAME | MY_RELATIVE_PATH;
 
1697
 
 
1698
#ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS
 
1699
  option|= MY_REPLACE_DIR;                      // Force use of db directory
 
1700
#endif
 
1701
 
 
1702
  if (!dirname_length(exchange->file_name))
1028
1703
  {
1029
 
    target_path= fs::system_complete(getDataHomeCatalog());
1030
 
    util::string::const_shared_ptr schema(session->schema());
1031
 
    if (schema and not schema->empty())
1032
 
    {
1033
 
      int count_elements= 0;
1034
 
      for (fs::path::iterator iter= to_file.begin();
1035
 
           iter != to_file.end();
1036
 
           ++iter, ++count_elements)
1037
 
      { }
1038
 
 
1039
 
      if (count_elements == 1)
1040
 
      {
1041
 
        target_path /= *schema;
1042
 
      }
1043
 
    }
1044
 
    target_path /= to_file;
 
1704
    strcpy(path, drizzle_real_data_home);
 
1705
    if (session->db)
 
1706
      strncat(path, session->db, FN_REFLEN-strlen(drizzle_real_data_home)-1);
 
1707
    (void) fn_format(path, exchange->file_name, path, "", option);
1045
1708
  }
1046
1709
  else
1047
 
  {
1048
 
    target_path = exchange->file_name;
1049
 
  }
1050
 
 
1051
 
  if (not secure_file_priv.string().empty())
1052
 
  {
1053
 
    if (target_path.file_string().substr(0, secure_file_priv.file_string().size()) != secure_file_priv.file_string())
1054
 
    {
1055
 
      /* Write only allowed to dir or subdir specified by secure_file_priv */
1056
 
      my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
1057
 
      return -1;
1058
 
    }
1059
 
  }
1060
 
 
1061
 
  if (!access(target_path.file_string().c_str(), F_OK))
 
1710
    (void) fn_format(path, exchange->file_name, drizzle_real_data_home, "", option);
 
1711
 
 
1712
  if (opt_secure_file_priv &&
 
1713
      strncmp(opt_secure_file_priv, path, strlen(opt_secure_file_priv)))
 
1714
  {
 
1715
    /* Write only allowed to dir or subdir specified by secure_file_priv */
 
1716
    my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
 
1717
    return -1;
 
1718
  }
 
1719
 
 
1720
  if (!access(path, F_OK))
1062
1721
  {
1063
1722
    my_error(ER_FILE_EXISTS_ERROR, MYF(0), exchange->file_name);
1064
1723
    return -1;
1065
1724
  }
1066
1725
  /* Create the file world readable */
1067
 
  if ((file= internal::my_create(target_path.file_string().c_str(), 0666, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0)
 
1726
  if ((file= my_create(path, 0666, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0)
1068
1727
    return file;
 
1728
#ifdef HAVE_FCHMOD
1069
1729
  (void) fchmod(file, 0666);                    // Because of umask()
1070
 
  if (cache->init_io_cache(file, 0L, internal::WRITE_CACHE, 0L, 1, MYF(MY_WME)))
 
1730
#else
 
1731
  (void) chmod(path, 0666);
 
1732
#endif
 
1733
  if (init_io_cache(cache, file, 0L, WRITE_CACHE, 0L, 1, MYF(MY_WME)))
1071
1734
  {
1072
 
    internal::my_close(file, MYF(0));
1073
 
    internal::my_delete(target_path.file_string().c_str(), MYF(0));  // Delete file on error, it was just created
 
1735
    my_close(file, MYF(0));
 
1736
    my_delete(path, MYF(0));  // Delete file on error, it was just created
1074
1737
    return -1;
1075
1738
  }
1076
1739
  return file;
1084
1747
  bool string_results= false, non_string_results= false;
1085
1748
  unit= u;
1086
1749
  if ((uint32_t) strlen(exchange->file_name) + NAME_LEN >= FN_REFLEN)
1087
 
  {
1088
 
    path= exchange->file_name;
1089
 
  }
 
1750
    strncpy(path,exchange->file_name,FN_REFLEN-1);
1090
1751
 
1091
1752
  /* Check if there is any blobs in data */
1092
1753
  {
1093
 
    List<Item>::iterator li(list.begin());
 
1754
    List_iterator_fast<Item> li(list);
1094
1755
    Item *item;
1095
1756
    while ((item=li++))
1096
1757
    {
1097
1758
      if (item->max_length >= MAX_BLOB_WIDTH)
1098
1759
      {
1099
 
        blob_flag=1;
1100
 
        break;
 
1760
        blob_flag=1;
 
1761
        break;
1101
1762
      }
1102
 
 
1103
1763
      if (item->result_type() == STRING_RESULT)
1104
1764
        string_results= true;
1105
1765
      else
1134
1794
    return 1;
1135
1795
  }
1136
1796
 
1137
 
  if ((file= create_file(session, path, exchange, cache)) < 0)
 
1797
  if ((file= create_file(session, path, exchange, &cache)) < 0)
1138
1798
    return 1;
1139
1799
 
1140
1800
  return 0;
1141
1801
}
1142
1802
 
 
1803
 
 
1804
#define NEED_ESCAPING(x) ((int) (unsigned char) (x) == escape_char    || \
 
1805
                          (enclosed ? (int) (unsigned char) (x) == field_sep_char      \
 
1806
                                    : (int) (unsigned char) (x) == field_term_char) || \
 
1807
                          (int) (unsigned char) (x) == line_sep_char  || \
 
1808
                          !(x))
 
1809
 
1143
1810
bool select_export::send_data(List<Item> &items)
1144
1811
{
1145
1812
  char buff[MAX_FIELD_WIDTH],null_buff[2],space[MAX_FIELD_WIDTH];
1150
1817
  if (unit->offset_limit_cnt)
1151
1818
  {                                             // using limit offset,count
1152
1819
    unit->offset_limit_cnt--;
1153
 
    return false;
 
1820
    return(0);
1154
1821
  }
1155
1822
  row_count++;
1156
1823
  Item *item;
1157
1824
  uint32_t used_length=0,items_left=items.elements;
1158
 
  List<Item>::iterator li(items.begin());
1159
 
 
1160
 
  if (my_b_write(cache,(unsigned char*) exchange->line_start->ptr(),
1161
 
                 exchange->line_start->length()))
1162
 
    return true;
1163
 
 
 
1825
  List_iterator_fast<Item> li(items);
 
1826
 
 
1827
  if (my_b_write(&cache,(unsigned char*) exchange->line_start->ptr(),
 
1828
                 exchange->line_start->length()))
 
1829
    goto err;
1164
1830
  while ((item=li++))
1165
1831
  {
1166
1832
    Item_result result_type=item->result_type();
1169
1835
    res=item->str_result(&tmp);
1170
1836
    if (res && enclosed)
1171
1837
    {
1172
 
      if (my_b_write(cache,(unsigned char*) exchange->enclosed->ptr(),
1173
 
                     exchange->enclosed->length()))
1174
 
        return true;
 
1838
      if (my_b_write(&cache,(unsigned char*) exchange->enclosed->ptr(),
 
1839
                     exchange->enclosed->length()))
 
1840
        goto err;
1175
1841
    }
1176
1842
    if (!res)
1177
1843
    {                                           // NULL
1178
1844
      if (!fixed_row_size)
1179
1845
      {
1180
 
        if (escape_char != -1)                  // Use \N syntax
1181
 
        {
1182
 
          null_buff[0]=escape_char;
1183
 
          null_buff[1]='N';
1184
 
          if (my_b_write(cache,(unsigned char*) null_buff,2))
1185
 
            return true;
1186
 
        }
1187
 
        else if (my_b_write(cache,(unsigned char*) "NULL",4))
1188
 
          return true;
 
1846
        if (escape_char != -1)                  // Use \N syntax
 
1847
        {
 
1848
          null_buff[0]=escape_char;
 
1849
          null_buff[1]='N';
 
1850
          if (my_b_write(&cache,(unsigned char*) null_buff,2))
 
1851
            goto err;
 
1852
        }
 
1853
        else if (my_b_write(&cache,(unsigned char*) "NULL",4))
 
1854
          goto err;
1189
1855
      }
1190
1856
      else
1191
1857
      {
1192
 
        used_length=0;                          // Fill with space
 
1858
        used_length=0;                          // Fill with space
1193
1859
      }
1194
1860
    }
1195
1861
    else
1196
1862
    {
1197
1863
      if (fixed_row_size)
1198
 
        used_length= min(res->length(), static_cast<size_t>(item->max_length));
 
1864
        used_length=cmin(res->length(),item->max_length);
1199
1865
      else
1200
 
        used_length= res->length();
1201
 
 
 
1866
        used_length=res->length();
1202
1867
      if ((result_type == STRING_RESULT || is_unsafe_field_sep) &&
1203
 
          escape_char != -1)
 
1868
           escape_char != -1)
1204
1869
      {
1205
1870
        char *pos, *start, *end;
1206
1871
        const CHARSET_INFO * const res_charset= res->charset();
1207
1872
        const CHARSET_INFO * const character_set_client= default_charset_info;
1208
1873
 
1209
1874
        bool check_second_byte= (res_charset == &my_charset_bin) &&
1210
 
          character_set_client->
1211
 
          escape_with_backslash_is_dangerous;
 
1875
                                 character_set_client->
 
1876
                                 escape_with_backslash_is_dangerous;
1212
1877
        assert(character_set_client->mbmaxlen == 2 ||
1213
1878
               !character_set_client->escape_with_backslash_is_dangerous);
1214
 
        for (start=pos=(char*) res->ptr(),end=pos+used_length ;
1215
 
             pos != end ;
1216
 
             pos++)
1217
 
        {
1218
 
          if (use_mb(res_charset))
1219
 
          {
1220
 
            int l;
1221
 
            if ((l=my_ismbchar(res_charset, pos, end)))
1222
 
            {
1223
 
              pos += l-1;
1224
 
              continue;
1225
 
            }
1226
 
          }
 
1879
        for (start=pos=(char*) res->ptr(),end=pos+used_length ;
 
1880
             pos != end ;
 
1881
             pos++)
 
1882
        {
 
1883
#ifdef USE_MB
 
1884
          if (use_mb(res_charset))
 
1885
          {
 
1886
            int l;
 
1887
            if ((l=my_ismbchar(res_charset, pos, end)))
 
1888
            {
 
1889
              pos += l-1;
 
1890
              continue;
 
1891
            }
 
1892
          }
 
1893
#endif
1227
1894
 
1228
1895
          /*
1229
1896
            Special case when dumping BINARY/VARBINARY/BLOB values
1257
1924
            assert before the loop makes that sure.
1258
1925
          */
1259
1926
 
1260
 
          if ((needs_escaping(*pos, enclosed) ||
 
1927
          if ((NEED_ESCAPING(*pos) ||
1261
1928
               (check_second_byte &&
1262
1929
                my_mbcharlen(character_set_client, (unsigned char) *pos) == 2 &&
1263
1930
                pos + 1 < end &&
1264
 
                needs_escaping(pos[1], enclosed))) &&
 
1931
                NEED_ESCAPING(pos[1]))) &&
1265
1932
              /*
1266
 
                Don't escape field_term_char by doubling - doubling is only
1267
 
                valid for ENCLOSED BY characters:
 
1933
               Don't escape field_term_char by doubling - doubling is only
 
1934
               valid for ENCLOSED BY characters:
1268
1935
              */
1269
1936
              (enclosed || !is_ambiguous_field_term ||
1270
1937
               (int) (unsigned char) *pos != field_term_char))
1271
1938
          {
1272
 
            char tmp_buff[2];
 
1939
            char tmp_buff[2];
1273
1940
            tmp_buff[0]= ((int) (unsigned char) *pos == field_sep_char &&
1274
1941
                          is_ambiguous_field_sep) ?
1275
 
              field_sep_char : escape_char;
1276
 
            tmp_buff[1]= *pos ? *pos : '0';
1277
 
            if (my_b_write(cache,(unsigned char*) start,(uint32_t) (pos-start)) ||
1278
 
                my_b_write(cache,(unsigned char*) tmp_buff,2))
1279
 
              return true;
1280
 
            start=pos+1;
1281
 
          }
1282
 
        }
1283
 
        if (my_b_write(cache,(unsigned char*) start,(uint32_t) (pos-start)))
1284
 
          return true;
 
1942
                          field_sep_char : escape_char;
 
1943
            tmp_buff[1]= *pos ? *pos : '0';
 
1944
            if (my_b_write(&cache,(unsigned char*) start,(uint32_t) (pos-start)) ||
 
1945
                my_b_write(&cache,(unsigned char*) tmp_buff,2))
 
1946
              goto err;
 
1947
            start=pos+1;
 
1948
          }
 
1949
        }
 
1950
        if (my_b_write(&cache,(unsigned char*) start,(uint32_t) (pos-start)))
 
1951
          goto err;
1285
1952
      }
1286
 
      else if (my_b_write(cache,(unsigned char*) res->ptr(),used_length))
1287
 
        return true;
 
1953
      else if (my_b_write(&cache,(unsigned char*) res->ptr(),used_length))
 
1954
        goto err;
1288
1955
    }
1289
1956
    if (fixed_row_size)
1290
1957
    {                                           // Fill with space
1291
1958
      if (item->max_length > used_length)
1292
1959
      {
1293
 
        /* QQ:  Fix by adding a my_b_fill() function */
1294
 
        if (!space_inited)
1295
 
        {
1296
 
          space_inited=1;
1297
 
          memset(space, ' ', sizeof(space));
1298
 
        }
1299
 
        uint32_t length=item->max_length-used_length;
1300
 
        for (; length > sizeof(space) ; length-=sizeof(space))
1301
 
        {
1302
 
          if (my_b_write(cache,(unsigned char*) space,sizeof(space)))
1303
 
            return true;
1304
 
        }
1305
 
        if (my_b_write(cache,(unsigned char*) space,length))
1306
 
          return true;
 
1960
        /* QQ:  Fix by adding a my_b_fill() function */
 
1961
        if (!space_inited)
 
1962
        {
 
1963
          space_inited=1;
 
1964
          memset(space, ' ', sizeof(space));
 
1965
        }
 
1966
        uint32_t length=item->max_length-used_length;
 
1967
        for (; length > sizeof(space) ; length-=sizeof(space))
 
1968
        {
 
1969
          if (my_b_write(&cache,(unsigned char*) space,sizeof(space)))
 
1970
            goto err;
 
1971
        }
 
1972
        if (my_b_write(&cache,(unsigned char*) space,length))
 
1973
          goto err;
1307
1974
      }
1308
1975
    }
1309
1976
    if (res && enclosed)
1310
1977
    {
1311
 
      if (my_b_write(cache, (unsigned char*) exchange->enclosed->ptr(),
 
1978
      if (my_b_write(&cache, (unsigned char*) exchange->enclosed->ptr(),
1312
1979
                     exchange->enclosed->length()))
1313
 
        return true;
 
1980
        goto err;
1314
1981
    }
1315
1982
    if (--items_left)
1316
1983
    {
1317
 
      if (my_b_write(cache, (unsigned char*) exchange->field_term->ptr(),
 
1984
      if (my_b_write(&cache, (unsigned char*) exchange->field_term->ptr(),
1318
1985
                     field_term_length))
1319
 
        return true;
 
1986
        goto err;
1320
1987
    }
1321
1988
  }
1322
 
  if (my_b_write(cache,(unsigned char*) exchange->line_term->ptr(),
1323
 
                 exchange->line_term->length()))
1324
 
  {
1325
 
    return true;
1326
 
  }
1327
 
 
1328
 
  return false;
 
1989
  if (my_b_write(&cache,(unsigned char*) exchange->line_term->ptr(),
 
1990
                 exchange->line_term->length()))
 
1991
    goto err;
 
1992
  return(0);
 
1993
err:
 
1994
  return(1);
1329
1995
}
1330
1996
 
1331
1997
 
1338
2004
select_dump::prepare(List<Item> &, Select_Lex_Unit *u)
1339
2005
{
1340
2006
  unit= u;
1341
 
  return (int) ((file= create_file(session, path, exchange, cache)) < 0);
 
2007
  return (int) ((file= create_file(session, path, exchange, &cache)) < 0);
1342
2008
}
1343
2009
 
1344
2010
 
1345
2011
bool select_dump::send_data(List<Item> &items)
1346
2012
{
1347
 
  List<Item>::iterator li(items.begin());
 
2013
  List_iterator_fast<Item> li(items);
1348
2014
  char buff[MAX_FIELD_WIDTH];
1349
2015
  String tmp(buff,sizeof(buff),&my_charset_bin),*res;
1350
2016
  tmp.length(0);
1358
2024
  if (row_count++ > 1)
1359
2025
  {
1360
2026
    my_message(ER_TOO_MANY_ROWS, ER(ER_TOO_MANY_ROWS), MYF(0));
1361
 
    return 1;
 
2027
    goto err;
1362
2028
  }
1363
2029
  while ((item=li++))
1364
2030
  {
1365
2031
    res=item->str_result(&tmp);
1366
2032
    if (!res)                                   // If NULL
1367
2033
    {
1368
 
      if (my_b_write(cache,(unsigned char*) "",1))
1369
 
        return 1;
 
2034
      if (my_b_write(&cache,(unsigned char*) "",1))
 
2035
        goto err;
1370
2036
    }
1371
 
    else if (my_b_write(cache,(unsigned char*) res->ptr(),res->length()))
 
2037
    else if (my_b_write(&cache,(unsigned char*) res->ptr(),res->length()))
1372
2038
    {
1373
 
      my_error(ER_ERROR_ON_WRITE, MYF(0), path.file_string().c_str(), errno);
1374
 
      return 1;
 
2039
      my_error(ER_ERROR_ON_WRITE, MYF(0), path, my_errno);
 
2040
      goto err;
1375
2041
    }
1376
2042
  }
1377
2043
  return(0);
 
2044
err:
 
2045
  return(1);
1378
2046
}
1379
2047
 
1380
2048
 
1397
2065
    unit->offset_limit_cnt--;
1398
2066
    return(0);
1399
2067
  }
1400
 
  List<Item>::iterator li(items.begin());
 
2068
  List_iterator_fast<Item> li(items);
1401
2069
  Item *val_item;
1402
2070
  for (uint32_t i= 0; (val_item= li++); i++)
1403
2071
    it->store(i, val_item);
1409
2077
void select_max_min_finder_subselect::cleanup()
1410
2078
{
1411
2079
  cache= 0;
 
2080
  return;
1412
2081
}
1413
2082
 
1414
2083
 
1415
2084
bool select_max_min_finder_subselect::send_data(List<Item> &items)
1416
2085
{
1417
2086
  Item_maxmin_subselect *it= (Item_maxmin_subselect *)item;
1418
 
  List<Item>::iterator li(items.begin());
 
2087
  List_iterator_fast<Item> li(items);
1419
2088
  Item *val_item= li++;
1420
2089
  it->register_value();
1421
2090
  if (it->assigned())
1432
2101
      switch (val_item->result_type())
1433
2102
      {
1434
2103
      case REAL_RESULT:
1435
 
        op= &select_max_min_finder_subselect::cmp_real;
1436
 
        break;
 
2104
        op= &select_max_min_finder_subselect::cmp_real;
 
2105
        break;
1437
2106
      case INT_RESULT:
1438
 
        op= &select_max_min_finder_subselect::cmp_int;
1439
 
        break;
 
2107
        op= &select_max_min_finder_subselect::cmp_int;
 
2108
        break;
1440
2109
      case STRING_RESULT:
1441
 
        op= &select_max_min_finder_subselect::cmp_str;
1442
 
        break;
 
2110
        op= &select_max_min_finder_subselect::cmp_str;
 
2111
        break;
1443
2112
      case DECIMAL_RESULT:
1444
2113
        op= &select_max_min_finder_subselect::cmp_decimal;
1445
2114
        break;
1446
2115
      case ROW_RESULT:
1447
2116
        // This case should never be choosen
1448
 
        assert(0);
1449
 
        op= 0;
 
2117
        assert(0);
 
2118
        op= 0;
1450
2119
      }
1451
2120
    }
1452
2121
    cache->store(val_item);
1485
2154
bool select_max_min_finder_subselect::cmp_decimal()
1486
2155
{
1487
2156
  Item *maxmin= ((Item_singlerow_subselect *)item)->element_index(0);
1488
 
  type::Decimal cval, *cvalue= cache->val_decimal(&cval);
1489
 
  type::Decimal mval, *mvalue= maxmin->val_decimal(&mval);
 
2157
  my_decimal cval, *cvalue= cache->val_decimal(&cval);
 
2158
  my_decimal mval, *mvalue= maxmin->val_decimal(&mval);
1490
2159
  if (fmax)
1491
2160
    return (cache->null_value && !maxmin->null_value) ||
1492
2161
      (!cache->null_value && !maxmin->null_value &&
1493
 
       class_decimal_cmp(cvalue, mvalue) > 0) ;
 
2162
       my_decimal_cmp(cvalue, mvalue) > 0) ;
1494
2163
  return (maxmin->null_value && !cache->null_value) ||
1495
2164
    (!cache->null_value && !maxmin->null_value &&
1496
 
     class_decimal_cmp(cvalue,mvalue) < 0);
 
2165
     my_decimal_cmp(cvalue,mvalue) < 0);
1497
2166
}
1498
2167
 
1499
2168
bool select_max_min_finder_subselect::cmp_str()
1528
2197
  return(0);
1529
2198
}
1530
2199
 
 
2200
 
 
2201
/*
 
2202
  Statement functions
 
2203
*/
 
2204
 
 
2205
Statement::Statement(LEX *lex_arg, MEM_ROOT *mem_root_arg, ulong id_arg)
 
2206
  :Query_arena(mem_root_arg),
 
2207
  id(id_arg),
 
2208
  mark_used_columns(MARK_COLUMNS_READ),
 
2209
  lex(lex_arg),
 
2210
  query(0),
 
2211
  query_length(0),
 
2212
  db(NULL),
 
2213
  db_length(0)
 
2214
{
 
2215
}
 
2216
 
 
2217
 
1531
2218
/*
1532
2219
  Don't free mem_root, as mem_root is freed in the end of dispatch_command
1533
2220
  (once for any command).
1535
2222
void Session::end_statement()
1536
2223
{
1537
2224
  /* Cleanup SQL processing state to reuse this statement in next query. */
1538
 
  lex->end();
1539
 
  query_cache_key= ""; // reset the cache key
1540
 
  resetResultsetMessage();
 
2225
  lex_end(lex);
1541
2226
}
1542
2227
 
 
2228
 
1543
2229
bool Session::copy_db_to(char **p_db, size_t *p_db_length)
1544
2230
{
1545
 
  assert(_schema);
1546
 
  if (_schema and _schema->empty())
1547
 
  {
1548
 
    my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
1549
 
    return true;
1550
 
  }
1551
 
  else if (not _schema)
1552
 
  {
1553
 
    my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
1554
 
    return true;
1555
 
  }
1556
 
  assert(_schema);
1557
 
 
1558
 
  *p_db= strmake(_schema->c_str(), _schema->size());
1559
 
  *p_db_length= _schema->size();
1560
 
 
 
2231
  if (db == NULL)
 
2232
  {
 
2233
    my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
 
2234
    return true;
 
2235
  }
 
2236
  *p_db= strmake(db, db_length);
 
2237
  *p_db_length= db_length;
1561
2238
  return false;
1562
2239
}
1563
2240
 
 
2241
 
1564
2242
/****************************************************************************
1565
2243
  Tmp_Table_Param
1566
2244
****************************************************************************/
1572
2250
  quick_group= 1;
1573
2251
  table_charset= 0;
1574
2252
  precomputed_group_by= 0;
 
2253
  bit_fields_as_long= 0;
 
2254
  return;
1575
2255
}
1576
2256
 
1577
2257
void Tmp_Table_Param::cleanup(void)
1579
2259
  /* Fix for Intel compiler */
1580
2260
  if (copy_field)
1581
2261
  {
1582
 
    boost::checked_array_delete(copy_field);
1583
 
    save_copy_field= save_copy_field_end= copy_field= copy_field_end= 0;
1584
 
  }
 
2262
    delete [] copy_field;
 
2263
    save_copy_field= copy_field= 0;
 
2264
  }
 
2265
}
 
2266
 
 
2267
 
 
2268
void session_increment_bytes_sent(ulong length)
 
2269
{
 
2270
  Session *session=current_session;
 
2271
  if (likely(session != 0))
 
2272
  { /* current_session==0 when disconnect() calls net_send_error() */
 
2273
    session->status_var.bytes_sent+= length;
 
2274
  }
 
2275
}
 
2276
 
 
2277
 
 
2278
void session_increment_bytes_received(ulong length)
 
2279
{
 
2280
  current_session->status_var.bytes_received+= length;
 
2281
}
 
2282
 
 
2283
 
 
2284
void session_increment_net_big_packet_count(ulong length)
 
2285
{
 
2286
  current_session->status_var.net_big_packet_count+= length;
1585
2287
}
1586
2288
 
1587
2289
void Session::send_kill_message() const
1588
2290
{
1589
 
  drizzled::error_t err= static_cast<drizzled::error_t>(killed_errno());
1590
 
  if (err != EE_OK)
 
2291
  int err= killed_errno();
 
2292
  if (err)
1591
2293
    my_message(err, ER(err), MYF(0));
1592
2294
}
1593
2295
 
1596
2298
  memset(&status_var, 0, sizeof(status_var));
1597
2299
}
1598
2300
 
1599
 
 
1600
 
void Session::set_db(const std::string &new_db)
 
2301
void Security_context::skip_grants()
 
2302
{
 
2303
  /* privileges for the user are unknown everything is allowed */
 
2304
}
 
2305
 
 
2306
 
 
2307
/****************************************************************************
 
2308
  Handling of open and locked tables states.
 
2309
 
 
2310
  This is used when we want to open/lock (and then close) some tables when
 
2311
  we already have a set of tables open and locked. We use these methods for
 
2312
  access to mysql.proc table to find definitions of stored routines.
 
2313
****************************************************************************/
 
2314
 
 
2315
void Session::reset_n_backup_open_tables_state(Open_tables_state *backup)
 
2316
{
 
2317
  backup->set_open_tables_state(this);
 
2318
  reset_open_tables_state();
 
2319
  state_flags|= Open_tables_state::BACKUPS_AVAIL;
 
2320
  return;
 
2321
}
 
2322
 
 
2323
 
 
2324
void Session::restore_backup_open_tables_state(Open_tables_state *backup)
 
2325
{
 
2326
  /*
 
2327
    Before we will throw away current open tables state we want
 
2328
    to be sure that it was properly cleaned up.
 
2329
  */
 
2330
  assert(open_tables == 0 && temporary_tables == 0 &&
 
2331
              handler_tables == 0 && derived_tables == 0 &&
 
2332
              lock == 0 && locked_tables == 0);
 
2333
  set_open_tables_state(backup);
 
2334
  return;
 
2335
}
 
2336
 
 
2337
 
 
2338
bool Session::set_db(const char *new_db, size_t new_db_len)
1601
2339
{
1602
2340
  /* Do not reallocate memory if current chunk is big enough. */
1603
 
  if (new_db.length())
1604
 
  {
1605
 
    _schema.reset(new std::string(new_db));
1606
 
  }
 
2341
  if (db && new_db && db_length >= new_db_len)
 
2342
    memcpy(db, new_db, new_db_len+1);
1607
2343
  else
1608
2344
  {
1609
 
    _schema.reset(new std::string(""));
 
2345
    if (db)
 
2346
      free(db);
 
2347
    if (new_db)
 
2348
    {
 
2349
      db= (char *)malloc(new_db_len + 1);
 
2350
      if (db != NULL)
 
2351
      {
 
2352
        memcpy(db, new_db, new_db_len);
 
2353
        db[new_db_len]= 0;
 
2354
      }
 
2355
    }
 
2356
    else
 
2357
      db= NULL;
1610
2358
  }
 
2359
  db_length= db ? new_db_len : 0;
 
2360
  return new_db && !db;
 
2361
}
 
2362
 
 
2363
 
 
2364
/**
 
2365
  Check the killed state of a user thread
 
2366
  @param session  user thread
 
2367
  @retval 0 the user thread is active
 
2368
  @retval 1 the user thread has been killed
 
2369
*/
 
2370
extern "C" int session_killed(const Session *session)
 
2371
{
 
2372
  return(session->killed);
 
2373
}
 
2374
 
 
2375
/**
 
2376
  Return the thread id of a user thread
 
2377
  @param session user thread
 
2378
  @return thread id
 
2379
*/
 
2380
extern "C" unsigned long session_get_thread_id(const Session *session)
 
2381
{
 
2382
  return((unsigned long)session->thread_id);
 
2383
}
 
2384
 
 
2385
 
 
2386
extern "C"
 
2387
LEX_STRING *session_make_lex_string(Session *session, LEX_STRING *lex_str,
 
2388
                                const char *str, unsigned int size,
 
2389
                                int allocate_lex_string)
 
2390
{
 
2391
  return session->make_lex_string(lex_str, str, size,
 
2392
                              (bool) allocate_lex_string);
 
2393
}
 
2394
 
 
2395
extern "C" const struct charset_info_st *session_charset(Session *session)
 
2396
{
 
2397
  return(session->charset());
 
2398
}
 
2399
 
 
2400
extern "C" char **session_query(Session *session)
 
2401
{
 
2402
  return(&session->query);
 
2403
}
 
2404
 
 
2405
extern "C" int session_non_transactional_update(const Session *session)
 
2406
{
 
2407
  return(session->transaction.all.modified_non_trans_table);
 
2408
}
 
2409
 
 
2410
extern "C" void session_mark_transaction_to_rollback(Session *session, bool all)
 
2411
{
 
2412
  mark_transaction_to_rollback(session, all);
1611
2413
}
1612
2414
 
1613
2415
 
1617
2419
  @param  session   Thread handle
1618
2420
  @param  all   true <=> rollback main transaction.
1619
2421
*/
1620
 
void Session::markTransactionForRollback(bool all)
 
2422
 
 
2423
void mark_transaction_to_rollback(Session *session, bool all)
1621
2424
{
1622
 
  is_fatal_sub_stmt_error= true;
1623
 
  transaction_rollback_request= all;
 
2425
  if (session)
 
2426
  {
 
2427
    session->is_fatal_sub_stmt_error= true;
 
2428
    session->transaction_rollback_request= all;
 
2429
  }
1624
2430
}
1625
2431
 
1626
 
void Session::disconnect(enum error_t errcode)
 
2432
void Session::disconnect(uint32_t errcode, bool should_lock)
1627
2433
{
1628
2434
  /* Allow any plugins to cleanup their session variables */
1629
2435
  plugin_sessionvar_cleanup(this);
1630
2436
 
1631
2437
  /* If necessary, log any aborted or unauthorized connections */
1632
 
  if (getKilled() || client->wasAborted())
1633
 
  {
1634
 
    status_var.aborted_threads++;
1635
 
  }
 
2438
  if (killed || (net.error && net.vio != 0))
 
2439
    statistic_increment(aborted_threads, &LOCK_status);
1636
2440
 
1637
 
  if (client->wasAborted())
 
2441
  if (net.error && net.vio != 0)
1638
2442
  {
1639
 
    if (not getKilled() && variables.log_warnings > 1)
 
2443
    if (! killed && variables.log_warnings > 1)
1640
2444
    {
1641
 
      errmsg_printf(error::WARN, ER(ER_NEW_ABORTING_CONNECTION)
 
2445
      Security_context *sctx= &security_ctx;
 
2446
 
 
2447
      errmsg_printf(ERRMSG_LVL_WARN, ER(ER_NEW_ABORTING_CONNECTION)
1642
2448
                  , thread_id
1643
 
                  , (_schema->empty() ? "unconnected" : _schema->c_str())
1644
 
                  , security_ctx->username().empty() == false ? security_ctx->username().c_str() : "unauthenticated"
1645
 
                  , security_ctx->address().c_str()
 
2449
                  , (db ? db : "unconnected")
 
2450
                  , sctx->user.empty() == false ? sctx->user.c_str() : "unauthenticated"
 
2451
                  , sctx->ip.c_str()
1646
2452
                  , (main_da.is_error() ? main_da.message() : ER(ER_UNKNOWN_ERROR)));
1647
2453
    }
1648
2454
  }
1649
2455
 
1650
 
  setKilled(Session::KILL_CONNECTION);
1651
 
 
1652
 
  if (client->isConnected())
 
2456
  /* Close out our connection to the client */
 
2457
  st_vio *vio;
 
2458
  if (should_lock)
 
2459
    (void) pthread_mutex_lock(&LOCK_thread_count);
 
2460
  killed= Session::KILL_CONNECTION;
 
2461
  if ((vio= net.vio) != 0)
1653
2462
  {
1654
 
    if (errcode != EE_OK)
1655
 
    {
1656
 
      /*my_error(errcode, ER(errcode));*/
1657
 
      client->sendError(errcode, ER(errcode));
1658
 
    }
1659
 
    client->close();
 
2463
    if (errcode)
 
2464
      net_send_error(this, errcode, ER(errcode)); /* purecov: inspected */
 
2465
    drizzleclient_net_close(&net);              /* vio is freed in delete session */
1660
2466
  }
 
2467
  if (should_lock)
 
2468
    (void) pthread_mutex_unlock(&LOCK_thread_count);
1661
2469
}
1662
2470
 
 
2471
/**
 
2472
 Reset Session part responsible for command processing state.
 
2473
 
 
2474
   This needs to be called before execution of every statement
 
2475
   (prepared or conventional).
 
2476
   It is not called by substatements of routines.
 
2477
 
 
2478
  @todo
 
2479
   Make it a method of Session and align its name with the rest of
 
2480
   reset/end/start/init methods.
 
2481
  @todo
 
2482
   Call it after we use Session for queries, not before.
 
2483
*/
 
2484
 
1663
2485
void Session::reset_for_next_command()
1664
2486
{
1665
2487
  free_list= 0;
1670
2492
  */
1671
2493
  auto_inc_intervals_in_cur_stmt_for_binlog.empty();
1672
2494
 
1673
 
  is_fatal_error= false;
 
2495
  is_fatal_error= 0;
1674
2496
  server_status&= ~ (SERVER_MORE_RESULTS_EXISTS |
1675
2497
                          SERVER_QUERY_NO_INDEX_USED |
1676
2498
                          SERVER_QUERY_NO_GOOD_INDEX_USED);
 
2499
  /*
 
2500
    If in autocommit mode and not in a transaction, reset
 
2501
    OPTION_STATUS_NO_TRANS_UPDATE | OPTION_KEEP_LOG to not get warnings
 
2502
    in ha_rollback_trans() about some tables couldn't be rolled back.
 
2503
  */
 
2504
  if (!(options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))
 
2505
  {
 
2506
    options&= ~OPTION_KEEP_LOG;
 
2507
    transaction.all.modified_non_trans_table= false;
 
2508
  }
 
2509
  thread_specific_used= false;
1677
2510
 
1678
2511
  clear_error();
1679
2512
  main_da.reset_diagnostics_area();
1680
2513
  total_warn_count=0;                   // Warnings for this query
1681
2514
  sent_row_count= examined_row_count= 0;
 
2515
 
 
2516
  return;
1682
2517
}
1683
2518
 
1684
2519
/*
1685
2520
  Close all temporary tables created by 'CREATE TEMPORARY TABLE' for thread
 
2521
  creates one DROP TEMPORARY Table binlog event for each pseudo-thread
1686
2522
*/
1687
2523
 
1688
 
void Open_tables_state::close_temporary_tables()
 
2524
void Session::close_temporary_tables()
1689
2525
{
1690
2526
  Table *table;
1691
2527
  Table *tmp_next;
1692
2528
 
1693
 
  if (not temporary_tables)
 
2529
  if (!temporary_tables)
1694
2530
    return;
1695
2531
 
1696
2532
  for (table= temporary_tables; table; table= tmp_next)
1697
2533
  {
1698
 
    tmp_next= table->getNext();
1699
 
    nukeTable(table);
1700
 
  }
1701
 
  temporary_tables= NULL;
1702
 
}
1703
 
 
1704
 
/*
1705
 
  unlink from session->temporary tables and close temporary table
1706
 
*/
1707
 
 
1708
 
void Open_tables_state::close_temporary_table(Table *table)
1709
 
{
1710
 
  if (table->getPrev())
1711
 
  {
1712
 
    table->getPrev()->setNext(table->getNext());
1713
 
    if (table->getPrev()->getNext())
1714
 
    {
1715
 
      table->getNext()->setPrev(table->getPrev());
1716
 
    }
1717
 
  }
1718
 
  else
1719
 
  {
1720
 
    /* removing the item from the list */
1721
 
    assert(table == temporary_tables);
1722
 
    /*
1723
 
      slave must reset its temporary list pointer to zero to exclude
1724
 
      passing non-zero value to end_slave via rli->save_temporary_tables
1725
 
      when no temp tables opened, see an invariant below.
1726
 
    */
1727
 
    temporary_tables= table->getNext();
1728
 
    if (temporary_tables)
1729
 
    {
1730
 
      table->getNext()->setPrev(NULL);
1731
 
    }
1732
 
  }
1733
 
  nukeTable(table);
1734
 
}
1735
 
 
1736
 
/*
1737
 
  Close and drop a temporary table
1738
 
 
1739
 
  NOTE
1740
 
  This dosn't unlink table from session->temporary
1741
 
  If this is needed, use close_temporary_table()
1742
 
*/
1743
 
 
1744
 
void Open_tables_state::nukeTable(Table *table)
1745
 
{
1746
 
  plugin::StorageEngine *table_type= table->getShare()->db_type();
1747
 
 
1748
 
  table->free_io_cache();
1749
 
  table->delete_table();
1750
 
 
1751
 
  identifier::Table identifier(table->getShare()->getSchemaName(), table->getShare()->getTableName(), table->getShare()->getPath());
1752
 
  rm_temporary_table(table_type, identifier);
1753
 
 
1754
 
  boost::checked_delete(table->getMutableShare());
1755
 
 
1756
 
  boost::checked_delete(table);
1757
 
}
 
2534
    tmp_next= table->next;
 
2535
    close_temporary(table, 1, 1);
 
2536
  }
 
2537
  temporary_tables= 0;
 
2538
 
 
2539
  return;
 
2540
}
 
2541
 
1758
2542
 
1759
2543
/** Clear most status variables. */
1760
2544
extern time_t flush_status_time;
 
2545
extern uint32_t max_used_connections;
1761
2546
 
1762
2547
void Session::refresh_status()
1763
2548
{
 
2549
  pthread_mutex_lock(&LOCK_status);
 
2550
 
 
2551
  /* Add thread's status variabes to global status */
 
2552
  add_to_status(&global_status_var, &status_var);
 
2553
 
1764
2554
  /* Reset thread's status variables */
1765
2555
  memset(&status_var, 0, sizeof(status_var));
1766
2556
 
 
2557
  /* Reset some global variables */
 
2558
  reset_status_vars();
 
2559
 
 
2560
  /* Reset the counters of all key caches (default and named). */
 
2561
  process_key_caches(reset_key_cache_counters);
1767
2562
  flush_status_time= time((time_t*) 0);
1768
 
  current_global_counters.max_used_connections= 1; /* We set it to one, because we know we exist */
1769
 
  current_global_counters.connections= 0;
1770
 
}
1771
 
 
1772
 
user_var_entry *Session::getVariable(LEX_STRING &name, bool create_if_not_exists)
1773
 
{
1774
 
  return getVariable(std::string(name.str, name.length), create_if_not_exists);
1775
 
}
1776
 
 
1777
 
user_var_entry *Session::getVariable(const std::string  &name, bool create_if_not_exists)
1778
 
{
1779
 
  if (cleanup_done)
1780
 
    return NULL;
1781
 
 
1782
 
  UserVars::iterator iter= user_vars.find(name);
1783
 
  if (iter != user_vars.end())
1784
 
    return (*iter).second;
1785
 
 
1786
 
  if (not create_if_not_exists)
1787
 
    return NULL;
1788
 
 
1789
 
  user_var_entry *entry= NULL;
1790
 
  entry= new (nothrow) user_var_entry(name.c_str(), query_id);
1791
 
 
1792
 
  if (entry == NULL)
1793
 
    return NULL;
1794
 
 
1795
 
  std::pair<UserVars::iterator, bool> returnable= user_vars.insert(make_pair(name, entry));
1796
 
 
1797
 
  if (not returnable.second)
1798
 
  {
1799
 
    boost::checked_delete(entry);
1800
 
  }
1801
 
 
1802
 
  return entry;
1803
 
}
1804
 
 
1805
 
void Session::setVariable(const std::string &name, const std::string &value)
1806
 
{
1807
 
  user_var_entry *updateable_var= getVariable(name.c_str(), true);
1808
 
  if (updateable_var)
1809
 
  {
1810
 
    updateable_var->update_hash(false,
1811
 
                                (void*)value.c_str(),
1812
 
                                static_cast<uint32_t>(value.length()), STRING_RESULT,
1813
 
                                &my_charset_bin,
1814
 
                                DERIVATION_IMPLICIT, false);
1815
 
  }
1816
 
}
1817
 
 
1818
 
void Open_tables_state::mark_temp_tables_as_free_for_reuse()
1819
 
{
1820
 
  for (Table *table= temporary_tables ; table ; table= table->getNext())
1821
 
  {
1822
 
    if (table->query_id == getQueryId())
1823
 
    {
1824
 
      table->query_id= 0;
1825
 
      table->cursor->ha_reset();
1826
 
    }
1827
 
  }
1828
 
}
1829
 
 
1830
 
void Session::mark_used_tables_as_free_for_reuse(Table *table)
1831
 
{
1832
 
  for (; table ; table= table->getNext())
1833
 
  {
1834
 
    if (table->query_id == getQueryId())
1835
 
    {
1836
 
      table->query_id= 0;
1837
 
      table->cursor->ha_reset();
1838
 
    }
1839
 
  }
1840
 
}
1841
 
 
1842
 
/*
1843
 
  Unlocks tables and frees derived tables.
1844
 
  Put all normal tables used by thread in free list.
1845
 
 
1846
 
  It will only close/mark as free for reuse tables opened by this
1847
 
  substatement, it will also check if we are closing tables after
1848
 
  execution of complete query (i.e. we are on upper level) and will
1849
 
  leave prelocked mode if needed.
1850
 
*/
1851
 
void Session::close_thread_tables()
1852
 
{
1853
 
  clearDerivedTables();
1854
 
 
1855
 
  /*
1856
 
    Mark all temporary tables used by this statement as free for reuse.
1857
 
  */
1858
 
  mark_temp_tables_as_free_for_reuse();
1859
 
  /*
1860
 
    Let us commit transaction for statement. Since in 5.0 we only have
1861
 
    one statement transaction and don't allow several nested statement
1862
 
    transactions this call will do nothing if we are inside of stored
1863
 
    function or trigger (i.e. statement transaction is already active and
1864
 
    does not belong to statement for which we do close_thread_tables()).
1865
 
    TODO: This should be fixed in later releases.
1866
 
   */
1867
 
  {
1868
 
    TransactionServices &transaction_services= TransactionServices::singleton();
1869
 
    main_da.can_overwrite_status= true;
1870
 
    transaction_services.autocommitOrRollback(*this, is_error());
1871
 
    main_da.can_overwrite_status= false;
1872
 
    transaction.stmt.reset();
1873
 
  }
1874
 
 
1875
 
  if (lock)
1876
 
  {
1877
 
    /*
1878
 
      For RBR we flush the pending event just before we unlock all the
1879
 
      tables.  This means that we are at the end of a topmost
1880
 
      statement, so we ensure that the STMT_END_F flag is set on the
1881
 
      pending event.  For statements that are *inside* stored
1882
 
      functions, the pending event will not be flushed: that will be
1883
 
      handled either before writing a query log event (inside
1884
 
      binlog_query()) or when preparing a pending event.
1885
 
     */
1886
 
    unlockTables(lock);
1887
 
    lock= 0;
1888
 
  }
1889
 
  /*
1890
 
    Note that we need to hold table::Cache::singleton().mutex() while changing the
1891
 
    open_tables list. Another thread may work on it.
1892
 
    (See: table::Cache::singleton().removeTable(), wait_completed_table())
1893
 
    Closing a MERGE child before the parent would be fatal if the
1894
 
    other thread tries to abort the MERGE lock in between.
1895
 
  */
1896
 
  if (open_tables)
1897
 
    close_open_tables();
1898
 
}
1899
 
 
1900
 
void Session::close_tables_for_reopen(TableList **tables)
1901
 
{
1902
 
  /*
1903
 
    If table list consists only from tables from prelocking set, table list
1904
 
    for new attempt should be empty, so we have to update list's root pointer.
1905
 
  */
1906
 
  if (lex->first_not_own_table() == *tables)
1907
 
    *tables= 0;
1908
 
  lex->chop_off_not_own_tables();
1909
 
  for (TableList *tmp= *tables; tmp; tmp= tmp->next_global)
1910
 
    tmp->table= 0;
1911
 
  close_thread_tables();
1912
 
}
1913
 
 
1914
 
bool Session::openTablesLock(TableList *tables)
1915
 
{
1916
 
  uint32_t counter;
1917
 
  bool need_reopen;
1918
 
 
1919
 
  for ( ; ; )
1920
 
  {
1921
 
    if (open_tables_from_list(&tables, &counter))
1922
 
      return true;
1923
 
 
1924
 
    if (not lock_tables(tables, counter, &need_reopen))
1925
 
      break;
1926
 
 
1927
 
    if (not need_reopen)
1928
 
      return true;
1929
 
 
1930
 
    close_tables_for_reopen(&tables);
1931
 
  }
1932
 
 
1933
 
  if ((handle_derived(lex, &derived_prepare) || (handle_derived(lex, &derived_filling))))
1934
 
    return true;
1935
 
 
1936
 
  return false;
1937
 
}
1938
 
 
1939
 
/*
1940
 
  @note "best_effort" is used in cases were if a failure occurred on this
1941
 
  operation it would not be surprising because we are only removing because there
1942
 
  might be an issue (lame engines).
1943
 
*/
1944
 
 
1945
 
bool Open_tables_state::rm_temporary_table(const identifier::Table &identifier, bool best_effort)
1946
 
{
1947
 
  if (not plugin::StorageEngine::dropTable(*static_cast<Session *>(this), identifier))
1948
 
  {
1949
 
    if (not best_effort)
1950
 
    {
1951
 
      std::string path;
1952
 
      identifier.getSQLPath(path);
1953
 
      errmsg_printf(error::WARN, _("Could not remove temporary table: '%s', error: %d"),
1954
 
                    path.c_str(), errno);
1955
 
    }
1956
 
 
1957
 
    return true;
1958
 
  }
1959
 
 
1960
 
  return false;
1961
 
}
1962
 
 
1963
 
bool Open_tables_state::rm_temporary_table(plugin::StorageEngine *base, const identifier::Table &identifier)
1964
 
{
1965
 
  drizzled::error_t error;
1966
 
  assert(base);
1967
 
 
1968
 
  if (not plugin::StorageEngine::dropTable(*static_cast<Session *>(this), *base, identifier, error))
1969
 
  {
1970
 
    std::string path;
1971
 
    identifier.getSQLPath(path);
1972
 
    errmsg_printf(error::WARN, _("Could not remove temporary table: '%s', error: %d"),
1973
 
                  path.c_str(), error);
1974
 
 
1975
 
    return true;
1976
 
  }
1977
 
 
1978
 
  return false;
1979
 
}
1980
 
 
1981
 
/**
1982
 
  @note this will be removed, I am looking through Hudson to see if it is finding
1983
 
  any tables that are missed during cleanup.
1984
 
*/
1985
 
void Open_tables_state::dumpTemporaryTableNames(const char *foo)
1986
 
{
1987
 
  Table *table;
1988
 
 
1989
 
  if (not temporary_tables)
1990
 
    return;
1991
 
 
1992
 
  cerr << "Begin Run: " << foo << "\n";
1993
 
  for (table= temporary_tables; table; table= table->getNext())
1994
 
  {
1995
 
    bool have_proto= false;
1996
 
 
1997
 
    message::Table *proto= table->getShare()->getTableMessage();
1998
 
    if (table->getShare()->getTableMessage())
1999
 
      have_proto= true;
2000
 
 
2001
 
    const char *answer= have_proto ? "true" : "false";
2002
 
 
2003
 
    if (have_proto)
2004
 
    {
2005
 
      cerr << "\tTable Name " << table->getShare()->getSchemaName() << "." << table->getShare()->getTableName() << " : " << answer << "\n";
2006
 
      cerr << "\t\t Proto " << proto->schema() << " " << proto->name() << "\n";
2007
 
    }
2008
 
    else
2009
 
    {
2010
 
      cerr << "\tTabl;e Name " << table->getShare()->getSchemaName() << "." << table->getShare()->getTableName() << " : " << answer << "\n";
2011
 
    }
2012
 
  }
2013
 
}
2014
 
 
2015
 
table::Singular *Session::getInstanceTable()
2016
 
{
2017
 
  temporary_shares.push_back(new table::Singular()); // This will not go into the tableshare cache, so no key is used.
2018
 
 
2019
 
  table::Singular *tmp_share= temporary_shares.back();
2020
 
 
2021
 
  assert(tmp_share);
2022
 
 
2023
 
  return tmp_share;
2024
 
}
2025
 
 
2026
 
 
2027
 
/**
2028
 
  Create a reduced Table object with properly set up Field list from a
2029
 
  list of field definitions.
2030
 
 
2031
 
    The created table doesn't have a table Cursor associated with
2032
 
    it, has no keys, no group/distinct, no copy_funcs array.
2033
 
    The sole purpose of this Table object is to use the power of Field
2034
 
    class to read/write data to/from table->getInsertRecord(). Then one can store
2035
 
    the record in any container (RB tree, hash, etc).
2036
 
    The table is created in Session mem_root, so are the table's fields.
2037
 
    Consequently, if you don't BLOB fields, you don't need to free it.
2038
 
 
2039
 
  @param session         connection handle
2040
 
  @param field_list  list of column definitions
2041
 
 
2042
 
  @return
2043
 
    0 if out of memory, Table object in case of success
2044
 
*/
2045
 
table::Singular *Session::getInstanceTable(List<CreateField> &field_list)
2046
 
{
2047
 
  temporary_shares.push_back(new table::Singular(this, field_list)); // This will not go into the tableshare cache, so no key is used.
2048
 
 
2049
 
  table::Singular *tmp_share= temporary_shares.back();
2050
 
 
2051
 
  assert(tmp_share);
2052
 
 
2053
 
  return tmp_share;
2054
 
}
2055
 
 
2056
 
namespace display  {
2057
 
 
2058
 
static const std::string NONE= "NONE";
2059
 
static const std::string GOT_GLOBAL_READ_LOCK= "HAS GLOBAL READ LOCK";
2060
 
static const std::string MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT= "HAS GLOBAL READ LOCK WITH BLOCKING COMMIT";
2061
 
 
2062
 
const std::string &type(drizzled::Session::global_read_lock_t type)
2063
 
{
2064
 
  switch (type) {
2065
 
    default:
2066
 
    case Session::NONE:
2067
 
      return NONE;
2068
 
    case Session::GOT_GLOBAL_READ_LOCK:
2069
 
      return GOT_GLOBAL_READ_LOCK;
2070
 
    case Session::MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT:
2071
 
      return MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT;
2072
 
  }
2073
 
}
2074
 
 
2075
 
size_t max_string_length(drizzled::Session::global_read_lock_t)
2076
 
{
2077
 
  return MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT.size();
2078
 
}
2079
 
 
2080
 
} /* namespace display */
2081
 
 
2082
 
} /* namespace drizzled */
 
2563
  max_used_connections= 1; /* We set it to one, because we know we exist */
 
2564
  pthread_mutex_unlock(&LOCK_status);
 
2565
}