~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_parse.cc

  • Committer: Brian Aker
  • Date: 2009-07-16 22:37:01 UTC
  • mto: This revision was merged to the branch mainline in revision 1100.
  • Revision ID: brian@gaz-20090716223701-vbbbo8dmgd2ljqqo
Refactor TableShare has to be behind class.

Show diffs side-by-side

added added

removed removed

Lines of Context:
13
13
   along with this program; if not, write to the Free Software
14
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
15
 
16
 
#include "config.h"
17
 
 
18
16
#define DRIZZLE_LEX 1
19
 
 
20
 
#include <drizzled/my_hash.h>
 
17
#include <drizzled/server_includes.h>
 
18
#include <mysys/hash.h>
 
19
#include <drizzled/logging.h>
 
20
#include <drizzled/db.h>
21
21
#include <drizzled/error.h>
22
22
#include <drizzled/nested_join.h>
23
23
#include <drizzled/query_id.h>
24
 
#include "drizzled/transaction_services.h"
25
24
#include <drizzled/sql_parse.h>
26
25
#include <drizzled/data_home.h>
27
26
#include <drizzled/sql_base.h>
28
27
#include <drizzled/show.h>
29
 
#include <drizzled/db.h>
 
28
#include <drizzled/info_schema.h>
 
29
#include <drizzled/rename.h>
30
30
#include <drizzled/function/time/unix_timestamp.h>
31
31
#include <drizzled/function/get_system_var.h>
32
32
#include <drizzled/item/cmpfunc.h>
33
33
#include <drizzled/item/null.h>
34
34
#include <drizzled/session.h>
35
35
#include <drizzled/sql_load.h>
 
36
#include <drizzled/connect.h>
36
37
#include <drizzled/lock.h>
37
38
#include <drizzled/select_send.h>
38
 
#include <drizzled/plugin/client.h>
39
 
#include <drizzled/statement.h>
40
 
#include <drizzled/statement/alter_table.h>
41
 
#include "drizzled/probes.h"
42
 
#include "drizzled/session_list.h"
43
 
#include "drizzled/global_charset_info.h"
44
 
 
45
 
#include "drizzled/plugin/logging.h"
46
 
#include "drizzled/plugin/query_rewrite.h"
47
 
#include "drizzled/plugin/authorization.h"
48
 
#include "drizzled/optimizer/explain_plan.h"
49
 
#include "drizzled/pthread_globals.h"
50
 
 
51
 
#include <limits.h>
52
 
 
53
39
#include <bitset>
54
40
#include <algorithm>
55
41
 
56
 
#include "drizzled/internal/my_sys.h"
57
 
 
58
42
using namespace std;
59
43
 
60
 
extern int DRIZZLEparse(void *session); // from sql_yacc.cc
61
 
 
62
 
namespace drizzled
63
 
{
64
 
 
65
44
/* Prototypes */
 
45
static bool append_file_to_dir(Session *session, const char **filename_ptr,
 
46
                               const char *table_name);
 
47
 
66
48
bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
67
 
static bool parse_sql(Session *session, Lex_input_stream *lip);
68
 
void mysql_parse(Session *session, const char *inBuf, uint32_t length);
69
49
 
70
50
/**
71
51
  @defgroup Runtime_Environment Runtime Environment
74
54
 
75
55
extern size_t my_thread_stack_size;
76
56
extern const CHARSET_INFO *character_set_filesystem;
 
57
const char *any_db="*any*";     // Special symbol for check_access
77
58
 
78
59
const LEX_STRING command_name[COM_END+1]={
79
60
  { C_STRING_WITH_LEN("Sleep") },
123
104
  sql_command_flags[SQLCOM_DROP_INDEX]=     CF_CHANGES_DATA;
124
105
 
125
106
  sql_command_flags[SQLCOM_UPDATE]=         CF_CHANGES_DATA | CF_HAS_ROW_COUNT;
 
107
  sql_command_flags[SQLCOM_UPDATE_MULTI]=   CF_CHANGES_DATA | CF_HAS_ROW_COUNT;
126
108
  sql_command_flags[SQLCOM_INSERT]=         CF_CHANGES_DATA | CF_HAS_ROW_COUNT;
127
109
  sql_command_flags[SQLCOM_INSERT_SELECT]=  CF_CHANGES_DATA | CF_HAS_ROW_COUNT;
128
110
  sql_command_flags[SQLCOM_DELETE]=         CF_CHANGES_DATA | CF_HAS_ROW_COUNT;
 
111
  sql_command_flags[SQLCOM_DELETE_MULTI]=   CF_CHANGES_DATA | CF_HAS_ROW_COUNT;
129
112
  sql_command_flags[SQLCOM_REPLACE]=        CF_CHANGES_DATA | CF_HAS_ROW_COUNT;
130
113
  sql_command_flags[SQLCOM_REPLACE_SELECT]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT;
131
114
 
 
115
  sql_command_flags[SQLCOM_SHOW_STATUS]=      CF_STATUS_COMMAND;
 
116
  sql_command_flags[SQLCOM_SHOW_DATABASES]=   CF_STATUS_COMMAND;
 
117
  sql_command_flags[SQLCOM_SHOW_OPEN_TABLES]= CF_STATUS_COMMAND;
 
118
  sql_command_flags[SQLCOM_SHOW_FIELDS]=      CF_STATUS_COMMAND;
 
119
  sql_command_flags[SQLCOM_SHOW_KEYS]=        CF_STATUS_COMMAND;
 
120
  sql_command_flags[SQLCOM_SHOW_VARIABLES]=   CF_STATUS_COMMAND;
132
121
  sql_command_flags[SQLCOM_SHOW_WARNS]= CF_STATUS_COMMAND;
133
122
  sql_command_flags[SQLCOM_SHOW_ERRORS]= CF_STATUS_COMMAND;
 
123
  sql_command_flags[SQLCOM_SHOW_ENGINE_STATUS]= CF_STATUS_COMMAND;
 
124
  sql_command_flags[SQLCOM_SHOW_PROCESSLIST]= CF_STATUS_COMMAND;
134
125
  sql_command_flags[SQLCOM_SHOW_CREATE_DB]=  CF_STATUS_COMMAND;
135
126
  sql_command_flags[SQLCOM_SHOW_CREATE]=  CF_STATUS_COMMAND;
136
127
 
 
128
   sql_command_flags[SQLCOM_SHOW_TABLES]=       (CF_STATUS_COMMAND |
 
129
                                               CF_SHOW_TABLE_COMMAND);
 
130
  sql_command_flags[SQLCOM_SHOW_TABLE_STATUS]= (CF_STATUS_COMMAND |
 
131
                                                CF_SHOW_TABLE_COMMAND);
137
132
  /*
138
133
    The following admin table operations are allowed
139
134
    on log tables.
140
135
  */
 
136
  sql_command_flags[SQLCOM_OPTIMIZE]=         CF_WRITE_LOGS_COMMAND;
141
137
  sql_command_flags[SQLCOM_ANALYZE]=          CF_WRITE_LOGS_COMMAND;
142
138
}
143
139
 
 
140
 
 
141
bool is_update_query(enum enum_sql_command command)
 
142
{
 
143
  assert(command >= 0 && command <= SQLCOM_END);
 
144
  return (sql_command_flags[command].test(CF_BIT_CHANGES_DATA));
 
145
}
 
146
 
144
147
/**
145
148
  Perform one connection-level (COM_XXXX) command.
146
149
 
168
171
  bool error= 0;
169
172
  Query_id &query_id= Query_id::get_query_id();
170
173
 
171
 
  DRIZZLE_COMMAND_START(session->thread_id,
172
 
                        command);
173
 
 
174
 
  session->command= command;
 
174
  session->command=command;
175
175
  session->lex->sql_command= SQLCOM_END; /* to avoid confusing VIEW detectors */
176
176
  session->set_time();
177
 
  session->setQueryId(query_id.value());
 
177
  session->query_id= query_id.value();
178
178
 
179
179
  switch( command ) {
180
180
  /* Ignore these statements. */
188
188
 
189
189
  /* TODO: set session->lex->sql_command to SQLCOM_END here */
190
190
 
191
 
  plugin::Logging::preDo(session);
 
191
  logging_pre_do(session);
192
192
 
193
193
  session->server_status&=
194
194
           ~(SERVER_QUERY_NO_INDEX_USED | SERVER_QUERY_NO_GOOD_INDEX_USED);
195
195
  switch (command) {
196
196
  case COM_INIT_DB:
197
197
  {
 
198
    LEX_STRING tmp;
198
199
    status_var_increment(session->status_var.com_stat[SQLCOM_CHANGE_DB]);
199
 
    if (packet_length == 0)
200
 
    {
201
 
      my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
202
 
      break;
203
 
    }
204
 
 
205
 
    string tmp(packet, packet_length);
206
 
 
207
 
    SchemaIdentifier identifier(tmp);
208
 
 
209
 
    if (not mysql_change_db(session, identifier))
 
200
    tmp.str= packet;
 
201
    tmp.length= packet_length;
 
202
    if (!mysql_change_db(session, &tmp, false))
210
203
    {
211
204
      session->my_ok();
212
205
    }
216
209
  {
217
210
    if (! session->readAndStoreQuery(packet, packet_length))
218
211
      break;                                    // fatal error is set
219
 
    DRIZZLE_QUERY_START(session->query.c_str(),
220
 
                        session->thread_id,
221
 
                        const_cast<const char *>(session->db.empty() ? "" : session->db.c_str()));
 
212
    const char* end_of_stmt= NULL;
222
213
 
223
 
    plugin::QueryRewriter::rewriteQuery(session->db, session->query);
224
 
    mysql_parse(session, session->query.c_str(), session->query.length());
 
214
    mysql_parse(session, session->query, session->query_length, &end_of_stmt);
225
215
 
226
216
    break;
227
217
  }
228
218
  case COM_QUIT:
229
219
    /* We don't calculate statistics for this command */
 
220
    session->protocol->setError(0);
230
221
    session->main_da.disable_status();              // Don't send anything back
231
222
    error=true;                                 // End server
232
223
    break;
253
244
 
254
245
  /* If commit fails, we should be able to reset the OK status. */
255
246
  session->main_da.can_overwrite_status= true;
256
 
  TransactionServices &transaction_services= TransactionServices::singleton();
257
 
  transaction_services.ha_autocommit_or_rollback(session, session->is_error());
 
247
  ha_autocommit_or_rollback(session, session->is_error());
258
248
  session->main_da.can_overwrite_status= false;
259
249
 
260
250
  session->transaction.stmt.reset();
279
269
  {
280
270
  case Diagnostics_area::DA_ERROR:
281
271
    /* The query failed, send error to log and abort bootstrap. */
282
 
    session->client->sendError(session->main_da.sql_errno(),
283
 
                               session->main_da.message());
 
272
    session->protocol->sendError(session->main_da.sql_errno(),
 
273
                                 session->main_da.message());
284
274
    break;
285
275
 
286
276
  case Diagnostics_area::DA_EOF:
287
 
    session->client->sendEOF();
 
277
    session->protocol->sendEOF();
288
278
    break;
289
279
 
290
280
  case Diagnostics_area::DA_OK:
291
 
    session->client->sendOK();
 
281
    session->protocol->sendOK();
292
282
    break;
293
283
 
294
284
  case Diagnostics_area::DA_DISABLED:
296
286
 
297
287
  case Diagnostics_area::DA_EMPTY:
298
288
  default:
299
 
    session->client->sendOK();
 
289
    session->protocol->sendOK();
300
290
    break;
301
291
  }
302
292
 
306
296
  /* Free tables */
307
297
  session->close_thread_tables();
308
298
 
309
 
  plugin::Logging::postDo(session);
 
299
  logging_post_do(session);
310
300
 
311
301
  /* Store temp state for processlist */
312
302
  session->set_proc_info("cleaning up");
313
 
  session->command= COM_SLEEP;
 
303
  session->command=COM_SLEEP;
314
304
  memset(session->process_list_info, 0, PROCESS_LIST_WIDTH);
315
 
  session->query.clear();
 
305
  session->query=0;
 
306
  session->query_length=0;
316
307
 
317
308
  session->set_proc_info(NULL);
318
 
  free_root(session->mem_root,MYF(memory::KEEP_PREALLOC));
319
 
 
320
 
  if (DRIZZLE_QUERY_DONE_ENABLED() || DRIZZLE_COMMAND_DONE_ENABLED())
321
 
  {
322
 
    if (command == COM_QUERY)
323
 
    {
324
 
      DRIZZLE_QUERY_DONE(session->is_error());
325
 
    }
326
 
    DRIZZLE_COMMAND_DONE(session->is_error());
327
 
  }
328
 
 
329
 
  return error;
 
309
  session->packet.shrink(session->variables.net_buffer_length); // Reclaim some memory
 
310
  free_root(session->mem_root,MYF(MY_KEEP_PREALLOC));
 
311
  return(error);
330
312
}
331
313
 
332
314
 
355
337
    1                 out of memory or SHOW commands are not allowed
356
338
                      in this version of the server.
357
339
*/
358
 
static bool _schema_select(Session *session, Select_Lex *sel,
359
 
                           const string& schema_table_name)
360
 
{
361
 
  LEX_STRING db, table;
362
 
  /*
363
 
     We have to make non const db_name & table_name
364
 
     because of lower_case_table_names
365
 
  */
366
 
  session->make_lex_string(&db, "data_dictionary", sizeof("data_dictionary"), false);
367
 
  session->make_lex_string(&table, schema_table_name, false);
368
 
 
369
 
  if (! sel->add_table_to_list(session, new Table_ident(db, table),
370
 
                               NULL, 0, TL_READ))
371
 
  {
372
 
    return true;
373
 
  }
374
 
  return false;
375
 
}
376
 
 
377
 
int prepare_new_schema_table(Session *session, LEX *lex,
378
 
                             const string& schema_table_name)
 
340
 
 
341
int prepare_schema_table(Session *session, LEX *lex, Table_ident *table_ident,
 
342
                         const string& schema_table_name)
379
343
{
380
344
  Select_Lex *schema_select_lex= NULL;
381
345
 
 
346
 
 
347
  if (schema_table_name.compare("TABLES") == 0 ||
 
348
      schema_table_name.compare("TABLE_NAMES") == 0)
 
349
  {
 
350
    LEX_STRING db;
 
351
    size_t dummy;
 
352
    if (lex->select_lex.db == NULL &&
 
353
        lex->copy_db_to(&lex->select_lex.db, &dummy))
 
354
    {
 
355
      return (1);
 
356
    }
 
357
    schema_select_lex= new Select_Lex();
 
358
    db.str= schema_select_lex->db= lex->select_lex.db;
 
359
    schema_select_lex->table_list.first= NULL;
 
360
    db.length= strlen(db.str);
 
361
 
 
362
    if (check_db_name(&db))
 
363
    {
 
364
      my_error(ER_WRONG_DB_NAME, MYF(0), db.str);
 
365
      return (1);
 
366
    }
 
367
  }
 
368
  else if (schema_table_name.compare("COLUMNS") == 0 ||
 
369
           schema_table_name.compare("STATISTICS") == 0)
 
370
  {
 
371
    assert(table_ident);
 
372
    TableList **query_tables_last= lex->query_tables_last;
 
373
    schema_select_lex= new Select_Lex();
 
374
    /* 'parent_lex' is used in init_query() so it must be before it. */
 
375
    schema_select_lex->parent_lex= lex;
 
376
    schema_select_lex->init_query();
 
377
    if (! schema_select_lex->add_table_to_list(session, table_ident, 0, 0, TL_READ))
 
378
    {
 
379
      return (1);
 
380
    }
 
381
    lex->query_tables_last= query_tables_last;
 
382
  }
 
383
 
382
384
  Select_Lex *select_lex= lex->current_select;
383
385
  assert(select_lex);
384
 
  if (_schema_select(session, select_lex, schema_table_name))
 
386
  if (make_schema_select(session, select_lex, schema_table_name))
385
387
  {
386
388
    return(1);
387
389
  }
425
427
static int
426
428
mysql_execute_command(Session *session)
427
429
{
428
 
  bool res= false;
 
430
  int res= false;
 
431
  bool need_start_waiting= false; // have protection against global read lock
429
432
  LEX  *lex= session->lex;
430
433
  /* first Select_Lex (have special meaning for many of non-SELECTcommands) */
431
434
  Select_Lex *select_lex= &lex->select_lex;
 
435
  /* first table of first Select_Lex */
 
436
  TableList *first_table= (TableList*) select_lex->table_list.first;
432
437
  /* list of all tables in query */
433
438
  TableList *all_tables;
 
439
  /* most outer Select_Lex_Unit of query */
 
440
  Select_Lex_Unit *unit= &lex->unit;
434
441
  /* A peek into the query string */
435
 
  size_t proc_info_len= session->query.length() > PROCESS_LIST_WIDTH ?
436
 
                        PROCESS_LIST_WIDTH : session->query.length();
 
442
  size_t proc_info_len= session->query_length > PROCESS_LIST_WIDTH ?
 
443
                        PROCESS_LIST_WIDTH : session->query_length;
437
444
 
438
 
  memcpy(session->process_list_info, session->query.c_str(), proc_info_len);
 
445
  memcpy(session->process_list_info, session->query, proc_info_len);
439
446
  session->process_list_info[proc_info_len]= '\0';
440
447
 
441
448
  /*
468
475
    variables, but for now this is probably good enough.
469
476
    Don't reset warnings when executing a stored routine.
470
477
  */
471
 
  if (all_tables || ! lex->is_single_level_stmt())
472
 
  {
 
478
  if (all_tables || !lex->is_single_level_stmt())
473
479
    drizzle_reset_errors(session, 0);
474
 
  }
475
480
 
476
481
  status_var_increment(session->status_var.com_stat[lex->sql_command]);
477
482
 
478
 
  assert(session->transaction.stmt.hasModifiedNonTransData() == false);
479
 
 
480
 
  /* now we are ready to execute the statement */
481
 
  res= lex->statement->execute();
482
 
 
 
483
  assert(session->transaction.stmt.modified_non_trans_table == false);
 
484
 
 
485
  switch (lex->sql_command) {
 
486
  case SQLCOM_SHOW_STATUS:
 
487
  {
 
488
    system_status_var old_status_var= session->status_var;
 
489
    session->initial_status_var= &old_status_var;
 
490
    res= execute_sqlcom_select(session, all_tables);
 
491
    /* Don't log SHOW STATUS commands to slow query log */
 
492
    session->server_status&= ~(SERVER_QUERY_NO_INDEX_USED |
 
493
                           SERVER_QUERY_NO_GOOD_INDEX_USED);
 
494
    /*
 
495
      restore status variables, as we don't want 'show status' to cause
 
496
      changes
 
497
    */
 
498
    pthread_mutex_lock(&LOCK_status);
 
499
    add_diff_to_status(&global_status_var, &session->status_var,
 
500
                       &old_status_var);
 
501
    session->status_var= old_status_var;
 
502
    pthread_mutex_unlock(&LOCK_status);
 
503
    break;
 
504
  }
 
505
  case SQLCOM_SHOW_DATABASES:
 
506
  case SQLCOM_SHOW_TABLES:
 
507
  case SQLCOM_SHOW_TABLE_STATUS:
 
508
  case SQLCOM_SHOW_OPEN_TABLES:
 
509
  case SQLCOM_SHOW_FIELDS:
 
510
  case SQLCOM_SHOW_KEYS:
 
511
  case SQLCOM_SHOW_VARIABLES:
 
512
  case SQLCOM_SELECT:
 
513
  {
 
514
    session->status_var.last_query_cost= 0.0;
 
515
    res= execute_sqlcom_select(session, all_tables);
 
516
    break;
 
517
  }
 
518
  case SQLCOM_EMPTY_QUERY:
 
519
    session->my_ok();
 
520
    break;
 
521
 
 
522
  case SQLCOM_SHOW_WARNS:
 
523
  {
 
524
    res= mysqld_show_warnings(session, (uint32_t)
 
525
                              ((1L << (uint32_t) DRIZZLE_ERROR::WARN_LEVEL_NOTE) |
 
526
                               (1L << (uint32_t) DRIZZLE_ERROR::WARN_LEVEL_WARN) |
 
527
                               (1L << (uint32_t) DRIZZLE_ERROR::WARN_LEVEL_ERROR)
 
528
                               ));
 
529
    break;
 
530
  }
 
531
  case SQLCOM_SHOW_ERRORS:
 
532
  {
 
533
    res= mysqld_show_warnings(session, (uint32_t)
 
534
                              (1L << (uint32_t) DRIZZLE_ERROR::WARN_LEVEL_ERROR));
 
535
    break;
 
536
  }
 
537
  case SQLCOM_ASSIGN_TO_KEYCACHE:
 
538
  {
 
539
    assert(first_table == all_tables && first_table != 0);
 
540
    res= mysql_assign_to_keycache(session, first_table, &lex->ident);
 
541
    break;
 
542
  }
 
543
  case SQLCOM_SHOW_ENGINE_STATUS:
 
544
    {
 
545
      res = ha_show_status(session, lex->show_engine, HA_ENGINE_STATUS);
 
546
      break;
 
547
    }
 
548
  case SQLCOM_CREATE_TABLE:
 
549
  {
 
550
    /* If CREATE TABLE of non-temporary table, do implicit commit */
 
551
    if (!(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE))
 
552
    {
 
553
      if (! session->endActiveTransaction())
 
554
      {
 
555
        res= -1;
 
556
        break;
 
557
      }
 
558
    }
 
559
    assert(first_table == all_tables && first_table != 0);
 
560
    bool link_to_local;
 
561
    // Skip first table, which is the table we are creating
 
562
    TableList *create_table= lex->unlink_first_table(&link_to_local);
 
563
    TableList *select_tables= lex->query_tables;
 
564
    /*
 
565
      Code below (especially in mysql_create_table() and select_create
 
566
      methods) may modify HA_CREATE_INFO structure in LEX, so we have to
 
567
      use a copy of this structure to make execution prepared statement-
 
568
      safe. A shallow copy is enough as this code won't modify any memory
 
569
      referenced from this structure.
 
570
    */
 
571
    HA_CREATE_INFO create_info(lex->create_info);
 
572
    /*
 
573
      We need to copy alter_info for the same reasons of re-execution
 
574
      safety, only in case of Alter_info we have to do (almost) a deep
 
575
      copy.
 
576
    */
 
577
    Alter_info alter_info(lex->alter_info, session->mem_root);
 
578
 
 
579
    if (session->is_fatal_error)
 
580
    {
 
581
      /* If out of memory when creating a copy of alter_info. */
 
582
      res= 1;
 
583
      goto end_with_restore_list;
 
584
    }
 
585
 
 
586
    if ((res= create_table_precheck(session, select_tables, create_table)))
 
587
      goto end_with_restore_list;
 
588
 
 
589
    /* Might have been updated in create_table_precheck */
 
590
    create_info.alias= create_table->alias;
 
591
 
 
592
#ifdef HAVE_READLINK
 
593
    /* Fix names if symlinked tables */
 
594
    if (append_file_to_dir(session, &create_info.data_file_name,
 
595
                           create_table->table_name) ||
 
596
        append_file_to_dir(session, &create_info.index_file_name,
 
597
                           create_table->table_name))
 
598
      goto end_with_restore_list;
 
599
#endif
 
600
    /*
 
601
      The create-select command will open and read-lock the select table
 
602
      and then create, open and write-lock the new table. If a global
 
603
      read lock steps in, we get a deadlock. The write lock waits for
 
604
      the global read lock, while the global read lock waits for the
 
605
      select table to be closed. So we wait until the global readlock is
 
606
      gone before starting both steps. Note that
 
607
      wait_if_global_read_lock() sets a protection against a new global
 
608
      read lock when it succeeds. This needs to be released by
 
609
      start_waiting_global_read_lock(). We protect the normal CREATE
 
610
      TABLE in the same way. That way we avoid that a new table is
 
611
      created during a gobal read lock.
 
612
    */
 
613
    if (!(need_start_waiting= !wait_if_global_read_lock(session, 0, 1)))
 
614
    {
 
615
      res= 1;
 
616
      goto end_with_restore_list;
 
617
    }
 
618
    if (select_lex->item_list.elements)         // With select
 
619
    {
 
620
      select_result *result;
 
621
 
 
622
      select_lex->options|= SELECT_NO_UNLOCK;
 
623
      unit->set_limit(select_lex);
 
624
 
 
625
      if (!(create_info.options & HA_LEX_CREATE_TMP_TABLE))
 
626
      {
 
627
        lex->link_first_table_back(create_table, link_to_local);
 
628
        create_table->create= true;
 
629
      }
 
630
 
 
631
      if (!(res= session->open_and_lock_tables(lex->query_tables)))
 
632
      {
 
633
        /*
 
634
          Is table which we are changing used somewhere in other parts
 
635
          of query
 
636
        */
 
637
        if (!(create_info.options & HA_LEX_CREATE_TMP_TABLE))
 
638
        {
 
639
          TableList *duplicate;
 
640
          create_table= lex->unlink_first_table(&link_to_local);
 
641
          if ((duplicate= unique_table(session, create_table, select_tables, 0)))
 
642
          {
 
643
            my_error(ER_UPDATE_TABLE_USED, MYF(0), create_table->alias);
 
644
            res= 1;
 
645
            goto end_with_restore_list;
 
646
          }
 
647
        }
 
648
 
 
649
        /*
 
650
          select_create is currently not re-execution friendly and
 
651
          needs to be created for every execution of a PS/SP.
 
652
        */
 
653
        if ((result= new select_create(create_table,
 
654
                                       &create_info,
 
655
                                       lex->create_table_proto,
 
656
                                       &alter_info,
 
657
                                       select_lex->item_list,
 
658
                                       lex->duplicates,
 
659
                                       lex->ignore,
 
660
                                       select_tables)))
 
661
        {
 
662
          /*
 
663
            CREATE from SELECT give its Select_Lex for SELECT,
 
664
            and item_list belong to SELECT
 
665
          */
 
666
          res= handle_select(session, lex, result, 0);
 
667
          delete result;
 
668
        }
 
669
      }
 
670
      else if (!(create_info.options & HA_LEX_CREATE_TMP_TABLE))
 
671
        create_table= lex->unlink_first_table(&link_to_local);
 
672
 
 
673
    }
 
674
    else
 
675
    {
 
676
      /* So that CREATE TEMPORARY TABLE gets to binlog at commit/rollback */
 
677
      if (create_info.options & HA_LEX_CREATE_TMP_TABLE)
 
678
        session->options|= OPTION_KEEP_LOG;
 
679
      /* regular create */
 
680
      if (create_info.options & HA_LEX_CREATE_TABLE_LIKE)
 
681
        res= mysql_create_like_table(session, create_table, select_tables,
 
682
                                     &create_info);
 
683
      else
 
684
      {
 
685
        res= mysql_create_table(session, create_table->db,
 
686
                                create_table->table_name, &create_info,
 
687
                                lex->create_table_proto,
 
688
                                &alter_info, 0, 0);
 
689
      }
 
690
      if (!res)
 
691
        session->my_ok();
 
692
    }
 
693
 
 
694
    /* put tables back for PS rexecuting */
 
695
end_with_restore_list:
 
696
    lex->link_first_table_back(create_table, link_to_local);
 
697
    break;
 
698
  }
 
699
  case SQLCOM_CREATE_INDEX:
 
700
    /* Fall through */
 
701
  case SQLCOM_DROP_INDEX:
 
702
  /*
 
703
    CREATE INDEX and DROP INDEX are implemented by calling ALTER
 
704
    TABLE with proper arguments.
 
705
 
 
706
    In the future ALTER TABLE will notice that the request is to
 
707
    only add indexes and create these one by one for the existing
 
708
    table without having to do a full rebuild.
 
709
  */
 
710
  {
 
711
    /* Prepare stack copies to be re-execution safe */
 
712
    HA_CREATE_INFO create_info;
 
713
    Alter_info alter_info(lex->alter_info, session->mem_root);
 
714
 
 
715
    if (session->is_fatal_error) /* out of memory creating a copy of alter_info */
 
716
      goto error;
 
717
 
 
718
    assert(first_table == all_tables && first_table != 0);
 
719
    if (! session->endActiveTransaction())
 
720
      goto error;
 
721
 
 
722
    memset(&create_info, 0, sizeof(create_info));
 
723
    create_info.db_type= 0;
 
724
    create_info.row_type= ROW_TYPE_NOT_USED;
 
725
    create_info.default_table_charset= get_default_db_collation(session->db);
 
726
 
 
727
    res= mysql_alter_table(session, first_table->db, first_table->table_name,
 
728
                           &create_info, first_table, &alter_info,
 
729
                           0, (order_st*) 0, 0);
 
730
    break;
 
731
  }
 
732
  case SQLCOM_ALTER_TABLE:
 
733
    assert(first_table == all_tables && first_table != 0);
 
734
    {
 
735
      /*
 
736
        Code in mysql_alter_table() may modify its HA_CREATE_INFO argument,
 
737
        so we have to use a copy of this structure to make execution
 
738
        prepared statement- safe. A shallow copy is enough as no memory
 
739
        referenced from this structure will be modified.
 
740
      */
 
741
      HA_CREATE_INFO create_info(lex->create_info);
 
742
      Alter_info alter_info(lex->alter_info, session->mem_root);
 
743
 
 
744
      if (session->is_fatal_error) /* out of memory creating a copy of alter_info */
 
745
      {
 
746
        goto error;
 
747
      }
 
748
 
 
749
      /* Must be set in the parser */
 
750
      assert(select_lex->db);
 
751
 
 
752
      { // Rename of table
 
753
          TableList tmp_table;
 
754
          memset(&tmp_table, 0, sizeof(tmp_table));
 
755
          tmp_table.table_name= lex->name.str;
 
756
          tmp_table.db=select_lex->db;
 
757
      }
 
758
 
 
759
      /* Don't yet allow changing of symlinks with ALTER TABLE */
 
760
      if (create_info.data_file_name)
 
761
        push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN, 0,
 
762
                     "DATA DIRECTORY option ignored");
 
763
      if (create_info.index_file_name)
 
764
        push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN, 0,
 
765
                     "INDEX DIRECTORY option ignored");
 
766
      create_info.data_file_name= create_info.index_file_name= NULL;
 
767
      /* ALTER TABLE ends previous transaction */
 
768
      if (! session->endActiveTransaction())
 
769
        goto error;
 
770
 
 
771
      if (!(need_start_waiting= !wait_if_global_read_lock(session, 0, 1)))
 
772
      {
 
773
        res= 1;
 
774
        break;
 
775
      }
 
776
 
 
777
      res= mysql_alter_table(session, select_lex->db, lex->name.str,
 
778
                             &create_info,
 
779
                             first_table,
 
780
                             &alter_info,
 
781
                             select_lex->order_list.elements,
 
782
                             (order_st *) select_lex->order_list.first,
 
783
                             lex->ignore);
 
784
      break;
 
785
    }
 
786
  case SQLCOM_RENAME_TABLE:
 
787
  {
 
788
    assert(first_table == all_tables && first_table != 0);
 
789
    TableList *table;
 
790
    for (table= first_table; table; table= table->next_local->next_local)
 
791
    {
 
792
      TableList old_list, new_list;
 
793
      /*
 
794
        we do not need initialize old_list and new_list because we will
 
795
        come table[0] and table->next[0] there
 
796
      */
 
797
      old_list= table[0];
 
798
      new_list= table->next_local[0];
 
799
    }
 
800
 
 
801
    if (! session->endActiveTransaction() || drizzle_rename_tables(session, first_table))
 
802
    {
 
803
      goto error;
 
804
    }
 
805
    break;
 
806
  }
 
807
  case SQLCOM_SHOW_CREATE:
 
808
    assert(first_table == all_tables && first_table != 0);
 
809
    {
 
810
      res= drizzled_show_create(session, first_table);
 
811
      break;
 
812
    }
 
813
  case SQLCOM_CHECKSUM:
 
814
  {
 
815
    assert(first_table == all_tables && first_table != 0);
 
816
    res = mysql_checksum_table(session, first_table, &lex->check_opt);
 
817
    break;
 
818
  }
 
819
  case SQLCOM_CHECK:
 
820
  {
 
821
    assert(first_table == all_tables && first_table != 0);
 
822
    res = mysql_check_table(session, first_table, &lex->check_opt);
 
823
    select_lex->table_list.first= (unsigned char*) first_table;
 
824
    lex->query_tables=all_tables;
 
825
    break;
 
826
  }
 
827
  case SQLCOM_ANALYZE:
 
828
  {
 
829
    assert(first_table == all_tables && first_table != 0);
 
830
    res= mysql_analyze_table(session, first_table, &lex->check_opt);
 
831
    /* ! we write after unlocking the table */
 
832
    write_bin_log(session, true, session->query, session->query_length);
 
833
    select_lex->table_list.first= (unsigned char*) first_table;
 
834
    lex->query_tables=all_tables;
 
835
    break;
 
836
  }
 
837
 
 
838
  case SQLCOM_OPTIMIZE:
 
839
  {
 
840
    assert(first_table == all_tables && first_table != 0);
 
841
    res= mysql_optimize_table(session, first_table, &lex->check_opt);
 
842
    /* ! we write after unlocking the table */
 
843
    write_bin_log(session, true, session->query, session->query_length);
 
844
    select_lex->table_list.first= (unsigned char*) first_table;
 
845
    lex->query_tables=all_tables;
 
846
    break;
 
847
  }
 
848
  case SQLCOM_UPDATE:
 
849
    assert(first_table == all_tables && first_table != 0);
 
850
    if ((res= update_precheck(session, all_tables)))
 
851
      break;
 
852
    assert(select_lex->offset_limit == 0);
 
853
    unit->set_limit(select_lex);
 
854
    res= mysql_update(session, all_tables,
 
855
                      select_lex->item_list,
 
856
                      lex->value_list,
 
857
                      select_lex->where,
 
858
                      select_lex->order_list.elements,
 
859
                      (order_st *) select_lex->order_list.first,
 
860
                      unit->select_limit_cnt,
 
861
                      lex->duplicates, lex->ignore);
 
862
    break;
 
863
  case SQLCOM_UPDATE_MULTI:
 
864
  {
 
865
    assert(first_table == all_tables && first_table != 0);
 
866
    if ((res= update_precheck(session, all_tables)))
 
867
      break;
 
868
 
 
869
    if ((res= mysql_multi_update_prepare(session)))
 
870
      break;
 
871
 
 
872
    res= mysql_multi_update(session, all_tables,
 
873
                            &select_lex->item_list,
 
874
                            &lex->value_list,
 
875
                            select_lex->where,
 
876
                            select_lex->options,
 
877
                            lex->duplicates, lex->ignore, unit, select_lex);
 
878
    break;
 
879
  }
 
880
  case SQLCOM_REPLACE:
 
881
  case SQLCOM_INSERT:
 
882
  {
 
883
    assert(first_table == all_tables && first_table != 0);
 
884
    if ((res= insert_precheck(session, all_tables)))
 
885
      break;
 
886
 
 
887
    if (!(need_start_waiting= !wait_if_global_read_lock(session, 0, 1)))
 
888
    {
 
889
      res= 1;
 
890
      break;
 
891
    }
 
892
 
 
893
    res= mysql_insert(session, all_tables, lex->field_list, lex->many_values,
 
894
                      lex->update_list, lex->value_list,
 
895
                      lex->duplicates, lex->ignore);
 
896
 
 
897
    break;
 
898
  }
 
899
  case SQLCOM_REPLACE_SELECT:
 
900
  case SQLCOM_INSERT_SELECT:
 
901
  {
 
902
    select_result *sel_result;
 
903
    assert(first_table == all_tables && first_table != 0);
 
904
    if ((res= insert_precheck(session, all_tables)))
 
905
      break;
 
906
 
 
907
    /* Don't unlock tables until command is written to binary log */
 
908
    select_lex->options|= SELECT_NO_UNLOCK;
 
909
 
 
910
    unit->set_limit(select_lex);
 
911
 
 
912
    if (! (need_start_waiting= ! wait_if_global_read_lock(session, 0, 1)))
 
913
    {
 
914
      res= 1;
 
915
      break;
 
916
    }
 
917
 
 
918
    if (!(res= session->open_and_lock_tables(all_tables)))
 
919
    {
 
920
      /* Skip first table, which is the table we are inserting in */
 
921
      TableList *second_table= first_table->next_local;
 
922
      select_lex->table_list.first= (unsigned char*) second_table;
 
923
      select_lex->context.table_list=
 
924
        select_lex->context.first_name_resolution_table= second_table;
 
925
      res= mysql_insert_select_prepare(session);
 
926
      if (!res && (sel_result= new select_insert(first_table,
 
927
                                                 first_table->table,
 
928
                                                 &lex->field_list,
 
929
                                                 &lex->update_list,
 
930
                                                 &lex->value_list,
 
931
                                                 lex->duplicates,
 
932
                                                 lex->ignore)))
 
933
      {
 
934
        res= handle_select(session, lex, sel_result, OPTION_SETUP_TABLES_DONE);
 
935
        /*
 
936
          Invalidate the table in the query cache if something changed
 
937
          after unlocking when changes become visible.
 
938
          TODO: this is workaround. right way will be move invalidating in
 
939
          the unlock procedure.
 
940
        */
 
941
        if (first_table->lock_type ==  TL_WRITE_CONCURRENT_INSERT &&
 
942
            session->lock)
 
943
        {
 
944
          /* INSERT ... SELECT should invalidate only the very first table */
 
945
          TableList *save_table= first_table->next_local;
 
946
          first_table->next_local= 0;
 
947
          first_table->next_local= save_table;
 
948
        }
 
949
        delete sel_result;
 
950
      }
 
951
      /* revert changes for SP */
 
952
      select_lex->table_list.first= (unsigned char*) first_table;
 
953
    }
 
954
 
 
955
    break;
 
956
  }
 
957
  case SQLCOM_TRUNCATE:
 
958
    if (! session->endActiveTransaction())
 
959
    {
 
960
      res= -1;
 
961
      break;
 
962
    }
 
963
    assert(first_table == all_tables && first_table != 0);
 
964
    /*
 
965
      Don't allow this within a transaction because we want to use
 
966
      re-generate table
 
967
    */
 
968
    if (session->inTransaction())
 
969
    {
 
970
      my_message(ER_LOCK_OR_ACTIVE_TRANSACTION, ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
 
971
      goto error;
 
972
    }
 
973
 
 
974
    res= mysql_truncate(session, first_table, 0);
 
975
 
 
976
    break;
 
977
  case SQLCOM_DELETE:
 
978
  {
 
979
    assert(first_table == all_tables && first_table != 0);
 
980
    assert(select_lex->offset_limit == 0);
 
981
    unit->set_limit(select_lex);
 
982
 
 
983
    if (!(need_start_waiting= !wait_if_global_read_lock(session, 0, 1)))
 
984
    {
 
985
      res= 1;
 
986
      break;
 
987
    }
 
988
 
 
989
    res = mysql_delete(session, all_tables, select_lex->where,
 
990
                       &select_lex->order_list,
 
991
                       unit->select_limit_cnt, select_lex->options,
 
992
                       false);
 
993
    break;
 
994
  }
 
995
  case SQLCOM_DELETE_MULTI:
 
996
  {
 
997
    assert(first_table == all_tables && first_table != 0);
 
998
    TableList *aux_tables=
 
999
      (TableList *)session->lex->auxiliary_table_list.first;
 
1000
    multi_delete *del_result;
 
1001
 
 
1002
    if (!(need_start_waiting= !wait_if_global_read_lock(session, 0, 1)))
 
1003
    {
 
1004
      res= 1;
 
1005
      break;
 
1006
    }
 
1007
 
 
1008
    if ((res= multi_delete_precheck(session, all_tables)))
 
1009
      break;
 
1010
 
 
1011
    /* condition will be true on SP re-excuting */
 
1012
    if (select_lex->item_list.elements != 0)
 
1013
      select_lex->item_list.empty();
 
1014
    if (session->add_item_to_list(new Item_null()))
 
1015
      goto error;
 
1016
 
 
1017
    session->set_proc_info("init");
 
1018
    if ((res= session->open_and_lock_tables(all_tables)))
 
1019
      break;
 
1020
 
 
1021
    if ((res= mysql_multi_delete_prepare(session)))
 
1022
      goto error;
 
1023
 
 
1024
    if (!session->is_fatal_error &&
 
1025
        (del_result= new multi_delete(aux_tables, lex->table_count)))
 
1026
    {
 
1027
      res= mysql_select(session, &select_lex->ref_pointer_array,
 
1028
                        select_lex->get_table_list(),
 
1029
                        select_lex->with_wild,
 
1030
                        select_lex->item_list,
 
1031
                        select_lex->where,
 
1032
                        0, (order_st *)NULL, (order_st *)NULL, (Item *)NULL,
 
1033
                        select_lex->options | session->options | SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK | OPTION_SETUP_TABLES_DONE,
 
1034
                        del_result, unit, select_lex);
 
1035
      res|= session->is_error();
 
1036
      if (res)
 
1037
        del_result->abort();
 
1038
      delete del_result;
 
1039
    }
 
1040
    else
 
1041
      res= true;                                // Error
 
1042
    break;
 
1043
  }
 
1044
  case SQLCOM_DROP_TABLE:
 
1045
  {
 
1046
    assert(first_table == all_tables && first_table != 0);
 
1047
    if (!lex->drop_temporary)
 
1048
    {
 
1049
      if (! session->endActiveTransaction())
 
1050
        goto error;
 
1051
    }
 
1052
    else
 
1053
    {
 
1054
      /* So that DROP TEMPORARY TABLE gets to binlog at commit/rollback */
 
1055
      session->options|= OPTION_KEEP_LOG;
 
1056
    }
 
1057
    /* DDL and binlog write order protected by LOCK_open */
 
1058
    res= mysql_rm_table(session, first_table, lex->drop_if_exists, lex->drop_temporary);
 
1059
  }
 
1060
  break;
 
1061
  case SQLCOM_SHOW_PROCESSLIST:
 
1062
    mysqld_list_processes(session, NULL, lex->verbose);
 
1063
    break;
 
1064
  case SQLCOM_CHANGE_DB:
 
1065
  {
 
1066
    LEX_STRING db_str= { (char *) select_lex->db, strlen(select_lex->db) };
 
1067
 
 
1068
    if (!mysql_change_db(session, &db_str, false))
 
1069
      session->my_ok();
 
1070
 
 
1071
    break;
 
1072
  }
 
1073
 
 
1074
  case SQLCOM_LOAD:
 
1075
  {
 
1076
    assert(first_table == all_tables && first_table != 0);
 
1077
    res= mysql_load(session, lex->exchange, first_table, lex->field_list,
 
1078
                    lex->update_list, lex->value_list, lex->duplicates, lex->ignore);
 
1079
    break;
 
1080
  }
 
1081
 
 
1082
  case SQLCOM_SET_OPTION:
 
1083
  {
 
1084
    List<set_var_base> *lex_var_list= &lex->var_list;
 
1085
 
 
1086
    if (session->open_and_lock_tables(all_tables))
 
1087
      goto error;
 
1088
    if (!(res= sql_set_variables(session, lex_var_list)))
 
1089
    {
 
1090
      session->my_ok();
 
1091
    }
 
1092
    else
 
1093
    {
 
1094
      /*
 
1095
        We encountered some sort of error, but no message was sent.
 
1096
        Send something semi-generic here since we don't know which
 
1097
        assignment in the list caused the error.
 
1098
      */
 
1099
      if (!session->is_error())
 
1100
        my_error(ER_WRONG_ARGUMENTS,MYF(0),"SET");
 
1101
      goto error;
 
1102
    }
 
1103
 
 
1104
    break;
 
1105
  }
 
1106
 
 
1107
  case SQLCOM_UNLOCK_TABLES:
 
1108
    /*
 
1109
      It is critical for mysqldump --single-transaction --master-data that
 
1110
      UNLOCK TABLES does not implicitely commit a connection which has only
 
1111
      done FLUSH TABLES WITH READ LOCK + BEGIN. If this assumption becomes
 
1112
      false, mysqldump will not work.
 
1113
    */
 
1114
    if (session->global_read_lock)
 
1115
      unlock_global_read_lock(session);
 
1116
    session->my_ok();
 
1117
    break;
 
1118
  case SQLCOM_CREATE_DB:
 
1119
  {
 
1120
    /*
 
1121
      As mysql_create_db() may modify HA_CREATE_INFO structure passed to
 
1122
      it, we need to use a copy of LEX::create_info to make execution
 
1123
      prepared statement- safe.
 
1124
    */
 
1125
    HA_CREATE_INFO create_info(lex->create_info);
 
1126
    if (! session->endActiveTransaction())
 
1127
    {
 
1128
      res= -1;
 
1129
      break;
 
1130
    }
 
1131
    char *alias;
 
1132
    if (!(alias=session->strmake(lex->name.str, lex->name.length)) ||
 
1133
        check_db_name(&lex->name))
 
1134
    {
 
1135
      my_error(ER_WRONG_DB_NAME, MYF(0), lex->name.str);
 
1136
      break;
 
1137
    }
 
1138
    res= mysql_create_db(session,(lex->name.str), &create_info);
 
1139
    break;
 
1140
  }
 
1141
  case SQLCOM_DROP_DB:
 
1142
  {
 
1143
    if (! session->endActiveTransaction())
 
1144
    {
 
1145
      res= -1;
 
1146
      break;
 
1147
    }
 
1148
    if (check_db_name(&lex->name))
 
1149
    {
 
1150
      my_error(ER_WRONG_DB_NAME, MYF(0), lex->name.str);
 
1151
      break;
 
1152
    }
 
1153
    if (session->inTransaction())
 
1154
    {
 
1155
      my_message(ER_LOCK_OR_ACTIVE_TRANSACTION, ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
 
1156
      goto error;
 
1157
    }
 
1158
    res= mysql_rm_db(session, lex->name.str, lex->drop_if_exists);
 
1159
    break;
 
1160
  }
 
1161
  case SQLCOM_ALTER_DB:
 
1162
  {
 
1163
    LEX_STRING *db= &lex->name;
 
1164
    HA_CREATE_INFO create_info(lex->create_info);
 
1165
    if (check_db_name(db))
 
1166
    {
 
1167
      my_error(ER_WRONG_DB_NAME, MYF(0), db->str);
 
1168
      break;
 
1169
    }
 
1170
    if (session->inTransaction())
 
1171
    {
 
1172
      my_message(ER_LOCK_OR_ACTIVE_TRANSACTION, ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
 
1173
      goto error;
 
1174
    }
 
1175
    res= mysql_alter_db(session, db->str, &create_info);
 
1176
    break;
 
1177
  }
 
1178
  case SQLCOM_SHOW_CREATE_DB:
 
1179
  {
 
1180
    if (check_db_name(&lex->name))
 
1181
    {
 
1182
      my_error(ER_WRONG_DB_NAME, MYF(0), lex->name.str);
 
1183
      break;
 
1184
    }
 
1185
    res= mysqld_show_create_db(session, lex->name.str, &lex->create_info);
 
1186
    break;
 
1187
  }
 
1188
  case SQLCOM_FLUSH:
 
1189
  {
 
1190
    /*
 
1191
      reload_cache() will tell us if we are allowed to write to the
 
1192
      binlog or not.
 
1193
    */
 
1194
    if (!reload_cache(session, lex->type, first_table))
 
1195
    {
 
1196
      /*
 
1197
        We WANT to write and we CAN write.
 
1198
        ! we write after unlocking the table.
 
1199
      */
 
1200
      /*
 
1201
        Presumably, RESET and binlog writing doesn't require synchronization
 
1202
      */
 
1203
      write_bin_log(session, false, session->query, session->query_length);
 
1204
      session->my_ok();
 
1205
    }
 
1206
 
 
1207
    break;
 
1208
  }
 
1209
  case SQLCOM_KILL:
 
1210
  {
 
1211
    Item *it= (Item *)lex->value_list.head();
 
1212
 
 
1213
    if ((!it->fixed && it->fix_fields(lex->session, &it)) || it->check_cols(1))
 
1214
    {
 
1215
      my_message(ER_SET_CONSTANTS_ONLY, ER(ER_SET_CONSTANTS_ONLY),
 
1216
                 MYF(0));
 
1217
      goto error;
 
1218
    }
 
1219
    sql_kill(session, (ulong)it->val_int(), lex->type & ONLY_KILL_QUERY);
 
1220
    break;
 
1221
  }
 
1222
  case SQLCOM_BEGIN:
 
1223
    if (session->transaction.xid_state.xa_state != XA_NOTR)
 
1224
    {
 
1225
      my_error(ER_XAER_RMFAIL, MYF(0),
 
1226
               xa_state_names[session->transaction.xid_state.xa_state]);
 
1227
      break;
 
1228
    }
 
1229
    /*
 
1230
      Breakpoints for backup testing.
 
1231
    */
 
1232
    if (! session->startTransaction())
 
1233
      goto error;
 
1234
    session->my_ok();
 
1235
    break;
 
1236
  case SQLCOM_COMMIT:
 
1237
    if (! session->endTransaction(lex->tx_release ? COMMIT_RELEASE : lex->tx_chain ? COMMIT_AND_CHAIN : COMMIT))
 
1238
      goto error;
 
1239
    session->my_ok();
 
1240
    break;
 
1241
  case SQLCOM_ROLLBACK:
 
1242
    if (! session->endTransaction(lex->tx_release ? ROLLBACK_RELEASE : lex->tx_chain ? ROLLBACK_AND_CHAIN : ROLLBACK))
 
1243
      goto error;
 
1244
    session->my_ok();
 
1245
    break;
 
1246
  case SQLCOM_RELEASE_SAVEPOINT:
 
1247
  {
 
1248
    SAVEPOINT *sv;
 
1249
    for (sv=session->transaction.savepoints; sv; sv=sv->prev)
 
1250
    {
 
1251
      if (my_strnncoll(system_charset_info,
 
1252
                       (unsigned char *)lex->ident.str, lex->ident.length,
 
1253
                       (unsigned char *)sv->name, sv->length) == 0)
 
1254
        break;
 
1255
    }
 
1256
    if (sv)
 
1257
    {
 
1258
      if (ha_release_savepoint(session, sv))
 
1259
        res= true; // cannot happen
 
1260
      else
 
1261
        session->my_ok();
 
1262
      session->transaction.savepoints=sv->prev;
 
1263
    }
 
1264
    else
 
1265
      my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "SAVEPOINT", lex->ident.str);
 
1266
    break;
 
1267
  }
 
1268
  case SQLCOM_ROLLBACK_TO_SAVEPOINT:
 
1269
  {
 
1270
    SAVEPOINT *sv;
 
1271
    for (sv=session->transaction.savepoints; sv; sv=sv->prev)
 
1272
    {
 
1273
      if (my_strnncoll(system_charset_info,
 
1274
                       (unsigned char *)lex->ident.str, lex->ident.length,
 
1275
                       (unsigned char *)sv->name, sv->length) == 0)
 
1276
        break;
 
1277
    }
 
1278
    if (sv)
 
1279
    {
 
1280
      if (ha_rollback_to_savepoint(session, sv))
 
1281
        res= true; // cannot happen
 
1282
      else
 
1283
      {
 
1284
        if ((session->options & OPTION_KEEP_LOG) || session->transaction.all.modified_non_trans_table)
 
1285
          push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
1286
                       ER_WARNING_NOT_COMPLETE_ROLLBACK,
 
1287
                       ER(ER_WARNING_NOT_COMPLETE_ROLLBACK));
 
1288
        session->my_ok();
 
1289
      }
 
1290
      session->transaction.savepoints=sv;
 
1291
    }
 
1292
    else
 
1293
      my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "SAVEPOINT", lex->ident.str);
 
1294
    break;
 
1295
  }
 
1296
  case SQLCOM_SAVEPOINT:
 
1297
    if (!(session->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))
 
1298
      session->my_ok();
 
1299
    else
 
1300
    {
 
1301
      SAVEPOINT **sv, *newsv;
 
1302
      for (sv=&session->transaction.savepoints; *sv; sv=&(*sv)->prev)
 
1303
      {
 
1304
        if (my_strnncoll(system_charset_info,
 
1305
                         (unsigned char *)lex->ident.str, lex->ident.length,
 
1306
                         (unsigned char *)(*sv)->name, (*sv)->length) == 0)
 
1307
          break;
 
1308
      }
 
1309
      if (*sv) /* old savepoint of the same name exists */
 
1310
      {
 
1311
        newsv=*sv;
 
1312
        ha_release_savepoint(session, *sv); // it cannot fail
 
1313
        *sv=(*sv)->prev;
 
1314
      }
 
1315
      else if ((newsv=(SAVEPOINT *) alloc_root(&session->transaction.mem_root,
 
1316
                                               savepoint_alloc_size)) == 0)
 
1317
      {
 
1318
        my_error(ER_OUT_OF_RESOURCES, MYF(0));
 
1319
        break;
 
1320
      }
 
1321
      newsv->name=strmake_root(&session->transaction.mem_root,
 
1322
                               lex->ident.str, lex->ident.length);
 
1323
      newsv->length=lex->ident.length;
 
1324
      /*
 
1325
        if we'll get an error here, don't add new savepoint to the list.
 
1326
        we'll lose a little bit of memory in transaction mem_root, but it'll
 
1327
        be free'd when transaction ends anyway
 
1328
      */
 
1329
      if (ha_savepoint(session, newsv))
 
1330
        res= true;
 
1331
      else
 
1332
      {
 
1333
        newsv->prev=session->transaction.savepoints;
 
1334
        session->transaction.savepoints=newsv;
 
1335
        session->my_ok();
 
1336
      }
 
1337
    }
 
1338
    break;
 
1339
  default:
 
1340
    assert(0);                             /* Impossible */
 
1341
    session->my_ok();
 
1342
    break;
 
1343
  }
483
1344
  session->set_proc_info("query end");
484
1345
 
485
1346
  /*
488
1349
    wants. We also keep the last value in case of SQLCOM_CALL or
489
1350
    SQLCOM_EXECUTE.
490
1351
  */
491
 
  if (! (sql_command_flags[lex->sql_command].test(CF_BIT_HAS_ROW_COUNT)))
492
 
  {
 
1352
  if (!(sql_command_flags[lex->sql_command].test(CF_BIT_HAS_ROW_COUNT)))
493
1353
    session->row_count_func= -1;
 
1354
 
 
1355
  goto finish;
 
1356
 
 
1357
error:
 
1358
  res= true;
 
1359
 
 
1360
finish:
 
1361
  if (need_start_waiting)
 
1362
  {
 
1363
    /*
 
1364
      Release the protection against the global read lock and wake
 
1365
      everyone, who might want to set a global read lock.
 
1366
    */
 
1367
    start_waiting_global_read_lock(session);
494
1368
  }
495
 
 
496
 
  return (res || session->is_error());
 
1369
  return(res || session->is_error());
497
1370
}
498
1371
 
499
1372
bool execute_sqlcom_select(Session *session, TableList *all_tables)
508
1381
      param->select_limit=
509
1382
        new Item_int((uint64_t) session->variables.select_limit);
510
1383
  }
511
 
  if (not (res= session->openTablesLock(all_tables)))
 
1384
  if (!(res= session->open_and_lock_tables(all_tables)))
512
1385
  {
513
1386
    if (lex->describe)
514
1387
    {
519
1392
        even if the query itself redirects the output.
520
1393
      */
521
1394
      if (!(result= new select_send()))
522
 
        return true;
 
1395
        return true;                               /* purecov: inspected */
523
1396
      session->send_explain_fields(result);
524
 
      optimizer::ExplainPlan planner;
525
 
      res= planner.explainUnion(session, &session->lex->unit, result);
 
1397
      res= mysql_explain_union(session, &session->lex->unit, result);
526
1398
      if (lex->describe & DESCRIBE_EXTENDED)
527
1399
      {
528
1400
        char buff[1024];
542
1414
    else
543
1415
    {
544
1416
      if (!result && !(result= new select_send()))
545
 
        return true;
 
1417
        return true;                               /* purecov: inspected */
546
1418
      res= handle_select(session, lex, result, 0);
547
1419
      if (result != lex->result)
548
1420
        delete result;
697
1569
  */
698
1570
  if ((var= get_system_var(session, OPT_SESSION, tmp, null_lex_string)))
699
1571
  {
700
 
    end+= snprintf(buff, sizeof(buff), "@@session.%s", var_name);
 
1572
    end+= sprintf(buff, "@@session.%s", var_name);
701
1573
    var->set_name(buff, end-buff, system_charset_info);
702
1574
    session->add_item_to_list(var);
703
1575
  }
705
1577
}
706
1578
 
707
1579
 
 
1580
void mysql_init_multi_delete(LEX *lex)
 
1581
{
 
1582
  lex->sql_command=  SQLCOM_DELETE_MULTI;
 
1583
  mysql_init_select(lex);
 
1584
  lex->select_lex.select_limit= 0;
 
1585
  lex->unit.select_limit_cnt= HA_POS_ERROR;
 
1586
  lex->select_lex.table_list.save_and_clear(&lex->auxiliary_table_list);
 
1587
  lex->lock_option= TL_READ;
 
1588
  lex->query_tables= 0;
 
1589
  lex->query_tables_last= &lex->query_tables;
 
1590
}
 
1591
 
 
1592
 
708
1593
/**
709
1594
  Parse a query.
710
1595
 
711
1596
  @param       session     Current thread
712
1597
  @param       inBuf   Begining of the query text
713
1598
  @param       length  Length of the query text
 
1599
  @param[out]  found_semicolon For multi queries, position of the character of
 
1600
                               the next query in the query text.
714
1601
*/
715
1602
 
716
 
void mysql_parse(Session *session, const char *inBuf, uint32_t length)
 
1603
void mysql_parse(Session *session, const char *inBuf, uint32_t length,
 
1604
                 const char ** found_semicolon)
717
1605
{
 
1606
  /*
 
1607
    Warning.
 
1608
    The purpose of query_cache_send_result_to_client() is to lookup the
 
1609
    query in the query cache first, to avoid parsing and executing it.
 
1610
    So, the natural implementation would be to:
 
1611
    - first, call query_cache_send_result_to_client,
 
1612
    - second, if caching failed, initialise the lexical and syntactic parser.
 
1613
    The problem is that the query cache depends on a clean initialization
 
1614
    of (among others) lex->safe_to_cache_query and session->server_status,
 
1615
    which are reset respectively in
 
1616
    - lex_start()
 
1617
    - mysql_reset_session_for_next_command()
 
1618
    So, initializing the lexical analyser *before* using the query cache
 
1619
    is required for the cache to work properly.
 
1620
    FIXME: cleanup the dependencies in the code to simplify this.
 
1621
  */
718
1622
  lex_start(session);
719
1623
  session->reset_for_next_command();
720
1624
 
721
 
  LEX *lex= session->lex;
722
 
 
723
 
  Lex_input_stream lip(session, inBuf, length);
724
 
 
725
 
  bool err= parse_sql(session, &lip);
726
 
 
727
 
  if (!err)
728
1625
  {
 
1626
    LEX *lex= session->lex;
 
1627
 
 
1628
    Lex_input_stream lip(session, inBuf, length);
 
1629
 
 
1630
    bool err= parse_sql(session, &lip);
 
1631
    *found_semicolon= lip.found_semicolon;
 
1632
 
 
1633
    if (!err)
729
1634
    {
730
 
      if (! session->is_error())
731
1635
      {
732
 
        DRIZZLE_QUERY_EXEC_START(session->query.c_str(),
733
 
                                 session->thread_id,
734
 
                                 const_cast<const char *>(session->db.empty() ? "" : session->db.c_str()));
735
 
        /* Actually execute the query */
736
 
        mysql_execute_command(session);
737
 
        DRIZZLE_QUERY_EXEC_DONE(0);
 
1636
        if (! session->is_error())
 
1637
        {
 
1638
          /*
 
1639
            Binlog logs a string starting from session->query and having length
 
1640
            session->query_length; so we set session->query_length correctly (to not
 
1641
            log several statements in one event, when we executed only first).
 
1642
            We set it to not see the ';' (otherwise it would get into binlog
 
1643
            and Query_log_event::print() would give ';;' output).
 
1644
            This also helps display only the current query in SHOW
 
1645
            PROCESSLIST.
 
1646
            Note that we don't need LOCK_thread_count to modify query_length.
 
1647
          */
 
1648
          if (*found_semicolon &&
 
1649
              (session->query_length= (ulong)(*found_semicolon - session->query)))
 
1650
            session->query_length--;
 
1651
          /* Actually execute the query */
 
1652
          mysql_execute_command(session);
 
1653
        }
738
1654
      }
739
1655
    }
740
 
  }
741
 
  else
742
 
  {
743
 
    assert(session->is_error());
744
 
  }
745
 
 
746
 
  lex->unit.cleanup();
747
 
  session->set_proc_info("freeing items");
748
 
  session->end_statement();
749
 
  session->cleanup_after_query();
 
1656
    else
 
1657
    {
 
1658
      assert(session->is_error());
 
1659
    }
 
1660
    lex->unit.cleanup();
 
1661
    session->set_proc_info("freeing items");
 
1662
    session->end_statement();
 
1663
    session->cleanup_after_query();
 
1664
  }
750
1665
 
751
1666
  return;
752
1667
}
771
1686
{
772
1687
  register CreateField *new_field;
773
1688
  LEX  *lex= session->lex;
774
 
  statement::AlterTable *statement= (statement::AlterTable *)lex->statement;
775
1689
 
776
1690
  if (check_identifier_name(field_name, ER_TOO_LONG_IDENT))
777
 
    return true;
 
1691
    return(1);                          /* purecov: inspected */
778
1692
 
779
1693
  if (type_modifier & PRI_KEY_FLAG)
780
1694
  {
783
1697
    key= new Key(Key::PRIMARY, null_lex_str,
784
1698
                      &default_key_create_info,
785
1699
                      0, lex->col_list);
786
 
    statement->alter_info.key_list.push_back(key);
 
1700
    lex->alter_info.key_list.push_back(key);
787
1701
    lex->col_list.empty();
788
1702
  }
789
1703
  if (type_modifier & (UNIQUE_FLAG | UNIQUE_KEY_FLAG))
793
1707
    key= new Key(Key::UNIQUE, null_lex_str,
794
1708
                 &default_key_create_info, 0,
795
1709
                 lex->col_list);
796
 
    statement->alter_info.key_list.push_back(key);
 
1710
    lex->alter_info.key_list.push_back(key);
797
1711
    lex->col_list.empty();
798
1712
  }
799
1713
 
811
1725
         type == DRIZZLE_TYPE_TIMESTAMP))
812
1726
    {
813
1727
      my_error(ER_INVALID_DEFAULT, MYF(0), field_name->str);
814
 
      return true;
 
1728
      return(1);
815
1729
    }
816
1730
    else if (default_value->type() == Item::NULL_ITEM)
817
1731
    {
820
1734
          NOT_NULL_FLAG)
821
1735
      {
822
1736
        my_error(ER_INVALID_DEFAULT, MYF(0), field_name->str);
823
 
        return true;
 
1737
        return(1);
824
1738
      }
825
1739
    }
826
1740
    else if (type_modifier & AUTO_INCREMENT_FLAG)
827
1741
    {
828
1742
      my_error(ER_INVALID_DEFAULT, MYF(0), field_name->str);
829
 
      return true;
 
1743
      return(1);
830
1744
    }
831
1745
  }
832
1746
 
833
1747
  if (on_update_value && type != DRIZZLE_TYPE_TIMESTAMP)
834
1748
  {
835
1749
    my_error(ER_INVALID_ON_UPDATE, MYF(0), field_name->str);
836
 
    return true;
 
1750
    return(1);
837
1751
  }
838
1752
 
839
1753
  if (!(new_field= new CreateField()) ||
840
1754
      new_field->init(session, field_name->str, type, length, decimals, type_modifier,
841
1755
                      default_value, on_update_value, comment, change,
842
1756
                      interval_list, cs, 0, column_format))
843
 
    return true;
 
1757
    return(1);
844
1758
 
845
 
  statement->alter_info.create_list.push_back(new_field);
 
1759
  lex->alter_info.create_list.push_back(new_field);
846
1760
  lex->last_field=new_field;
847
 
 
848
 
  return false;
 
1761
  return(0);
849
1762
}
850
1763
 
851
1764
 
857
1770
}
858
1771
 
859
1772
/**
 
1773
  save order by and tables in own lists.
 
1774
*/
 
1775
 
 
1776
bool add_to_list(Session *session, SQL_LIST &list,Item *item,bool asc)
 
1777
{
 
1778
  order_st *order;
 
1779
  if (!(order = (order_st *) session->alloc(sizeof(order_st))))
 
1780
    return(1);
 
1781
  order->item_ptr= item;
 
1782
  order->item= &order->item_ptr;
 
1783
  order->asc = asc;
 
1784
  order->free_me=0;
 
1785
  order->used=0;
 
1786
  order->counter_used= 0;
 
1787
  list.link_in_list((unsigned char*) order,(unsigned char**) &order->next);
 
1788
  return(0);
 
1789
}
 
1790
 
 
1791
 
 
1792
/**
860
1793
  Add a table to list of used tables.
861
1794
 
862
1795
  @param table          Table to add
898
1831
    return NULL;
899
1832
  }
900
1833
 
901
 
  if (table->is_derived_table() == false && table->db.str)
 
1834
  if (table->is_derived_table() == false && table->db.str &&
 
1835
      check_db_name(&table->db))
902
1836
  {
903
 
    my_casedn_str(files_charset_info, table->db.str);
904
 
 
905
 
    SchemaIdentifier schema_identifier(string(table->db.str, table->db.length));
906
 
    if (not check_db_name(schema_identifier))
907
 
    {
908
 
 
909
 
      my_error(ER_WRONG_DB_NAME, MYF(0), table->db.str);
910
 
      return NULL;
911
 
    }
 
1837
    my_error(ER_WRONG_DB_NAME, MYF(0), table->db.str);
 
1838
    return NULL;
912
1839
  }
913
1840
 
914
1841
  if (!alias)                                   /* Alias is case sensitive */
923
1850
      return NULL;
924
1851
  }
925
1852
  if (!(ptr = (TableList *) session->calloc(sizeof(TableList))))
926
 
    return NULL;
 
1853
    return NULL;                                /* purecov: inspected */
927
1854
  if (table->db.str)
928
1855
  {
929
1856
    ptr->is_fqtn= true;
942
1869
  ptr->table_name=table->table.str;
943
1870
  ptr->table_name_length=table->table.length;
944
1871
  ptr->lock_type=   lock_type;
 
1872
  ptr->updating=    test(table_options & TL_OPTION_UPDATING);
945
1873
  ptr->force_index= test(table_options & TL_OPTION_FORCE_INDEX);
946
1874
  ptr->ignore_leaves= test(table_options & TL_OPTION_IGNORE_LEAVES);
947
1875
  ptr->derived=     table->sel;
 
1876
  if (!ptr->derived && !my_strcasecmp(system_charset_info, ptr->db,
 
1877
                                      INFORMATION_SCHEMA_NAME.c_str()))
 
1878
  {
 
1879
    InfoSchemaTable *schema_table= find_schema_table(ptr->table_name);
 
1880
    if (!schema_table ||
 
1881
        (schema_table->isHidden() &&
 
1882
         ((sql_command_flags[lex->sql_command].test(CF_BIT_STATUS_COMMAND)) == 0 ||
 
1883
          /*
 
1884
            this check is used for show columns|keys from I_S hidden table
 
1885
          */
 
1886
          lex->sql_command == SQLCOM_SHOW_FIELDS ||
 
1887
          lex->sql_command == SQLCOM_SHOW_KEYS)))
 
1888
    {
 
1889
      my_error(ER_UNKNOWN_TABLE, MYF(0),
 
1890
               ptr->table_name, INFORMATION_SCHEMA_NAME.c_str());
 
1891
      return NULL;
 
1892
    }
 
1893
    ptr->schema_table_name= ptr->table_name;
 
1894
    ptr->schema_table= schema_table;
 
1895
  }
948
1896
  ptr->select_lex=  lex->current_select;
949
1897
  ptr->index_hints= index_hints_arg;
950
1898
  ptr->option= option ? option->str : 0;
957
1905
         tables=tables->next_local)
958
1906
    {
959
1907
      if (!my_strcasecmp(table_alias_charset, alias_str, tables->alias) &&
960
 
          !strcasecmp(ptr->db, tables->db))
 
1908
          !strcmp(ptr->db, tables->db))
961
1909
      {
962
 
        my_error(ER_NONUNIQ_TABLE, MYF(0), alias_str);
963
 
        return NULL;
 
1910
        my_error(ER_NONUNIQ_TABLE, MYF(0), alias_str); /* purecov: tested */
 
1911
        return NULL;                            /* purecov: tested */
964
1912
      }
965
1913
    }
966
1914
  }
1214
2162
 
1215
2163
void Select_Lex::set_lock_for_tables(thr_lock_type lock_type)
1216
2164
{
 
2165
  bool for_update= lock_type >= TL_READ_NO_INSERT;
 
2166
 
1217
2167
  for (TableList *tables= (TableList*) table_list.first;
1218
2168
       tables;
1219
2169
       tables= tables->next_local)
1220
2170
  {
1221
2171
    tables->lock_type= lock_type;
 
2172
    tables->updating=  for_update;
1222
2173
  }
 
2174
  return;
1223
2175
}
1224
2176
 
1225
2177
 
1230
2182
    This object is created for any union construct containing a union
1231
2183
    operation and also for any single select union construct of the form
1232
2184
    @verbatim
1233
 
    (SELECT ... ORDER BY order_list [LIMIT n]) ORDER BY ...
 
2185
    (SELECT ... order_st BY order_list [LIMIT n]) order_st BY ...
1234
2186
    @endvarbatim
1235
2187
    or of the form
1236
2188
    @varbatim
1237
 
    (SELECT ... ORDER BY LIMIT n) ORDER BY ...
 
2189
    (SELECT ... order_st BY LIMIT n) order_st BY ...
1238
2190
    @endvarbatim
1239
2191
 
1240
2192
  @param session_arg               thread handle
1265
2217
  fake_select_lex->select_limit= 0;
1266
2218
 
1267
2219
  fake_select_lex->context.outer_context=first_sl->context.outer_context;
1268
 
  /* allow item list resolving in fake select for ORDER BY */
 
2220
  /* allow item list resolving in fake select for order_st BY */
1269
2221
  fake_select_lex->context.resolve_in_select_list= true;
1270
2222
  fake_select_lex->context.select_lex= fake_select_lex;
1271
2223
 
1273
2225
  {
1274
2226
    /*
1275
2227
      This works only for
1276
 
      (SELECT ... ORDER BY list [LIMIT n]) ORDER BY order_list [LIMIT m],
1277
 
      (SELECT ... LIMIT n) ORDER BY order_list [LIMIT m]
 
2228
      (SELECT ... order_st BY list [LIMIT n]) order_st BY order_list [LIMIT m],
 
2229
      (SELECT ... LIMIT n) order_st BY order_list [LIMIT m]
1278
2230
      just before the parser starts processing order_list
1279
2231
    */
1280
2232
    global_parameters= fake_select_lex;
1397
2349
 
1398
2350
 
1399
2351
/**
 
2352
  Reload/resets privileges and the different caches.
 
2353
 
 
2354
  @param session Thread handler (can be NULL!)
 
2355
  @param options What should be reset/reloaded (tables, privileges, slave...)
 
2356
  @param tables Tables to flush (if any)
 
2357
  @param write_to_binlog True if we can write to the binlog.
 
2358
 
 
2359
  @note Depending on 'options', it may be very bad to write the
 
2360
    query to the binlog (e.g. FLUSH SLAVE); this is a
 
2361
    pointer where reload_cache() will put 0 if
 
2362
    it thinks we really should not write to the binlog.
 
2363
    Otherwise it will put 1.
 
2364
 
 
2365
  @return Error status code
 
2366
    @retval 0 Ok
 
2367
    @retval !=0  Error; session->killed is set or session->is_error() is true
 
2368
*/
 
2369
 
 
2370
bool reload_cache(Session *session, ulong options, TableList *tables)
 
2371
{
 
2372
  bool result=0;
 
2373
 
 
2374
  if (options & REFRESH_LOG)
 
2375
  {
 
2376
    if (ha_flush_logs(NULL))
 
2377
      result=1;
 
2378
  }
 
2379
  /*
 
2380
    Note that if REFRESH_READ_LOCK bit is set then REFRESH_TABLES is set too
 
2381
    (see sql_yacc.yy)
 
2382
  */
 
2383
  if (options & (REFRESH_TABLES | REFRESH_READ_LOCK))
 
2384
  {
 
2385
    if ((options & REFRESH_READ_LOCK) && session)
 
2386
    {
 
2387
      if (lock_global_read_lock(session))
 
2388
        return true;                               // Killed
 
2389
      result= close_cached_tables(session, tables, (options & REFRESH_FAST) ?
 
2390
                                  false : true, true);
 
2391
      if (make_global_read_lock_block_commit(session)) // Killed
 
2392
      {
 
2393
        /* Don't leave things in a half-locked state */
 
2394
        unlock_global_read_lock(session);
 
2395
 
 
2396
        return true;
 
2397
      }
 
2398
    }
 
2399
    else
 
2400
      result= close_cached_tables(session, tables, (options & REFRESH_FAST) ?
 
2401
                                  false : true, false);
 
2402
  }
 
2403
  if (session && (options & REFRESH_STATUS))
 
2404
    session->refresh_status();
 
2405
 
 
2406
 return result;
 
2407
}
 
2408
 
 
2409
 
 
2410
/**
1400
2411
  kill on thread.
1401
2412
 
1402
2413
  @param session                        Thread class
1411
2422
kill_one_thread(Session *, ulong id, bool only_kill_query)
1412
2423
{
1413
2424
  Session *tmp= NULL;
1414
 
  uint32_t error= ER_NO_SUCH_THREAD;
 
2425
  uint32_t error=ER_NO_SUCH_THREAD;
1415
2426
  pthread_mutex_lock(&LOCK_thread_count); // For unlink from list
1416
2427
  
1417
 
  for (SessionList::iterator it= getSessionList().begin(); it != getSessionList().end(); ++it )
 
2428
  for( vector<Session*>::iterator it= session_list.begin(); it != session_list.end(); ++it )
1418
2429
  {
1419
2430
    if ((*it)->thread_id == id)
1420
2431
    {
1426
2437
  pthread_mutex_unlock(&LOCK_thread_count);
1427
2438
  if (tmp)
1428
2439
  {
1429
 
 
1430
 
    if (tmp->isViewable())
1431
 
    {
1432
 
      tmp->awake(only_kill_query ? Session::KILL_QUERY : Session::KILL_CONNECTION);
1433
 
      error= 0;
1434
 
    }
1435
 
 
 
2440
    tmp->awake(only_kill_query ? Session::KILL_QUERY : Session::KILL_CONNECTION);
 
2441
    error=0;
1436
2442
    pthread_mutex_unlock(&tmp->LOCK_delete);
1437
2443
  }
1438
2444
  return(error);
1459
2465
}
1460
2466
 
1461
2467
 
 
2468
/** If pointer is not a null pointer, append filename to it. */
 
2469
 
 
2470
static bool append_file_to_dir(Session *session, const char **filename_ptr,
 
2471
                               const char *table_name)
 
2472
{
 
2473
  char buff[FN_REFLEN],*ptr, *end;
 
2474
  if (!*filename_ptr)
 
2475
    return 0;                                   // nothing to do
 
2476
 
 
2477
  /* Check that the filename is not too long and it's a hard path */
 
2478
  if (strlen(*filename_ptr)+strlen(table_name) >= FN_REFLEN-1 ||
 
2479
      !test_if_hard_path(*filename_ptr))
 
2480
  {
 
2481
    my_error(ER_WRONG_TABLE_NAME, MYF(0), *filename_ptr);
 
2482
    return 1;
 
2483
  }
 
2484
  /* Fix is using unix filename format on dos */
 
2485
  strcpy(buff,*filename_ptr);
 
2486
  end=convert_dirname(buff, *filename_ptr, NULL);
 
2487
  if (!(ptr= (char*) session->alloc((size_t) (end-buff) + strlen(table_name)+1)))
 
2488
    return 1;                                   // End of memory
 
2489
  *filename_ptr=ptr;
 
2490
  sprintf(ptr,"%s%s",buff,table_name);
 
2491
  return 0;
 
2492
}
 
2493
 
 
2494
 
1462
2495
/**
1463
2496
  Check if the select is a simple select (not an union).
1464
2497
 
1556
2589
  return(false);
1557
2590
}
1558
2591
 
 
2592
/**
 
2593
  Multi delete query pre-check.
 
2594
 
 
2595
  @param session                        Thread handler
 
2596
  @param tables         Global/local table list
 
2597
 
 
2598
  @retval
 
2599
    false OK
 
2600
  @retval
 
2601
    true  error
 
2602
*/
 
2603
 
 
2604
bool multi_delete_precheck(Session *session, TableList *)
 
2605
{
 
2606
  Select_Lex *select_lex= &session->lex->select_lex;
 
2607
  TableList **save_query_tables_own_last= session->lex->query_tables_own_last;
 
2608
 
 
2609
  session->lex->query_tables_own_last= 0;
 
2610
  session->lex->query_tables_own_last= save_query_tables_own_last;
 
2611
 
 
2612
  if ((session->options & OPTION_SAFE_UPDATES) && !select_lex->where)
 
2613
  {
 
2614
    my_message(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE,
 
2615
               ER(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE), MYF(0));
 
2616
    return(true);
 
2617
  }
 
2618
  return(false);
 
2619
}
 
2620
 
 
2621
 
 
2622
/*
 
2623
  Given a table in the source list, find a correspondent table in the
 
2624
  table references list.
 
2625
 
 
2626
  @param lex Pointer to LEX representing multi-delete.
 
2627
  @param src Source table to match.
 
2628
  @param ref Table references list.
 
2629
 
 
2630
  @remark The source table list (tables listed before the FROM clause
 
2631
  or tables listed in the FROM clause before the USING clause) may
 
2632
  contain table names or aliases that must match unambiguously one,
 
2633
  and only one, table in the target table list (table references list,
 
2634
  after FROM/USING clause).
 
2635
 
 
2636
  @return Matching table, NULL otherwise.
 
2637
*/
 
2638
 
 
2639
static TableList *multi_delete_table_match(LEX *, TableList *tbl,
 
2640
                                           TableList *tables)
 
2641
{
 
2642
  TableList *match= NULL;
 
2643
 
 
2644
  for (TableList *elem= tables; elem; elem= elem->next_local)
 
2645
  {
 
2646
    int cmp;
 
2647
 
 
2648
    if (tbl->is_fqtn && elem->is_alias)
 
2649
      continue; /* no match */
 
2650
    if (tbl->is_fqtn && elem->is_fqtn)
 
2651
      cmp= my_strcasecmp(table_alias_charset, tbl->table_name, elem->table_name) ||
 
2652
           strcmp(tbl->db, elem->db);
 
2653
    else if (elem->is_alias)
 
2654
      cmp= my_strcasecmp(table_alias_charset, tbl->alias, elem->alias);
 
2655
    else
 
2656
      cmp= my_strcasecmp(table_alias_charset, tbl->table_name, elem->table_name) ||
 
2657
           strcmp(tbl->db, elem->db);
 
2658
 
 
2659
    if (cmp)
 
2660
      continue;
 
2661
 
 
2662
    if (match)
 
2663
    {
 
2664
      my_error(ER_NONUNIQ_TABLE, MYF(0), elem->alias);
 
2665
      return NULL;
 
2666
    }
 
2667
 
 
2668
    match= elem;
 
2669
  }
 
2670
 
 
2671
  if (!match)
 
2672
    my_error(ER_UNKNOWN_TABLE, MYF(0), tbl->table_name, "MULTI DELETE");
 
2673
 
 
2674
  return(match);
 
2675
}
 
2676
 
 
2677
 
 
2678
/**
 
2679
  Link tables in auxilary table list of multi-delete with corresponding
 
2680
  elements in main table list, and set proper locks for them.
 
2681
 
 
2682
  @param lex   pointer to LEX representing multi-delete
 
2683
 
 
2684
  @retval
 
2685
    false   success
 
2686
  @retval
 
2687
    true    error
 
2688
*/
 
2689
 
 
2690
bool multi_delete_set_locks_and_link_aux_tables(LEX *lex)
 
2691
{
 
2692
  TableList *tables= (TableList*)lex->select_lex.table_list.first;
 
2693
  TableList *target_tbl;
 
2694
 
 
2695
  lex->table_count= 0;
 
2696
 
 
2697
  for (target_tbl= (TableList *)lex->auxiliary_table_list.first;
 
2698
       target_tbl; target_tbl= target_tbl->next_local)
 
2699
  {
 
2700
    lex->table_count++;
 
2701
    /* All tables in aux_tables must be found in FROM PART */
 
2702
    TableList *walk= multi_delete_table_match(lex, target_tbl, tables);
 
2703
    if (!walk)
 
2704
      return(true);
 
2705
    if (!walk->derived)
 
2706
    {
 
2707
      target_tbl->table_name= walk->table_name;
 
2708
      target_tbl->table_name_length= walk->table_name_length;
 
2709
    }
 
2710
    walk->updating= target_tbl->updating;
 
2711
    walk->lock_type= target_tbl->lock_type;
 
2712
    target_tbl->correspondent_table= walk;      // Remember corresponding table
 
2713
  }
 
2714
  return(false);
 
2715
}
 
2716
 
1559
2717
 
1560
2718
/**
1561
2719
  simple INSERT query pre-check.
1599
2757
    true   Error
1600
2758
*/
1601
2759
 
1602
 
bool create_table_precheck(TableIdentifier &identifier)
 
2760
bool create_table_precheck(Session *, TableList *,
 
2761
                           TableList *create_table)
1603
2762
{
1604
 
  if (not plugin::StorageEngine::canCreateTable(identifier))
1605
 
  {
1606
 
    my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), "", "", identifier.getSchemaName().c_str());
1607
 
    return true;
1608
 
  }
1609
 
 
1610
 
  if (not plugin::StorageEngine::doesSchemaExist(identifier))
1611
 
  {
1612
 
    my_error(ER_BAD_DB_ERROR, MYF(0), identifier.getSchemaName().c_str());
1613
 
    return true;
1614
 
  }
1615
 
 
1616
 
  return false;
 
2763
  bool error= true;                                 // Error message is given
 
2764
 
 
2765
  if (create_table && (strcmp(create_table->db, "information_schema") == 0))
 
2766
  {
 
2767
    my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), "", "", INFORMATION_SCHEMA_NAME.c_str());
 
2768
    return(true);
 
2769
  }
 
2770
 
 
2771
  error= false;
 
2772
 
 
2773
  return(error);
1617
2774
}
1618
2775
 
1619
2776
 
1726
2883
}
1727
2884
 
1728
2885
 
 
2886
/*
 
2887
  Check if path does not contain mysql data home directory
 
2888
  SYNOPSIS
 
2889
    test_if_data_home_dir()
 
2890
    dir                     directory
 
2891
    conv_home_dir           converted data home directory
 
2892
    home_dir_len            converted data home directory length
 
2893
 
 
2894
  RETURN VALUES
 
2895
    0   ok
 
2896
    1   error
 
2897
*/
 
2898
 
 
2899
bool test_if_data_home_dir(const char *dir)
 
2900
{
 
2901
  char path[FN_REFLEN], conv_path[FN_REFLEN];
 
2902
  uint32_t dir_len, home_dir_len= strlen(drizzle_unpacked_real_data_home);
 
2903
 
 
2904
  if (!dir)
 
2905
    return(0);
 
2906
 
 
2907
  (void) fn_format(path, dir, "", "",
 
2908
                   (MY_RETURN_REAL_PATH|MY_RESOLVE_SYMLINKS));
 
2909
  dir_len= unpack_dirname(conv_path, dir);
 
2910
 
 
2911
  if (home_dir_len < dir_len)
 
2912
  {
 
2913
    if (!my_strnncoll(character_set_filesystem,
 
2914
                      (const unsigned char*) conv_path, home_dir_len,
 
2915
                      (const unsigned char*) drizzle_unpacked_real_data_home,
 
2916
                      home_dir_len))
 
2917
      return(1);
 
2918
  }
 
2919
  return(0);
 
2920
}
 
2921
 
 
2922
 
 
2923
extern int DRIZZLEparse(void *session); // from sql_yacc.cc
 
2924
 
 
2925
 
1729
2926
/**
1730
2927
  This is a wrapper of DRIZZLEparse(). All the code should call parse_sql()
1731
2928
  instead of DRIZZLEparse().
1738
2935
    @retval true on parsing error.
1739
2936
*/
1740
2937
 
1741
 
static bool parse_sql(Session *session, Lex_input_stream *lip)
 
2938
bool parse_sql(Session *session, Lex_input_stream *lip)
1742
2939
{
1743
2940
  assert(session->m_lip == NULL);
1744
2941
 
1745
 
  DRIZZLE_QUERY_PARSE_START(session->query.c_str());
1746
 
 
1747
2942
  /* Set Lex_input_stream. */
1748
2943
 
1749
2944
  session->m_lip= lip;
1760
2955
 
1761
2956
  session->m_lip= NULL;
1762
2957
 
1763
 
  DRIZZLE_QUERY_PARSE_DONE(mysql_parse_status || session->is_fatal_error);
1764
 
 
1765
2958
  /* That's it. */
1766
2959
 
1767
2960
  return mysql_parse_status || session->is_fatal_error;
1770
2963
/**
1771
2964
  @} (end of group Runtime_Environment)
1772
2965
*/
1773
 
 
1774
 
} /* namespace drizzled */