~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_parse.cc

  • Committer: Padraig O'Sullivan
  • Date: 2009-07-08 04:26:02 UTC
  • mto: (1089.3.4 merge)
  • mto: This revision was merged to the branch mainline in revision 1092.
  • Revision ID: osullivan.padraig@gmail.com-20090708042602-x4hmf9ny8dcpvb22
Replaced an instance where a uint8_t type was being used to hold a
collection of flags. Converted it to a std::bitset<2> instead.

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