sql_lex.cc 83.4 KB
Newer Older
1
/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc.
unknown's avatar
unknown committed
2

unknown's avatar
unknown committed
3 4
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
unknown's avatar
unknown committed
5
   the Free Software Foundation; version 2 of the License.
unknown's avatar
unknown committed
6

unknown's avatar
unknown committed
7 8 9 10
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
unknown's avatar
unknown committed
11

unknown's avatar
unknown committed
12 13 14 15 16 17 18
   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */


/* A lexical scanner on a temporary buffer with a yacc interface */

19
#define MYSQL_LEX 1
unknown's avatar
unknown committed
20 21 22 23
#include "mysql_priv.h"
#include "item_create.h"
#include <m_ctype.h>
#include <hash.h>
24 25
#include "sp.h"
#include "sp_head.h"
unknown's avatar
unknown committed
26

27 28
static int lex_one_token(void *arg, void *yythd);

29 30 31 32
/*
  We are using pointer to this variable for distinguishing between assignment
  to NEW row field (when parsing trigger definition) and structured variable.
*/
33 34

sys_var *trg_new_row_fake_var= (sys_var*) 0x01;
35

36 37 38 39
/**
  LEX_STRING constant for null-string to be used in parser and other places.
*/
const LEX_STRING null_lex_str= {NULL, 0};
40
const LEX_STRING empty_lex_str= { (char*) "", 0 };
41 42 43 44 45 46 47 48 49 50
/**
  @note The order of the elements of this array must correspond to
  the order of elements in enum_binlog_stmt_unsafe.
*/
const int
Query_tables_list::binlog_stmt_unsafe_errcode[BINLOG_STMT_UNSAFE_COUNT] =
{
  ER_BINLOG_UNSAFE_LIMIT,
  ER_BINLOG_UNSAFE_INSERT_DELAYED,
  ER_BINLOG_UNSAFE_SYSTEM_TABLE,
51
  ER_BINLOG_UNSAFE_AUTOINC_COLUMNS,
52 53
  ER_BINLOG_UNSAFE_UDF,
  ER_BINLOG_UNSAFE_SYSTEM_VARIABLE,
54
  ER_BINLOG_UNSAFE_SYSTEM_FUNCTION,
55 56
  ER_BINLOG_UNSAFE_NONTRANS_AFTER_TRANS,
  ER_BINLOG_UNSAFE_MULTIPLE_ENGINES_AND_SELF_LOGGING_ENGINE
57 58
};

59

60
/* Longest standard keyword name */
61

unknown's avatar
unknown committed
62 63
#define TOCK_NAME_LENGTH 24

64 65
/*
  The following data is based on the latin1 character set, and is only
unknown's avatar
unknown committed
66 67 68
  used when comparing keywords
*/

unknown's avatar
unknown committed
69 70
static uchar to_upper_lex[]=
{
unknown's avatar
unknown committed
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
    0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
   16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
   32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
   48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
   64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
   80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
   96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
   80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,123,124,125,126,127,
  128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
  144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
  160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
  176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
  192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
  208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
  192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
  208,209,210,211,212,213,214,247,216,217,218,219,220,221,222,255
};

89 90 91 92 93 94 95 96 97 98 99
/* 
  Names of the index hints (for error messages). Keep in sync with 
  index_hint_type 
*/

const char * index_hint_type_name[] =
{
  "IGNORE INDEX", 
  "USE INDEX", 
  "FORCE INDEX"
};
100

unknown's avatar
unknown committed
101 102 103 104 105 106 107
inline int lex_casecmp(const char *s, const char *t, uint len)
{
  while (len-- != 0 &&
	 to_upper_lex[(uchar) *s++] == to_upper_lex[(uchar) *t++]) ;
  return (int) len+1;
}

unknown's avatar
unknown committed
108
#include <lex_hash.h>
unknown's avatar
unknown committed
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130


void lex_init(void)
{
  uint i;
  DBUG_ENTER("lex_init");
  for (i=0 ; i < array_elements(symbols) ; i++)
    symbols[i].length=(uchar) strlen(symbols[i].name);
  for (i=0 ; i < array_elements(sql_functions) ; i++)
    sql_functions[i].length=(uchar) strlen(sql_functions[i].name);

  DBUG_VOID_RETURN;
}


void lex_free(void)
{					// Call this when daemon ends
  DBUG_ENTER("lex_free");
  DBUG_VOID_RETURN;
}


131 132 133 134 135 136 137 138 139
void
st_parsing_options::reset()
{
  allows_variable= TRUE;
  allows_select_into= TRUE;
  allows_select_procedure= TRUE;
  allows_derived= TRUE;
}

140 141 142 143 144 145 146
Lex_input_stream::Lex_input_stream(THD *thd,
                                   const char* buffer,
                                   unsigned int length)
: m_thd(thd),
  yylineno(1),
  yytoklen(0),
  yylval(NULL),
147 148
  lookahead_token(-1),
  lookahead_yylval(NULL),
149 150 151 152 153 154
  m_ptr(buffer),
  m_tok_start(NULL),
  m_tok_end(NULL),
  m_end_of_query(buffer + length),
  m_tok_start_prev(NULL),
  m_buf(buffer),
unknown's avatar
unknown committed
155
  m_buf_length(length),
unknown's avatar
unknown committed
156
  m_echo(TRUE),
157 158 159
  m_cpp_tok_start(NULL),
  m_cpp_tok_start_prev(NULL),
  m_cpp_tok_end(NULL),
unknown's avatar
unknown committed
160 161
  m_body_utf8(NULL),
  m_cpp_utf8_processed_ptr(NULL),
162 163
  next_state(MY_LEX_START),
  found_semicolon(NULL),
164
  ignore_space(test(thd->variables.sql_mode & MODE_IGNORE_SPACE)),
165
  stmt_prepare_mode(FALSE),
166
  multi_statements(TRUE),
unknown's avatar
unknown committed
167 168
  in_comment(NO_COMMENT),
  m_underscore_cs(NULL)
169
{
170 171
  m_cpp_buf= (char*) thd->alloc(length + 1);
  m_cpp_ptr= m_cpp_buf;
172 173 174 175 176
}

Lex_input_stream::~Lex_input_stream()
{}

unknown's avatar
unknown committed
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
/**
  The operation is called from the parser in order to
  1) designate the intention to have utf8 body;
  1) Indicate to the lexer that we will need a utf8 representation of this
     statement;
  2) Determine the beginning of the body.

  @param thd        Thread context.
  @param begin_ptr  Pointer to the start of the body in the pre-processed
                    buffer.
*/

void Lex_input_stream::body_utf8_start(THD *thd, const char *begin_ptr)
{
  DBUG_ASSERT(begin_ptr);
  DBUG_ASSERT(m_cpp_buf <= begin_ptr && begin_ptr <= m_cpp_buf + m_buf_length);

  uint body_utf8_length=
    (m_buf_length / thd->variables.character_set_client->mbminlen) *
    my_charset_utf8_bin.mbmaxlen;

  m_body_utf8= (char *) thd->alloc(body_utf8_length + 1);
  m_body_utf8_ptr= m_body_utf8;
  *m_body_utf8_ptr= 0;

  m_cpp_utf8_processed_ptr= begin_ptr;
}

/**
unknown's avatar
unknown committed
206
  @brief The operation appends unprocessed part of pre-processed buffer till
unknown's avatar
unknown committed
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281
  the given pointer (ptr) and sets m_cpp_utf8_processed_ptr to end_ptr.

  The idea is that some tokens in the pre-processed buffer (like character
  set introducers) should be skipped.

  Example:
    CPP buffer: SELECT 'str1', _latin1 'str2';
    m_cpp_utf8_processed_ptr -- points at the "SELECT ...";
    In order to skip "_latin1", the following call should be made:
      body_utf8_append(<pointer to "_latin1 ...">, <pointer to " 'str2'...">)

  @param ptr      Pointer in the pre-processed buffer, which specifies the
                  end of the chunk, which should be appended to the utf8
                  body.
  @param end_ptr  Pointer in the pre-processed buffer, to which
                  m_cpp_utf8_processed_ptr will be set in the end of the
                  operation.
*/

void Lex_input_stream::body_utf8_append(const char *ptr,
                                        const char *end_ptr)
{
  DBUG_ASSERT(m_cpp_buf <= ptr && ptr <= m_cpp_buf + m_buf_length);
  DBUG_ASSERT(m_cpp_buf <= end_ptr && end_ptr <= m_cpp_buf + m_buf_length);

  if (!m_body_utf8)
    return;

  if (m_cpp_utf8_processed_ptr >= ptr)
    return;

  int bytes_to_copy= ptr - m_cpp_utf8_processed_ptr;

  memcpy(m_body_utf8_ptr, m_cpp_utf8_processed_ptr, bytes_to_copy);
  m_body_utf8_ptr += bytes_to_copy;
  *m_body_utf8_ptr= 0;

  m_cpp_utf8_processed_ptr= end_ptr;
}

/**
  The operation appends unprocessed part of the pre-processed buffer till
  the given pointer (ptr) and sets m_cpp_utf8_processed_ptr to ptr.

  @param ptr  Pointer in the pre-processed buffer, which specifies the end
              of the chunk, which should be appended to the utf8 body.
*/

void Lex_input_stream::body_utf8_append(const char *ptr)
{
  body_utf8_append(ptr, ptr);
}

/**
  The operation converts the specified text literal to the utf8 and appends
  the result to the utf8-body.

  @param thd      Thread context.
  @param txt      Text literal.
  @param txt_cs   Character set of the text literal.
  @param end_ptr  Pointer in the pre-processed buffer, to which
                  m_cpp_utf8_processed_ptr will be set in the end of the
                  operation.
*/

void Lex_input_stream::body_utf8_append_literal(THD *thd,
                                                const LEX_STRING *txt,
                                                CHARSET_INFO *txt_cs,
                                                const char *end_ptr)
{
  if (!m_cpp_utf8_processed_ptr)
    return;

  LEX_STRING utf_txt;

unknown's avatar
unknown committed
282
  if (!my_charset_same(txt_cs, &my_charset_utf8_general_ci))
unknown's avatar
unknown committed
283 284 285
  {
    thd->convert_string(&utf_txt,
                        &my_charset_utf8_general_ci,
286
                        txt->str, (uint) txt->length,
unknown's avatar
unknown committed
287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303
                        txt_cs);
  }
  else
  {
    utf_txt.str= txt->str;
    utf_txt.length= txt->length;
  }

  /* NOTE: utf_txt.length is in bytes, not in symbols. */

  memcpy(m_body_utf8_ptr, utf_txt.str, utf_txt.length);
  m_body_utf8_ptr += utf_txt.length;
  *m_body_utf8_ptr= 0;

  m_cpp_utf8_processed_ptr= end_ptr;
}

304

305 306 307 308 309 310
/*
  This is called before every query that is to be parsed.
  Because of this, it's critical to not do too much things here.
  (We already do too much here)
*/

311
void lex_start(THD *thd)
unknown's avatar
unknown committed
312
{
unknown's avatar
unknown committed
313
  LEX *lex= thd->lex;
unknown's avatar
unknown committed
314 315 316 317
  DBUG_ENTER("lex_start");

  lex->thd= lex->unit.thd= thd;

unknown's avatar
unknown committed
318
  lex->context_stack.empty();
319 320
  lex->unit.init_query();
  lex->unit.init_select();
unknown's avatar
unknown committed
321 322
  /* 'parent_lex' is used in init_query() so it must be before it. */
  lex->select_lex.parent_lex= lex;
323 324
  lex->select_lex.init_query();
  lex->value_list.empty();
unknown's avatar
unknown committed
325
  lex->update_list.empty();
326
  lex->set_var_list.empty();
327
  lex->param_list.empty();
unknown's avatar
unknown committed
328
  lex->view_list.empty();
329
  lex->prepared_stmt_params.empty();
330
  lex->auxiliary_table_list.empty();
331 332 333 334 335 336 337 338 339 340
  lex->unit.next= lex->unit.master=
    lex->unit.link_next= lex->unit.return_to= 0;
  lex->unit.prev= lex->unit.link_prev= 0;
  lex->unit.slave= lex->unit.global_parameters= lex->current_select=
    lex->all_selects_list= &lex->select_lex;
  lex->select_lex.master= &lex->unit;
  lex->select_lex.prev= &lex->unit.slave;
  lex->select_lex.link_next= lex->select_lex.slave= lex->select_lex.next= 0;
  lex->select_lex.link_prev= (st_select_lex_node**)&(lex->all_selects_list);
  lex->select_lex.options= 0;
341
  lex->select_lex.sql_cache= SELECT_LEX::SQL_CACHE_UNSPECIFIED;
unknown's avatar
unknown committed
342 343
  lex->select_lex.init_order();
  lex->select_lex.group_list.empty();
344
  lex->describe= 0;
unknown's avatar
unknown committed
345
  lex->subqueries= FALSE;
unknown's avatar
unknown committed
346
  lex->view_prepare_mode= FALSE;
unknown's avatar
unknown committed
347
  lex->derived_tables= 0;
348 349
  lex->lock_option= TL_READ;
  lex->safe_to_cache_query= 1;
350
  lex->leaf_tables_insert= 0;
351
  lex->parsing_options.reset();
unknown's avatar
unknown committed
352
  lex->empty_field_list_on_rset= 0;
353
  lex->select_lex.select_number= 1;
unknown's avatar
unknown committed
354
  lex->length=0;
355
  lex->part_info= 0;
unknown's avatar
unknown committed
356
  lex->select_lex.in_sum_expr=0;
unknown's avatar
unknown committed
357
  lex->select_lex.ftfunc_list_alloc.empty();
358
  lex->select_lex.ftfunc_list= &lex->select_lex.ftfunc_list_alloc;
unknown's avatar
unknown committed
359 360
  lex->select_lex.group_list.empty();
  lex->select_lex.order_list.empty();
361
  lex->sql_command= SQLCOM_END;
362
  lex->duplicates= DUP_ERROR;
363
  lex->ignore= 0;
unknown's avatar
unknown committed
364
  lex->spname= NULL;
365 366
  lex->sphead= NULL;
  lex->spcont= NULL;
unknown's avatar
unknown committed
367
  lex->proc_list.first= 0;
unknown's avatar
unknown committed
368
  lex->escape_used= FALSE;
unknown's avatar
unknown committed
369
  lex->query_tables= 0;
370
  lex->reset_query_tables_list(FALSE);
371
  lex->expr_allows_subselect= TRUE;
372
  lex->use_only_table_context= FALSE;
373

374 375
  lex->name.str= 0;
  lex->name.length= 0;
unknown's avatar
unknown committed
376
  lex->event_parse_data= NULL;
unknown's avatar
unknown committed
377
  lex->profile_options= PROFILE_NONE;
unknown's avatar
unknown committed
378 379 380
  lex->nest_level=0 ;
  lex->allow_sum_func= 0;
  lex->in_sum_func= NULL;
381
  lex->protect_against_global_read_lock= FALSE;
unknown's avatar
unknown committed
382 383 384 385 386 387 388 389 390 391 392 393 394 395 396
  /*
    ok, there must be a better solution for this, long-term
    I tried "bzero" in the sql_yacc.yy code, but that for
    some reason made the values zero, even if they were set
  */
  lex->server_options.server_name= 0;
  lex->server_options.server_name_length= 0;
  lex->server_options.host= 0;
  lex->server_options.db= 0;
  lex->server_options.username= 0;
  lex->server_options.password= 0;
  lex->server_options.scheme= 0;
  lex->server_options.socket= 0;
  lex->server_options.owner= 0;
  lex->server_options.port= -1;
unknown's avatar
unknown committed
397

398
  lex->is_lex_started= TRUE;
unknown's avatar
unknown committed
399
  DBUG_VOID_RETURN;
unknown's avatar
unknown committed
400 401 402 403
}

void lex_end(LEX *lex)
{
unknown's avatar
unknown committed
404
  DBUG_ENTER("lex_end");
unknown's avatar
unknown committed
405
  DBUG_PRINT("enter", ("lex: 0x%lx", (long) lex));
unknown's avatar
unknown committed
406 407 408 409 410 411

  /* release used plugins */
  plugin_unlock_list(0, (plugin_ref*)lex->plugins.buffer, 
                     lex->plugins.elements);
  reset_dynamic(&lex->plugins);

unknown's avatar
unknown committed
412
  DBUG_VOID_RETURN;
unknown's avatar
unknown committed
413 414
}

415 416 417 418
Yacc_state::~Yacc_state()
{
  if (yacc_yyss)
  {
419 420
    my_free(yacc_yyss, MYF(0));
    my_free(yacc_yyvs, MYF(0));
421
  }
unknown's avatar
unknown committed
422 423
}

424
static int find_keyword(Lex_input_stream *lip, uint len, bool function)
unknown's avatar
unknown committed
425
{
426
  const char *tok= lip->get_tok_start();
unknown's avatar
unknown committed
427

428
  SYMBOL *symbol= get_hash_symbol(tok, len, function);
unknown's avatar
unknown committed
429 430
  if (symbol)
  {
431 432 433 434
    lip->yylval->symbol.symbol=symbol;
    lip->yylval->symbol.str= (char*) tok;
    lip->yylval->symbol.length=len;

435
    if ((symbol->tok == NOT_SYM) &&
436
        (lip->m_thd->variables.sql_mode & MODE_HIGH_NOT_PRECEDENCE))
437 438
      return NOT2_SYM;
    if ((symbol->tok == OR_OR_SYM) &&
439
	!(lip->m_thd->variables.sql_mode & MODE_PIPES_AS_CONCAT))
440
      return OR2_SYM;
441

unknown's avatar
unknown committed
442 443 444 445 446
    return symbol->tok;
  }
  return 0;
}

447 448 449 450 451
/*
  Check if name is a keyword

  SYNOPSIS
    is_keyword()
452
    name      checked name (must not be empty)
453 454 455 456 457 458 459 460 461
    len       length of checked name

  RETURN VALUES
    0         name is a keyword
    1         name isn't a keyword
*/

bool is_keyword(const char *name, uint len)
{
462
  DBUG_ASSERT(len != 0);
463 464
  return get_hash_symbol(name,len,0)!=0;
}
unknown's avatar
unknown committed
465

466 467 468 469 470
/**
  Check if name is a sql function

    @param name      checked name

471
    @return is this a native function or not
472 473 474 475
    @retval 0         name is a function
    @retval 1         name isn't a function
*/

476 477 478
bool is_lex_native_function(const LEX_STRING *name)
{
  DBUG_ASSERT(name != NULL);
479
  return (get_hash_symbol(name->str, (uint) name->length, 1) != 0);
480 481
}

unknown's avatar
unknown committed
482 483
/* make a copy of token before ptr and set yytoklen */

484
static LEX_STRING get_token(Lex_input_stream *lip, uint skip, uint length)
unknown's avatar
unknown committed
485 486
{
  LEX_STRING tmp;
487
  lip->yyUnget();                       // ptr points now after last token char
488
  tmp.length=lip->yytoklen=length;
489
  tmp.str= lip->m_thd->strmake(lip->get_tok_start() + skip, tmp.length);
unknown's avatar
unknown committed
490 491 492 493

  lip->m_cpp_text_start= lip->get_cpp_tok_start() + skip;
  lip->m_cpp_text_end= lip->m_cpp_text_start + tmp.length;

unknown's avatar
unknown committed
494 495 496
  return tmp;
}

497 498 499 500 501 502 503
/* 
 todo: 
   There are no dangerous charsets in mysql for function 
   get_quoted_token yet. But it should be fixed in the 
   future to operate multichar strings (like ucs2)
*/

504
static LEX_STRING get_quoted_token(Lex_input_stream *lip,
505
                                   uint skip,
506
                                   uint length, char quote)
507 508
{
  LEX_STRING tmp;
509 510
  const char *from, *end;
  char *to;
511
  lip->yyUnget();                       // ptr points now after last token char
512 513
  tmp.length= lip->yytoklen=length;
  tmp.str=(char*) lip->m_thd->alloc(tmp.length+1);
514
  from= lip->get_tok_start() + skip;
515
  to= tmp.str;
516
  end= to+length;
unknown's avatar
unknown committed
517 518 519 520

  lip->m_cpp_text_start= lip->get_cpp_tok_start() + skip;
  lip->m_cpp_text_end= lip->m_cpp_text_start + length;

521
  for ( ; to != end; )
522
  {
523
    if ((*to++= *from++) == quote)
unknown's avatar
unknown committed
524
    {
525
      from++;					// Skip double quotes
unknown's avatar
unknown committed
526 527
      lip->m_cpp_text_start++;
    }
528 529 530 531 532 533 534 535 536 537
  }
  *to= 0;					// End null for safety
  return tmp;
}


/*
  Return an unescaped text literal without quotes
  Fix sometimes to do only one scan of the string
*/
unknown's avatar
unknown committed
538

539
static char *get_text(Lex_input_stream *lip, int pre_skip, int post_skip)
unknown's avatar
unknown committed
540 541 542
{
  reg1 uchar c,sep;
  uint found_escape=0;
543
  CHARSET_INFO *cs= lip->m_thd->charset();
unknown's avatar
unknown committed
544

545
  lip->tok_bitmap= 0;
546 547
  sep= lip->yyGetLast();                        // String should end with this
  while (! lip->eof())
unknown's avatar
unknown committed
548
  {
549
    c= lip->yyGet();
550
    lip->tok_bitmap|= c;
unknown's avatar
unknown committed
551
#ifdef USE_MB
552 553 554
    {
      int l;
      if (use_mb(cs) &&
555 556 557 558 559
          (l = my_ismbchar(cs,
                           lip->get_ptr() -1,
                           lip->get_end_of_query()))) {
        lip->skip_binary(l-1);
        continue;
560
      }
unknown's avatar
unknown committed
561 562
    }
#endif
563
    if (c == '\\' &&
564
        !(lip->m_thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES))
unknown's avatar
unknown committed
565 566
    {					// Escaped character
      found_escape=1;
567
      if (lip->eof())
unknown's avatar
unknown committed
568
	return 0;
569
      lip->yySkip();
unknown's avatar
unknown committed
570 571 572
    }
    else if (c == sep)
    {
573
      if (c == lip->yyGet())            // Check if two separators in a row
unknown's avatar
unknown committed
574
      {
575
        found_escape=1;                 // duplicate. Remember for delete
unknown's avatar
unknown committed
576 577 578
	continue;
      }
      else
579
        lip->yyUnget();
unknown's avatar
unknown committed
580 581

      /* Found end. Unescape and return string */
582 583
      const char *str, *end;
      char *start;
unknown's avatar
unknown committed
584

585 586 587 588 589 590 591
      str= lip->get_tok_start();
      end= lip->get_ptr();
      /* Extract the text from the token */
      str += pre_skip;
      end -= post_skip;
      DBUG_ASSERT(end >= str);

592
      if (!(start= (char*) lip->m_thd->alloc((uint) (end-str)+1)))
unknown's avatar
unknown committed
593
	return (char*) "";		// Sql_alloc has set error flag
unknown's avatar
unknown committed
594 595 596 597

      lip->m_cpp_text_start= lip->get_cpp_tok_start() + pre_skip;
      lip->m_cpp_text_end= lip->get_cpp_ptr() - post_skip;

unknown's avatar
unknown committed
598 599
      if (!found_escape)
      {
600 601 602
	lip->yytoklen=(uint) (end-str);
	memcpy(start,str,lip->yytoklen);
	start[lip->yytoklen]=0;
unknown's avatar
unknown committed
603 604 605
      }
      else
      {
606
        char *to;
607

unknown's avatar
unknown committed
608 609 610 611
	for (to=start ; str != end ; str++)
	{
#ifdef USE_MB
	  int l;
unknown's avatar
unknown committed
612
	  if (use_mb(cs) &&
613
              (l = my_ismbchar(cs, str, end))) {
unknown's avatar
unknown committed
614 615 616 617 618 619
	      while (l--)
		  *to++ = *str++;
	      str--;
	      continue;
	  }
#endif
620
	  if (!(lip->m_thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES) &&
621
              *str == '\\' && str+1 != end)
unknown's avatar
unknown committed
622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646
	  {
	    switch(*++str) {
	    case 'n':
	      *to++='\n';
	      break;
	    case 't':
	      *to++= '\t';
	      break;
	    case 'r':
	      *to++ = '\r';
	      break;
	    case 'b':
	      *to++ = '\b';
	      break;
	    case '0':
	      *to++= 0;			// Ascii null
	      break;
	    case 'Z':			// ^Z must be escaped on Win32
	      *to++='\032';
	      break;
	    case '_':
	    case '%':
	      *to++= '\\';		// remember prefix for wildcard
	      /* Fall through */
	    default:
647
              *to++= *str;
unknown's avatar
unknown committed
648 649 650
	      break;
	    }
	  }
651 652
	  else if (*str == sep)
	    *to++= *str++;		// Two ' or "
unknown's avatar
unknown committed
653 654 655 656
	  else
	    *to++ = *str;
	}
	*to=0;
657
	lip->yytoklen=(uint) (to-start);
unknown's avatar
unknown committed
658
      }
659
      return start;
unknown's avatar
unknown committed
660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680
    }
  }
  return 0;					// unexpected end of query
}


/*
** Calc type of integer; long integer, longlong integer or real.
** Returns smallest type that match the string.
** When using unsigned long long values the result is converted to a real
** because else they will be unexpected sign changes because all calculation
** is done with longlong or double.
*/

static const char *long_str="2147483647";
static const uint long_len=10;
static const char *signed_long_str="-2147483648";
static const char *longlong_str="9223372036854775807";
static const uint longlong_len=19;
static const char *signed_longlong_str="-9223372036854775808";
static const uint signed_longlong_len=19;
unknown's avatar
unknown committed
681 682
static const char *unsigned_longlong_str="18446744073709551615";
static const uint unsigned_longlong_len=20;
unknown's avatar
unknown committed
683

unknown's avatar
unknown committed
684
static inline uint int_token(const char *str,uint length)
unknown's avatar
unknown committed
685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718
{
  if (length < long_len)			// quick normal case
    return NUM;
  bool neg=0;

  if (*str == '+')				// Remove sign and pre-zeros
  {
    str++; length--;
  }
  else if (*str == '-')
  {
    str++; length--;
    neg=1;
  }
  while (*str == '0' && length)
  {
    str++; length --;
  }
  if (length < long_len)
    return NUM;

  uint smaller,bigger;
  const char *cmp;
  if (neg)
  {
    if (length == long_len)
    {
      cmp= signed_long_str+1;
      smaller=NUM;				// If <= signed_long_str
      bigger=LONG_NUM;				// If >= signed_long_str
    }
    else if (length < signed_longlong_len)
      return LONG_NUM;
    else if (length > signed_longlong_len)
unknown's avatar
unknown committed
719
      return DECIMAL_NUM;
unknown's avatar
unknown committed
720 721 722 723
    else
    {
      cmp=signed_longlong_str+1;
      smaller=LONG_NUM;				// If <= signed_longlong_str
unknown's avatar
unknown committed
724
      bigger=DECIMAL_NUM;
unknown's avatar
unknown committed
725 726 727 728 729 730 731 732 733 734 735 736 737
    }
  }
  else
  {
    if (length == long_len)
    {
      cmp= long_str;
      smaller=NUM;
      bigger=LONG_NUM;
    }
    else if (length < longlong_len)
      return LONG_NUM;
    else if (length > longlong_len)
unknown's avatar
unknown committed
738 739
    {
      if (length > unsigned_longlong_len)
unknown's avatar
unknown committed
740
        return DECIMAL_NUM;
unknown's avatar
unknown committed
741 742
      cmp=unsigned_longlong_str;
      smaller=ULONGLONG_NUM;
unknown's avatar
unknown committed
743
      bigger=DECIMAL_NUM;
unknown's avatar
unknown committed
744
    }
unknown's avatar
unknown committed
745 746 747 748
    else
    {
      cmp=longlong_str;
      smaller=LONG_NUM;
749
      bigger= ULONGLONG_NUM;
unknown's avatar
unknown committed
750 751 752 753 754 755
    }
  }
  while (*cmp && *cmp++ == *str++) ;
  return ((uchar) str[-1] <= (uchar) cmp[-1]) ? smaller : bigger;
}

756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802

/**
  Given a stream that is advanced to the first contained character in 
  an open comment, consume the comment.  Optionally, if we are allowed, 
  recurse so that we understand comments within this current comment.

  At this level, we do not support version-condition comments.  We might 
  have been called with having just passed one in the stream, though.  In 
  that case, we probably want to tolerate mundane comments inside.  Thus,
  the case for recursion.

  @retval  Whether EOF reached before comment is closed.
*/
bool consume_comment(Lex_input_stream *lip, int remaining_recursions_permitted)
{
  reg1 uchar c;
  while (! lip->eof())
  {
    c= lip->yyGet();

    if (remaining_recursions_permitted > 0)
    {
      if ((c == '/') && (lip->yyPeek() == '*'))
      {
        lip->yySkip(); /* Eat asterisk */
        consume_comment(lip, remaining_recursions_permitted-1);
        continue;
      }
    }

    if (c == '*')
    {
      if (lip->yyPeek() == '/')
      {
        lip->yySkip(); /* Eat slash */
        return FALSE;
      }
    }

    if (c == '\n')
      lip->yylineno++;
  }

  return TRUE;
}


803
/*
804
  MYSQLlex remember the following states from the following MYSQLlex()
805 806 807 808 809

  - MY_LEX_EOQ			Found end of query
  - MY_LEX_OPERATOR_OR_IDENT	Last state was an ident, text or number
				(which can't be followed by a signed number)
*/
unknown's avatar
unknown committed
810

811
int MYSQLlex(void *arg, void *yythd)
812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865
{
  THD *thd= (THD *)yythd;
  Lex_input_stream *lip= & thd->m_parser_state->m_lip;
  YYSTYPE *yylval=(YYSTYPE*) arg;
  int token;

  if (lip->lookahead_token >= 0)
  {
    /*
      The next token was already parsed in advance,
      return it.
    */
    token= lip->lookahead_token;
    lip->lookahead_token= -1;
    *yylval= *(lip->lookahead_yylval);
    lip->lookahead_yylval= NULL;
    return token;
  }

  token= lex_one_token(arg, yythd);

  switch(token) {
  case WITH:
    /*
      Parsing 'WITH' 'ROLLUP' or 'WITH' 'CUBE' requires 2 look ups,
      which makes the grammar LALR(2).
      Replace by a single 'WITH_ROLLUP' or 'WITH_CUBE' token,
      to transform the grammar into a LALR(1) grammar,
      which sql_yacc.yy can process.
    */
    token= lex_one_token(arg, yythd);
    switch(token) {
    case CUBE_SYM:
      return WITH_CUBE_SYM;
    case ROLLUP_SYM:
      return WITH_ROLLUP_SYM;
    default:
      /*
        Save the token following 'WITH'
      */
      lip->lookahead_yylval= lip->yylval;
      lip->yylval= NULL;
      lip->lookahead_token= token;
      return WITH;
    }
    break;
  default:
    break;
  }

  return token;
}

int lex_one_token(void *arg, void *yythd)
unknown's avatar
unknown committed
866
{
Staale Smedseng's avatar
Staale Smedseng committed
867
  reg1	uchar c= 0;
868
  bool comment_closed;
869
  int	tokval, result_state;
unknown's avatar
unknown committed
870
  uint length;
unknown's avatar
unknown committed
871
  enum my_lex_states state;
872
  THD *thd= (THD *)yythd;
873
  Lex_input_stream *lip= & thd->m_parser_state->m_lip;
874
  LEX *lex= thd->lex;
unknown's avatar
unknown committed
875
  YYSTYPE *yylval=(YYSTYPE*) arg;
876
  CHARSET_INFO *cs= thd->charset();
877 878
  uchar *state_map= cs->state_map;
  uchar *ident_map= cs->ident_map;
unknown's avatar
unknown committed
879

880
  lip->yylval=yylval;			// The global state
881

882
  lip->start_token();
883 884
  state=lip->next_state;
  lip->next_state=MY_LEX_OPERATOR_OR_IDENT;
unknown's avatar
unknown committed
885 886
  for (;;)
  {
887
    switch (state) {
888 889
    case MY_LEX_OPERATOR_OR_IDENT:	// Next is operator or keyword
    case MY_LEX_START:			// Start of token
890 891
      // Skip starting whitespace
      while(state_map[c= lip->yyPeek()] == MY_LEX_SKIP)
unknown's avatar
unknown committed
892 893
      {
	if (c == '\n')
894
	  lip->yylineno++;
895 896

        lip->yySkip();
unknown's avatar
unknown committed
897
      }
898 899 900 901

      /* Start of real token */
      lip->restart_token();
      c= lip->yyGet();
902
      state= (enum my_lex_states) state_map[c];
unknown's avatar
unknown committed
903
      break;
904
    case MY_LEX_ESCAPE:
905
      if (lip->yyGet() == 'N')
unknown's avatar
unknown committed
906 907 908 909 910
      {					// Allow \N as shortcut for NULL
	yylval->lex_str.str=(char*) "\\N";
	yylval->lex_str.length=2;
	return NULL_SYM;
      }
911 912
    case MY_LEX_CHAR:			// Unknown or single char token
    case MY_LEX_SKIP:			// This should not happen
913 914 915
      if (c == '-' && lip->yyPeek() == '-' &&
          (my_isspace(cs,lip->yyPeekn(1)) ||
           my_iscntrl(cs,lip->yyPeekn(1))))
916 917 918 919
      {
        state=MY_LEX_COMMENT;
        break;
      }
920

unknown's avatar
unknown committed
921
      if (c != ')')
922
	lip->next_state= MY_LEX_START;	// Allow signed numbers
923

unknown's avatar
unknown committed
924
      if (c == ',')
925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945
      {
        /*
          Warning:
          This is a work around, to make the "remember_name" rule in
          sql/sql_yacc.yy work properly.
          The problem is that, when parsing "select expr1, expr2",
          the code generated by bison executes the *pre* action
          remember_name (see select_item) *before* actually parsing the
          first token of expr2.
        */
        lip->restart_token();
      }
      else
      {
        /*
          Check for a placeholder: it should not precede a possible identifier
          because of binlogging: when a placeholder is replaced with
          its value in a query for the binlog, the query must stay
          grammatically correct.
        */
        if (c == '?' && lip->stmt_prepare_mode && !ident_map[lip->yyPeek()])
946
        return(PARAM_MARKER);
947 948
      }

unknown's avatar
unknown committed
949 950
      return((int) c);

unknown's avatar
unknown committed
951
    case MY_LEX_IDENT_OR_NCHAR:
952 953
      if (lip->yyPeek() != '\'')
      {
unknown's avatar
unknown committed
954 955 956
	state= MY_LEX_IDENT;
	break;
      }
957
      /* Found N'string' */
958 959
      lip->yySkip();                         // Skip '
      if (!(yylval->lex_str.str = get_text(lip, 2, 1)))
unknown's avatar
unknown committed
960
      {
961 962
	state= MY_LEX_CHAR;             // Read char by char
	break;
unknown's avatar
unknown committed
963
      }
964
      yylval->lex_str.length= lip->yytoklen;
965
      lex->text_string_is_7bit= (lip->tok_bitmap & 0x80) ? 0 : 1;
966
      return(NCHAR_STRING);
unknown's avatar
unknown committed
967

968
    case MY_LEX_IDENT_OR_HEX:
969
      if (lip->yyPeek() == '\'')
970
      {					// Found x'hex-number'
971
	state= MY_LEX_HEX_NUMBER;
972 973
	break;
      }
unknown's avatar
unknown committed
974
    case MY_LEX_IDENT_OR_BIN:
975
      if (lip->yyPeek() == '\'')
unknown's avatar
unknown committed
976 977 978 979
      {                                 // Found b'bin-number'
        state= MY_LEX_BIN_NUMBER;
        break;
      }
980
    case MY_LEX_IDENT:
981
      const char *start;
unknown's avatar
unknown committed
982
#if defined(USE_MB) && defined(USE_MB_IDENT)
983
      if (use_mb(cs))
unknown's avatar
unknown committed
984
      {
985
	result_state= IDENT_QUOTED;
986
        if (my_mbcharlen(cs, lip->yyGetLast()) > 1)
unknown's avatar
unknown committed
987
        {
988 989 990
          int l = my_ismbchar(cs,
                              lip->get_ptr() -1,
                              lip->get_end_of_query());
unknown's avatar
unknown committed
991
          if (l == 0) {
992
            state = MY_LEX_CHAR;
unknown's avatar
unknown committed
993 994
            continue;
          }
995
          lip->skip_binary(l - 1);
unknown's avatar
unknown committed
996
        }
997
        while (ident_map[c=lip->yyGet()])
unknown's avatar
unknown committed
998
        {
999
          if (my_mbcharlen(cs, c) > 1)
unknown's avatar
unknown committed
1000 1001
          {
            int l;
1002 1003 1004
            if ((l = my_ismbchar(cs,
                                 lip->get_ptr() -1,
                                 lip->get_end_of_query())) == 0)
unknown's avatar
unknown committed
1005
              break;
1006
            lip->skip_binary(l-1);
unknown's avatar
unknown committed
1007 1008 1009 1010 1011
          }
        }
      }
      else
#endif
1012
      {
Staale Smedseng's avatar
Staale Smedseng committed
1013
        for (result_state= c; ident_map[c= lip->yyGet()]; result_state|= c) ;
unknown's avatar
unknown committed
1014 1015
        /* If there were non-ASCII characters, mark that we must convert */
        result_state= result_state & 0x80 ? IDENT_QUOTED : IDENT;
1016
      }
1017 1018
      length= lip->yyLength();
      start= lip->get_ptr();
1019
      if (lip->ignore_space)
unknown's avatar
unknown committed
1020
      {
unknown's avatar
unknown committed
1021 1022 1023 1024
        /*
          If we find a space then this can't be an identifier. We notice this
          below by checking start != lex->ptr.
        */
Staale Smedseng's avatar
Staale Smedseng committed
1025
        for (; state_map[c] == MY_LEX_SKIP ; c= lip->yyGet()) ;
unknown's avatar
unknown committed
1026
      }
1027
      if (start == lip->get_ptr() && c == '.' && ident_map[lip->yyPeek()])
1028
	lip->next_state=MY_LEX_IDENT_SEP;
unknown's avatar
unknown committed
1029 1030
      else
      {					// '(' must follow directly if function
1031 1032
        lip->yyUnget();
	if ((tokval = find_keyword(lip, length, c == '(')))
unknown's avatar
unknown committed
1033
	{
1034
	  lip->next_state= MY_LEX_START;	// Allow signed numbers
unknown's avatar
unknown committed
1035 1036
	  return(tokval);		// Was keyword
	}
1037
        lip->yySkip();                  // next state does a unget
unknown's avatar
unknown committed
1038
      }
1039
      yylval->lex_str=get_token(lip, 0, length);
1040

unknown's avatar
unknown committed
1041
      /*
1042 1043
         Note: "SELECT _bla AS 'alias'"
         _bla should be considered as a IDENT if charset haven't been found.
unknown's avatar
unknown committed
1044
         So we don't use MYF(MY_WME) with get_charset_by_csname to avoid
1045 1046 1047
         producing an error.
      */

unknown's avatar
unknown committed
1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067
      if (yylval->lex_str.str[0] == '_')
      {
        CHARSET_INFO *cs= get_charset_by_csname(yylval->lex_str.str + 1,
                                                MY_CS_PRIMARY, MYF(0));
        if (cs)
        {
          yylval->charset= cs;
          lip->m_underscore_cs= cs;

          lip->body_utf8_append(lip->m_cpp_text_start,
                                lip->get_cpp_tok_start() + length);
          return(UNDERSCORE_CHARSET);
        }
      }

      lip->body_utf8_append(lip->m_cpp_text_start);

      lip->body_utf8_append_literal(thd, &yylval->lex_str, cs,
                                    lip->m_cpp_text_end);

1068
      return(result_state);			// IDENT or IDENT_QUOTED
unknown's avatar
unknown committed
1069

1070
    case MY_LEX_IDENT_SEP:		// Found ident and now '.'
1071 1072 1073
      yylval->lex_str.str= (char*) lip->get_ptr();
      yylval->lex_str.length= 1;
      c= lip->yyGet();                  // should be '.'
1074
      lip->next_state= MY_LEX_IDENT_START;// Next is an ident (not a keyword)
1075
      if (!ident_map[lip->yyPeek()])            // Probably ` or "
1076
	lip->next_state= MY_LEX_START;
unknown's avatar
unknown committed
1077 1078
      return((int) c);

1079
    case MY_LEX_NUMBER_IDENT:		// number or ident which num-start
1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097
      if (lip->yyGetLast() == '0')
      {
        c= lip->yyGet();
        if (c == 'x')
        {
          while (my_isxdigit(cs,(c = lip->yyGet()))) ;
          if ((lip->yyLength() >= 3) && !ident_map[c])
          {
            /* skip '0x' */
            yylval->lex_str=get_token(lip, 2, lip->yyLength()-2);
            return (HEX_NUM);
          }
          lip->yyUnget();
          state= MY_LEX_IDENT_START;
          break;
        }
        else if (c == 'b')
        {
Staale Smedseng's avatar
Staale Smedseng committed
1098
          while ((c= lip->yyGet()) == '0' || c == '1') ;
1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112
          if ((lip->yyLength() >= 3) && !ident_map[c])
          {
            /* Skip '0b' */
            yylval->lex_str= get_token(lip, 2, lip->yyLength()-2);
            return (BIN_NUM);
          }
          lip->yyUnget();
          state= MY_LEX_IDENT_START;
          break;
        }
        lip->yyUnget();
      }

      while (my_isdigit(cs, (c = lip->yyGet()))) ;
unknown's avatar
unknown committed
1113
      if (!ident_map[c])
unknown's avatar
unknown committed
1114
      {					// Can't be identifier
1115
	state=MY_LEX_INT_OR_REAL;
unknown's avatar
unknown committed
1116 1117 1118 1119
	break;
      }
      if (c == 'e' || c == 'E')
      {
unknown's avatar
unknown committed
1120
	// The following test is written this way to allow numbers of type 1e1
1121 1122
        if (my_isdigit(cs,lip->yyPeek()) ||
            (c=(lip->yyGet())) == '+' || c == '-')
unknown's avatar
unknown committed
1123
	{				// Allow 1E+10
1124
          if (my_isdigit(cs,lip->yyPeek()))     // Number must have digit after sign
unknown's avatar
unknown committed
1125
	  {
1126 1127 1128
            lip->yySkip();
            while (my_isdigit(cs,lip->yyGet())) ;
            yylval->lex_str=get_token(lip, 0, lip->yyLength());
unknown's avatar
unknown committed
1129 1130 1131
	    return(FLOAT_NUM);
	  }
	}
1132
        lip->yyUnget();
unknown's avatar
unknown committed
1133
      }
unknown's avatar
unknown committed
1134
      // fall through
1135
    case MY_LEX_IDENT_START:			// We come here after '.'
1136
      result_state= IDENT;
unknown's avatar
unknown committed
1137
#if defined(USE_MB) && defined(USE_MB_IDENT)
1138
      if (use_mb(cs))
unknown's avatar
unknown committed
1139
      {
1140
	result_state= IDENT_QUOTED;
1141
        while (ident_map[c=lip->yyGet()])
unknown's avatar
unknown committed
1142
        {
1143
          if (my_mbcharlen(cs, c) > 1)
unknown's avatar
unknown committed
1144 1145
          {
            int l;
1146 1147 1148
            if ((l = my_ismbchar(cs,
                                 lip->get_ptr() -1,
                                 lip->get_end_of_query())) == 0)
unknown's avatar
unknown committed
1149
              break;
1150
            lip->skip_binary(l-1);
unknown's avatar
unknown committed
1151 1152 1153 1154 1155
          }
        }
      }
      else
#endif
unknown's avatar
unknown committed
1156
      {
Staale Smedseng's avatar
Staale Smedseng committed
1157
        for (result_state=0; ident_map[c= lip->yyGet()]; result_state|= c) ;
unknown's avatar
unknown committed
1158 1159 1160
        /* If there were non-ASCII characters, mark that we must convert */
        result_state= result_state & 0x80 ? IDENT_QUOTED : IDENT;
      }
1161
      if (c == '.' && ident_map[lip->yyPeek()])
1162
	lip->next_state=MY_LEX_IDENT_SEP;// Next is '.'
unknown's avatar
unknown committed
1163

1164
      yylval->lex_str= get_token(lip, 0, lip->yyLength());
unknown's avatar
unknown committed
1165 1166 1167 1168 1169

      lip->body_utf8_append(lip->m_cpp_text_start);

      lip->body_utf8_append_literal(thd, &yylval->lex_str, cs,
                                    lip->m_cpp_text_end);
unknown's avatar
unknown committed
1170

1171
      return(result_state);
unknown's avatar
unknown committed
1172

1173
    case MY_LEX_USER_VARIABLE_DELIMITER:	// Found quote char
1174
    {
1175 1176
      uint double_quotes= 0;
      char quote_char= c;                       // Used char
1177
      while ((c=lip->yyGet()))
unknown's avatar
unknown committed
1178
      {
1179 1180
	int var_length;
	if ((var_length= my_mbcharlen(cs, c)) == 1)
1181 1182 1183
	{
	  if (c == quote_char)
	  {
1184
            if (lip->yyPeek() != quote_char)
1185
	      break;
1186
            c=lip->yyGet();
1187 1188 1189
	    double_quotes++;
	    continue;
	  }
1190 1191
	}
#ifdef USE_MB
Davi Arnaut's avatar
Davi Arnaut committed
1192
        else if (use_mb(cs))
1193
        {
Davi Arnaut's avatar
Davi Arnaut committed
1194 1195 1196
          if ((var_length= my_ismbchar(cs, lip->get_ptr() - 1,
                                       lip->get_end_of_query())))
            lip->skip_binary(var_length-1);
1197
        }
1198
#endif
unknown's avatar
unknown committed
1199
      }
1200
      if (double_quotes)
1201
	yylval->lex_str=get_quoted_token(lip, 1,
1202
                                         lip->yyLength() - double_quotes -1,
1203 1204
					 quote_char);
      else
1205
        yylval->lex_str=get_token(lip, 1, lip->yyLength() -1);
1206
      if (c == quote_char)
1207
        lip->yySkip();                  // Skip end `
1208
      lip->next_state= MY_LEX_START;
unknown's avatar
unknown committed
1209 1210 1211 1212 1213 1214

      lip->body_utf8_append(lip->m_cpp_text_start);

      lip->body_utf8_append_literal(thd, &yylval->lex_str, cs,
                                    lip->m_cpp_text_end);

1215
      return(IDENT_QUOTED);
1216
    }
1217
    case MY_LEX_INT_OR_REAL:		// Complete int or incomplete real
unknown's avatar
unknown committed
1218 1219
      if (c != '.')
      {					// Found complete integer number.
1220
        yylval->lex_str=get_token(lip, 0, lip->yyLength());
1221
	return int_token(yylval->lex_str.str, (uint) yylval->lex_str.length);
unknown's avatar
unknown committed
1222 1223
      }
      // fall through
1224
    case MY_LEX_REAL:			// Incomplete real number
1225
      while (my_isdigit(cs,c = lip->yyGet())) ;
unknown's avatar
unknown committed
1226 1227 1228

      if (c == 'e' || c == 'E')
      {
1229
        c = lip->yyGet();
unknown's avatar
unknown committed
1230
	if (c == '-' || c == '+')
1231
          c = lip->yyGet();                     // Skip sign
1232
	if (!my_isdigit(cs,c))
unknown's avatar
unknown committed
1233
	{				// No digit after sign
1234
	  state= MY_LEX_CHAR;
unknown's avatar
unknown committed
1235 1236
	  break;
	}
1237 1238
        while (my_isdigit(cs,lip->yyGet())) ;
        yylval->lex_str=get_token(lip, 0, lip->yyLength());
unknown's avatar
unknown committed
1239 1240
	return(FLOAT_NUM);
      }
1241
      yylval->lex_str=get_token(lip, 0, lip->yyLength());
unknown's avatar
unknown committed
1242
      return(DECIMAL_NUM);
unknown's avatar
unknown committed
1243

1244
    case MY_LEX_HEX_NUMBER:		// Found x'hexstring'
1245 1246 1247 1248 1249 1250 1251 1252
      lip->yySkip();                    // Accept opening '
      while (my_isxdigit(cs, (c= lip->yyGet()))) ;
      if (c != '\'')
        return(ABORT_SYM);              // Illegal hex constant
      lip->yySkip();                    // Accept closing '
      length= lip->yyLength();          // Length of hexnum+3
      if ((length % 2) == 0)
        return(ABORT_SYM);              // odd number of hex digits
1253 1254 1255
      yylval->lex_str=get_token(lip,
                                2,          // skip x'
                                length-3);  // don't count x' and last '
1256 1257
      return (HEX_NUM);

unknown's avatar
unknown committed
1258
    case MY_LEX_BIN_NUMBER:           // Found b'bin-string'
1259
      lip->yySkip();                  // Accept opening '
Staale Smedseng's avatar
Staale Smedseng committed
1260
      while ((c= lip->yyGet()) == '0' || c == '1') ;
unknown's avatar
unknown committed
1261
      if (c != '\'')
1262 1263 1264
        return(ABORT_SYM);            // Illegal hex constant
      lip->yySkip();                  // Accept closing '
      length= lip->yyLength();        // Length of bin-num + 3
1265 1266 1267 1268
      yylval->lex_str= get_token(lip,
                                 2,         // skip b'
                                 length-3); // don't count b' and last '
      return (BIN_NUM);
unknown's avatar
unknown committed
1269

1270
    case MY_LEX_CMP_OP:			// Incomplete comparison operator
1271 1272 1273 1274
      if (state_map[lip->yyPeek()] == MY_LEX_CMP_OP ||
          state_map[lip->yyPeek()] == MY_LEX_LONG_CMP_OP)
        lip->yySkip();
      if ((tokval = find_keyword(lip, lip->yyLength() + 1, 0)))
unknown's avatar
unknown committed
1275
      {
1276
	lip->next_state= MY_LEX_START;	// Allow signed numbers
unknown's avatar
unknown committed
1277 1278
	return(tokval);
      }
1279
      state = MY_LEX_CHAR;		// Something fishy found
unknown's avatar
unknown committed
1280 1281
      break;

1282
    case MY_LEX_LONG_CMP_OP:		// Incomplete comparison operator
1283 1284
      if (state_map[lip->yyPeek()] == MY_LEX_CMP_OP ||
          state_map[lip->yyPeek()] == MY_LEX_LONG_CMP_OP)
unknown's avatar
unknown committed
1285
      {
1286 1287 1288
        lip->yySkip();
        if (state_map[lip->yyPeek()] == MY_LEX_CMP_OP)
          lip->yySkip();
unknown's avatar
unknown committed
1289
      }
1290
      if ((tokval = find_keyword(lip, lip->yyLength() + 1, 0)))
unknown's avatar
unknown committed
1291
      {
1292
	lip->next_state= MY_LEX_START;	// Found long op
unknown's avatar
unknown committed
1293 1294
	return(tokval);
      }
1295
      state = MY_LEX_CHAR;		// Something fishy found
unknown's avatar
unknown committed
1296 1297
      break;

1298
    case MY_LEX_BOOL:
1299
      if (c != lip->yyPeek())
unknown's avatar
unknown committed
1300
      {
1301
	state=MY_LEX_CHAR;
unknown's avatar
unknown committed
1302 1303
	break;
      }
1304
      lip->yySkip();
1305 1306
      tokval = find_keyword(lip,2,0);	// Is a bool operator
      lip->next_state= MY_LEX_START;	// Allow signed numbers
unknown's avatar
unknown committed
1307 1308
      return(tokval);

1309
    case MY_LEX_STRING_OR_DELIMITER:
1310
      if (thd->variables.sql_mode & MODE_ANSI_QUOTES)
1311
      {
1312
	state= MY_LEX_USER_VARIABLE_DELIMITER;
1313 1314 1315
	break;
      }
      /* " used for strings */
1316
    case MY_LEX_STRING:			// Incomplete text string
1317
      if (!(yylval->lex_str.str = get_text(lip, 1, 1)))
unknown's avatar
unknown committed
1318
      {
1319
	state= MY_LEX_CHAR;		// Read char by char
unknown's avatar
unknown committed
1320 1321
	break;
      }
1322
      yylval->lex_str.length=lip->yytoklen;
unknown's avatar
unknown committed
1323 1324 1325 1326 1327 1328 1329 1330 1331

      lip->body_utf8_append(lip->m_cpp_text_start);

      lip->body_utf8_append_literal(thd, &yylval->lex_str,
        lip->m_underscore_cs ? lip->m_underscore_cs : cs,
        lip->m_cpp_text_end);

      lip->m_underscore_cs= NULL;

1332
      lex->text_string_is_7bit= (lip->tok_bitmap & 0x80) ? 0 : 1;
unknown's avatar
unknown committed
1333 1334
      return(TEXT_STRING);

1335
    case MY_LEX_COMMENT:			//  Comment
unknown's avatar
unknown committed
1336
      lex->select_lex.options|= OPTION_FOUND_COMMENT;
1337 1338
      while ((c = lip->yyGet()) != '\n' && c) ;
      lip->yyUnget();                   // Safety against eof
1339
      state = MY_LEX_START;		// Try again
unknown's avatar
unknown committed
1340
      break;
1341
    case MY_LEX_LONG_COMMENT:		/* Long C comment? */
1342
      if (lip->yyPeek() != '*')
unknown's avatar
unknown committed
1343
      {
1344
	state=MY_LEX_CHAR;		// Probable division
unknown's avatar
unknown committed
1345 1346
	break;
      }
unknown's avatar
unknown committed
1347
      lex->select_lex.options|= OPTION_FOUND_COMMENT;
1348 1349 1350
      /* Reject '/' '*', since we might need to turn off the echo */
      lip->yyUnget();

1351 1352
      lip->save_in_comment_state();

1353
      if (lip->yyPeekn(2) == '!')
unknown's avatar
unknown committed
1354
      {
1355 1356
        lip->in_comment= DISCARD_COMMENT;
        /* Accept '/' '*' '!', but do not keep this marker. */
unknown's avatar
unknown committed
1357
        lip->set_echo(FALSE);
1358 1359 1360 1361 1362 1363 1364
        lip->yySkip();
        lip->yySkip();
        lip->yySkip();

        /*
          The special comment format is very strict:
          '/' '*' '!', followed by exactly
1365 1366 1367 1368
          1 digit (major), 2 digits (minor), then 2 digits (dot).
          32302 -> 3.23.02
          50032 -> 5.0.32
          50114 -> 5.1.14
1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386
        */
        char version_str[6];
        version_str[0]= lip->yyPeekn(0);
        version_str[1]= lip->yyPeekn(1);
        version_str[2]= lip->yyPeekn(2);
        version_str[3]= lip->yyPeekn(3);
        version_str[4]= lip->yyPeekn(4);
        version_str[5]= 0;
        if (  my_isdigit(cs, version_str[0])
           && my_isdigit(cs, version_str[1])
           && my_isdigit(cs, version_str[2])
           && my_isdigit(cs, version_str[3])
           && my_isdigit(cs, version_str[4])
           )
        {
          ulong version;
          version=strtol(version_str, NULL, 10);

1387
          /* Accept 'M' 'm' 'm' 'd' 'd' */
1388 1389 1390 1391 1392
          lip->yySkipn(5);

          if (version <= MYSQL_VERSION_ID)
          {
            /* Expand the content of the special comment as real code */
unknown's avatar
unknown committed
1393
            lip->set_echo(TRUE);
1394
            state=MY_LEX_START;
1395 1396 1397 1398 1399 1400
            break;  /* Do not treat contents as a comment.  */
          }
          else
          {
            comment_closed= ! consume_comment(lip, 1);
            /* version allowed to have one level of comment inside. */
1401 1402 1403 1404
          }
        }
        else
        {
1405
          /* Not a version comment. */
1406
          state=MY_LEX_START;
unknown's avatar
unknown committed
1407
          lip->set_echo(TRUE);
1408 1409
          break;
        }
unknown's avatar
unknown committed
1410
      }
1411
      else
unknown's avatar
unknown committed
1412
      {
1413 1414 1415
        lip->in_comment= PRESERVE_COMMENT;
        lip->yySkip();                  // Accept /
        lip->yySkip();                  // Accept *
1416 1417
        comment_closed= ! consume_comment(lip, 0);
        /* regular comments can have zero comments inside. */
unknown's avatar
unknown committed
1418
      }
1419 1420 1421 1422 1423
      /*
        Discard:
        - regular '/' '*' comments,
        - special comments '/' '*' '!' for a future version,
        by scanning until we find a closing '*' '/' marker.
1424 1425 1426 1427 1428 1429 1430 1431 1432

        Nesting regular comments isn't allowed.  The first 
        '*' '/' returns the parser to the previous state.

        /#!VERSI oned containing /# regular #/ is allowed #/

		Inside one versioned comment, another versioned comment
		is treated as a regular discardable comment.  It gets
		no special parsing.
1433
      */
1434

1435 1436 1437
      /* Unbalanced comments with a missing '*' '/' are a syntax error */
      if (! comment_closed)
        return (ABORT_SYM);
1438
      state = MY_LEX_START;             // Try again
1439
      lip->restore_in_comment_state();
unknown's avatar
unknown committed
1440
      break;
1441
    case MY_LEX_END_LONG_COMMENT:
1442
      if ((lip->in_comment != NO_COMMENT) && lip->yyPeek() == '/')
unknown's avatar
unknown committed
1443
      {
1444 1445 1446 1447 1448 1449
        /* Reject '*' '/' */
        lip->yyUnget();
        /* Accept '*' '/', with the proper echo */
        lip->set_echo(lip->in_comment == PRESERVE_COMMENT);
        lip->yySkipn(2);
        /* And start recording the tokens again */
unknown's avatar
unknown committed
1450
        lip->set_echo(TRUE);
1451 1452
        lip->in_comment=NO_COMMENT;
        state=MY_LEX_START;
unknown's avatar
unknown committed
1453 1454
      }
      else
1455
	state=MY_LEX_CHAR;		// Return '*'
unknown's avatar
unknown committed
1456
      break;
1457
    case MY_LEX_SET_VAR:		// Check if ':='
1458
      if (lip->yyPeek() != '=')
unknown's avatar
unknown committed
1459
      {
1460
	state=MY_LEX_CHAR;		// Return ':'
unknown's avatar
unknown committed
1461 1462
	break;
      }
1463
      lip->yySkip();
unknown's avatar
unknown committed
1464
      return (SET_VAR);
1465
    case MY_LEX_SEMICOLON:			// optional line terminator
1466 1467
      state= MY_LEX_CHAR;               // Return ';'
      break;
1468
    case MY_LEX_EOL:
1469
      if (lip->eof())
unknown's avatar
unknown committed
1470
      {
1471
        lip->yyUnget();                 // Reject the last '\0'
unknown's avatar
unknown committed
1472
        lip->set_echo(FALSE);
1473
        lip->yySkip();
unknown's avatar
unknown committed
1474
        lip->set_echo(TRUE);
1475 1476 1477
        /* Unbalanced comments with a missing '*' '/' are a syntax error */
        if (lip->in_comment != NO_COMMENT)
          return (ABORT_SYM);
1478 1479
        lip->next_state=MY_LEX_END;     // Mark for next loop
        return(END_OF_INPUT);
unknown's avatar
unknown committed
1480 1481 1482
      }
      state=MY_LEX_CHAR;
      break;
1483
    case MY_LEX_END:
1484
      lip->next_state=MY_LEX_END;
unknown's avatar
unknown committed
1485
      return(0);			// We found end of input last time
1486

1487
      /* Actually real shouldn't start with . but allow them anyhow */
1488
    case MY_LEX_REAL_OR_POINT:
1489
      if (my_isdigit(cs,lip->yyPeek()))
1490
	state = MY_LEX_REAL;		// Real
unknown's avatar
unknown committed
1491 1492
      else
      {
1493
	state= MY_LEX_IDENT_SEP;	// return '.'
1494
        lip->yyUnget();                 // Put back '.'
unknown's avatar
unknown committed
1495 1496
      }
      break;
1497
    case MY_LEX_USER_END:		// end '@' of user@hostname
1498
      switch (state_map[lip->yyPeek()]) {
1499 1500 1501
      case MY_LEX_STRING:
      case MY_LEX_USER_VARIABLE_DELIMITER:
      case MY_LEX_STRING_OR_DELIMITER:
unknown's avatar
unknown committed
1502
	break;
1503
      case MY_LEX_USER_END:
1504
	lip->next_state=MY_LEX_SYSTEM_VAR;
unknown's avatar
unknown committed
1505 1506
	break;
      default:
1507
	lip->next_state=MY_LEX_HOSTNAME;
unknown's avatar
unknown committed
1508 1509
	break;
      }
1510
      yylval->lex_str.str=(char*) lip->get_ptr();
unknown's avatar
unknown committed
1511 1512
      yylval->lex_str.length=1;
      return((int) '@');
1513
    case MY_LEX_HOSTNAME:		// end '@' of user@hostname
1514
      for (c=lip->yyGet() ;
1515
	   my_isalnum(cs,c) || c == '.' || c == '_' ||  c == '$';
1516 1517
           c= lip->yyGet()) ;
      yylval->lex_str=get_token(lip, 0, lip->yyLength());
unknown's avatar
unknown committed
1518
      return(LEX_HOSTNAME);
1519
    case MY_LEX_SYSTEM_VAR:
1520
      yylval->lex_str.str=(char*) lip->get_ptr();
unknown's avatar
unknown committed
1521
      yylval->lex_str.length=1;
1522 1523
      lip->yySkip();                                    // Skip '@'
      lip->next_state= (state_map[lip->yyPeek()] ==
1524 1525 1526
			MY_LEX_USER_VARIABLE_DELIMITER ?
			MY_LEX_OPERATOR_OR_IDENT :
			MY_LEX_IDENT_OR_KEYWORD);
unknown's avatar
unknown committed
1527
      return((int) '@');
1528
    case MY_LEX_IDENT_OR_KEYWORD:
unknown's avatar
unknown committed
1529 1530 1531 1532 1533
      /*
	We come here when we have found two '@' in a row.
	We should now be able to handle:
	[(global | local | session) .]variable_name
      */
1534

Staale Smedseng's avatar
Staale Smedseng committed
1535
      for (result_state= 0; ident_map[c= lip->yyGet()]; result_state|= c) ;
unknown's avatar
unknown committed
1536 1537
      /* If there were non-ASCII characters, mark that we must convert */
      result_state= result_state & 0x80 ? IDENT_QUOTED : IDENT;
1538

unknown's avatar
unknown committed
1539
      if (c == '.')
1540
	lip->next_state=MY_LEX_IDENT_SEP;
1541 1542
      length= lip->yyLength();
      if (length == 0)
unknown's avatar
unknown committed
1543
        return(ABORT_SYM);              // Names must be nonempty.
1544
      if ((tokval= find_keyword(lip, length,0)))
unknown's avatar
unknown committed
1545
      {
1546
        lip->yyUnget();                         // Put back 'c'
unknown's avatar
unknown committed
1547 1548
	return(tokval);				// Was keyword
      }
1549
      yylval->lex_str=get_token(lip, 0, length);
unknown's avatar
unknown committed
1550 1551 1552 1553 1554 1555

      lip->body_utf8_append(lip->m_cpp_text_start);

      lip->body_utf8_append_literal(thd, &yylval->lex_str, cs,
                                    lip->m_cpp_text_end);

1556
      return(result_state);
unknown's avatar
unknown committed
1557 1558 1559
    }
  }
}
unknown's avatar
unknown committed
1560

1561

unknown's avatar
unknown committed
1562 1563 1564
/**
  Construct a copy of this object to be used for mysql_alter_table
  and mysql_create_table.
1565

unknown's avatar
unknown committed
1566 1567 1568 1569
  Historically, these two functions modify their Alter_info
  arguments. This behaviour breaks re-execution of prepared
  statements and stored procedures and is compensated by always
  supplying a copy of Alter_info to these functions.
1570

unknown's avatar
unknown committed
1571 1572
  @return You need to use check the error in THD for out
  of memory condition after calling this function.
1573 1574
*/

1575 1576 1577 1578 1579 1580 1581 1582 1583
Alter_info::Alter_info(const Alter_info &rhs, MEM_ROOT *mem_root)
  :drop_list(rhs.drop_list, mem_root),
  alter_list(rhs.alter_list, mem_root),
  key_list(rhs.key_list, mem_root),
  create_list(rhs.create_list, mem_root),
  flags(rhs.flags),
  keys_onoff(rhs.keys_onoff),
  tablespace_op(rhs.tablespace_op),
  partition_names(rhs.partition_names, mem_root),
1584
  num_parts(rhs.num_parts),
unknown's avatar
unknown committed
1585 1586 1587
  change_level(rhs.change_level),
  datetime_field(rhs.datetime_field),
  error_if_not_empty(rhs.error_if_not_empty)
1588
{
1589 1590 1591
  /*
    Make deep copies of used objects.
    This is not a fully deep copy - clone() implementations
unknown's avatar
unknown committed
1592
    of Alter_drop, Alter_column, Key, foreign_key, Key_part_spec
1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605
    do not copy string constants. At the same length the only
    reason we make a copy currently is that ALTER/CREATE TABLE
    code changes input Alter_info definitions, but string
    constants never change.
  */
  list_copy_and_replace_each_value(drop_list, mem_root);
  list_copy_and_replace_each_value(alter_list, mem_root);
  list_copy_and_replace_each_value(key_list, mem_root);
  list_copy_and_replace_each_value(create_list, mem_root);
  /* partition_names are not deeply copied currently */
}


1606 1607 1608 1609 1610 1611 1612
void trim_whitespace(CHARSET_INFO *cs, LEX_STRING *str)
{
  /*
    TODO:
    This code assumes that there are no multi-bytes characters
    that can be considered white-space.
  */
1613

1614 1615 1616 1617 1618
  while ((str->length > 0) && (my_isspace(cs, str->str[0])))
  {
    str->length --;
    str->str ++;
  }
1619

1620 1621 1622 1623 1624 1625 1626 1627
  /*
    FIXME:
    Also, parsing backward is not safe with multi bytes characters
  */
  while ((str->length > 0) && (my_isspace(cs, str->str[str->length-1])))
  {
    str->length --;
  }
1628 1629
}

1630

unknown's avatar
unknown committed
1631 1632 1633 1634 1635 1636
/*
  st_select_lex structures initialisations
*/

void st_select_lex_node::init_query()
{
1637
  options= 0;
1638
  sql_cache= SQL_CACHE_UNSPECIFIED;
1639
  linkage= UNSPECIFIED_TYPE;
1640 1641
  no_error= no_table_names_allowed= 0;
  uncacheable= 0;
unknown's avatar
unknown committed
1642 1643 1644 1645 1646 1647 1648 1649 1650
}

void st_select_lex_node::init_select()
{
}

void st_select_lex_unit::init_query()
{
  st_select_lex_node::init_query();
1651
  linkage= GLOBAL_OPTIONS_TYPE;
unknown's avatar
unknown committed
1652
  global_parameters= first_select();
1653 1654
  select_limit_cnt= HA_POS_ERROR;
  offset_limit_cnt= 0;
1655
  union_distinct= 0;
unknown's avatar
unknown committed
1656
  prepared= optimized= executed= 0;
unknown's avatar
unknown committed
1657
  item= 0;
1658 1659
  union_result= 0;
  table= 0;
unknown's avatar
unknown committed
1660
  fake_select_lex= 0;
1661
  cleaned= 0;
1662
  item_list.empty();
1663
  describe= 0;
1664
  found_rows_for_union= 0;
unknown's avatar
unknown committed
1665 1666 1667 1668 1669
}

void st_select_lex::init_query()
{
  st_select_lex_node::init_query();
1670
  table_list.empty();
1671 1672
  top_join_list.empty();
  join_list= &top_join_list;
1673
  embedding= leaf_tables= 0;
unknown's avatar
unknown committed
1674
  item_list.empty();
unknown's avatar
unknown committed
1675
  join= 0;
1676
  having= prep_having= where= prep_where= 0;
1677
  olap= UNSPECIFIED_OLAP_TYPE;
1678
  having_fix_field= 0;
1679 1680
  context.select_lex= this;
  context.init();
unknown's avatar
unknown committed
1681 1682 1683
  /*
    Add the name resolution context of the current (sub)query to the
    stack of contexts for the whole query.
1684 1685 1686 1687 1688
    TODO:
    push_context may return an error if there is no memory for a new
    element in the stack, however this method has no return value,
    thus push_context should be moved to a place where query
    initialization is checked for failure.
unknown's avatar
unknown committed
1689 1690
  */
  parent_lex->push_context(&context);
1691
  cond_count= between_count= with_wild= 0;
unknown's avatar
unknown committed
1692
  max_equal_elems= 0;
unknown's avatar
unknown committed
1693
  ref_pointer_array= 0;
unknown's avatar
unknown committed
1694
  select_n_where_fields= 0;
unknown's avatar
unknown committed
1695
  select_n_having_items= 0;
1696
  subquery_in_having= explicit_limit= 0;
1697
  is_item_list_lookup= 0;
1698
  first_execution= 1;
1699
  first_natural_join_processing= 1;
unknown's avatar
unknown committed
1700
  first_cond_optimization= 1;
1701
  parsing_place= NO_MATTER;
1702
  exclude_from_table_unique_test= no_wrap_view_item= FALSE;
unknown's avatar
unknown committed
1703
  nest_level= 0;
1704
  link_next= 0;
1705
  lock_option= TL_READ_DEFAULT;
unknown's avatar
unknown committed
1706 1707 1708 1709 1710
}

void st_select_lex::init_select()
{
  st_select_lex_node::init_select();
1711
  group_list.empty();
unknown's avatar
unknown committed
1712
  type= db= 0;
1713 1714 1715
  having= 0;
  table_join_options= 0;
  in_sum_expr= with_wild= 0;
unknown's avatar
unknown committed
1716
  options= 0;
1717
  sql_cache= SQL_CACHE_UNSPECIFIED;
1718
  braces= 0;
unknown's avatar
unknown committed
1719
  interval_list.empty();
unknown's avatar
unknown committed
1720
  ftfunc_list_alloc.empty();
unknown's avatar
unknown committed
1721
  inner_sum_func_list= 0;
unknown's avatar
unknown committed
1722
  ftfunc_list= &ftfunc_list_alloc;
unknown's avatar
unknown committed
1723
  linkage= UNSPECIFIED_TYPE;
unknown's avatar
unknown committed
1724 1725
  order_list.elements= 0;
  order_list.first= 0;
1726
  order_list.next= (uchar**) &order_list.first;
1727 1728 1729
  /* Set limit and offset to default values */
  select_limit= 0;      /* denotes the default limit = HA_POS_ERROR */
  offset_limit= 0;      /* denotes the default offset = 0 */
unknown's avatar
unknown committed
1730
  with_sum_func= 0;
1731
  is_correlated= 0;
1732 1733
  cur_pos_in_select_list= UNDEF_POS;
  non_agg_fields.empty();
1734
  cond_value= having_value= Item::COND_UNDEF;
1735
  inner_refs_list.empty();
1736
  full_group_by_flag= 0;
unknown's avatar
unknown committed
1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750
}

/*
  st_select_lex structures linking
*/

/* include on level down */
void st_select_lex_node::include_down(st_select_lex_node *upper)
{
  if ((next= upper->slave))
    next->prev= &next;
  prev= &upper->slave;
  upper->slave= this;
  master= upper;
unknown's avatar
unknown committed
1751
  slave= 0;
unknown's avatar
unknown committed
1752 1753
}

unknown's avatar
unknown committed
1754 1755
/*
  include on level down (but do not link)
unknown's avatar
unknown committed
1756

unknown's avatar
unknown committed
1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770
  SYNOPSYS
    st_select_lex_node::include_standalone()
    upper - reference on node underr which this node should be included
    ref - references on reference on this node
*/
void st_select_lex_node::include_standalone(st_select_lex_node *upper,
					    st_select_lex_node **ref)
{
  next= 0;
  prev= ref;
  master= upper;
  slave= 0;
}

unknown's avatar
unknown committed
1771 1772 1773 1774 1775 1776 1777 1778
/* include neighbour (on same level) */
void st_select_lex_node::include_neighbour(st_select_lex_node *before)
{
  if ((next= before->next))
    next->prev= &next;
  prev= &before->next;
  before->next= this;
  master= before->master;
unknown's avatar
unknown committed
1779
  slave= 0;
unknown's avatar
unknown committed
1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793
}

/* including in global SELECT_LEX list */
void st_select_lex_node::include_global(st_select_lex_node **plink)
{
  if ((link_next= *plink))
    link_next->link_prev= &link_next;
  link_prev= plink;
  *plink= this;
}

//excluding from global list (internal function)
void st_select_lex_node::fast_exclude()
{
unknown's avatar
unknown committed
1794
  if (link_prev)
unknown's avatar
unknown committed
1795 1796 1797 1798
  {
    if ((*link_prev= link_next))
      link_next->link_prev= link_prev;
  }
1799 1800 1801 1802
  // Remove slave structure
  for (; slave; slave= slave->next)
    slave->fast_exclude();
  
unknown's avatar
unknown committed
1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822
}

/*
  excluding select_lex structure (except first (first select can't be
  deleted, because it is most upper select))
*/
void st_select_lex_node::exclude()
{
  //exclude from global list
  fast_exclude();
  //exclude from other structures
  if ((*prev= next))
    next->prev= prev;
  /* 
     We do not need following statements, because prev pointer of first 
     list element point to master->slave
     if (master->slave == this)
       master->slave= next;
  */
}
1823

1824 1825 1826 1827 1828 1829 1830 1831 1832 1833

/*
  Exclude level of current unit from tree of SELECTs

  SYNOPSYS
    st_select_lex_unit::exclude_level()

  NOTE: units which belong to current will be brought up on level of
  currernt unit 
*/
unknown's avatar
unknown committed
1834 1835 1836
void st_select_lex_unit::exclude_level()
{
  SELECT_LEX_UNIT *units= 0, **units_last= &units;
unknown's avatar
unknown committed
1837
  for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
unknown's avatar
unknown committed
1838
  {
unknown's avatar
unknown committed
1839
    // unlink current level from global SELECTs list
unknown's avatar
unknown committed
1840 1841
    if (sl->link_prev && (*sl->link_prev= sl->link_next))
      sl->link_next->link_prev= sl->link_prev;
unknown's avatar
unknown committed
1842 1843

    // bring up underlay levels
unknown's avatar
unknown committed
1844 1845
    SELECT_LEX_UNIT **last= 0;
    for (SELECT_LEX_UNIT *u= sl->first_inner_unit(); u; u= u->next_unit())
unknown's avatar
unknown committed
1846 1847
    {
      u->master= master;
unknown's avatar
unknown committed
1848
      last= (SELECT_LEX_UNIT**)&(u->next);
unknown's avatar
unknown committed
1849
    }
unknown's avatar
unknown committed
1850 1851 1852 1853 1854 1855 1856 1857
    if (last)
    {
      (*units_last)= sl->first_inner_unit();
      units_last= last;
    }
  }
  if (units)
  {
unknown's avatar
unknown committed
1858
    // include brought up levels in place of current
unknown's avatar
unknown committed
1859 1860
    (*prev)= units;
    (*units_last)= (SELECT_LEX_UNIT*)next;
unknown's avatar
unknown committed
1861 1862 1863
    if (next)
      next->prev= (SELECT_LEX_NODE**)units_last;
    units->prev= prev;
unknown's avatar
unknown committed
1864 1865
  }
  else
unknown's avatar
unknown committed
1866 1867
  {
    // exclude currect unit from list of nodes
unknown's avatar
unknown committed
1868
    (*prev)= next;
unknown's avatar
unknown committed
1869 1870 1871
    if (next)
      next->prev= prev;
  }
unknown's avatar
unknown committed
1872 1873
}

1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884

/*
  Exclude subtree of current unit from tree of SELECTs

  SYNOPSYS
    st_select_lex_unit::exclude_tree()
*/
void st_select_lex_unit::exclude_tree()
{
  for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
  {
unknown's avatar
unknown committed
1885
    // unlink current level from global SELECTs list
1886 1887 1888
    if (sl->link_prev && (*sl->link_prev= sl->link_next))
      sl->link_next->link_prev= sl->link_prev;

unknown's avatar
unknown committed
1889
    // unlink underlay levels
1890 1891 1892 1893 1894
    for (SELECT_LEX_UNIT *u= sl->first_inner_unit(); u; u= u->next_unit())
    {
      u->exclude_level();
    }
  }
unknown's avatar
unknown committed
1895
  // exclude currect unit from list of nodes
1896
  (*prev)= next;
unknown's avatar
unknown committed
1897 1898
  if (next)
    next->prev= prev;
1899 1900 1901
}


unknown's avatar
unknown committed
1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913
/*
  st_select_lex_node::mark_as_dependent mark all st_select_lex struct from 
  this to 'last' as dependent

  SYNOPSIS
    last - pointer to last st_select_lex struct, before wich all 
           st_select_lex have to be marked as dependent

  NOTE
    'last' should be reachable from this st_select_lex_node
*/

unknown's avatar
unknown committed
1914
void st_select_lex::mark_as_dependent(st_select_lex *last)
unknown's avatar
unknown committed
1915 1916 1917 1918 1919
{
  /*
    Mark all selects from resolved to 1 before select where was
    found table as depended (of select where was found table)
  */
unknown's avatar
unknown committed
1920
  for (SELECT_LEX *s= this;
1921
       s && s != last;
unknown's avatar
unknown committed
1922
       s= s->outer_select())
1923
    if (!(s->uncacheable & UNCACHEABLE_DEPENDENT))
unknown's avatar
unknown committed
1924 1925
    {
      // Select is dependent of outer select
1926 1927
      s->uncacheable= (s->uncacheable & ~UNCACHEABLE_UNITED) |
                       UNCACHEABLE_DEPENDENT;
1928
      SELECT_LEX_UNIT *munit= s->master_unit();
1929 1930 1931 1932 1933 1934 1935 1936
      munit->uncacheable= (munit->uncacheable & ~UNCACHEABLE_UNITED) |
                       UNCACHEABLE_DEPENDENT;
      for (SELECT_LEX *sl= munit->first_select(); sl ; sl= sl->next_select())
      {
        if (sl != s &&
            !(sl->uncacheable & (UNCACHEABLE_DEPENDENT | UNCACHEABLE_UNITED)))
          sl->uncacheable|= UNCACHEABLE_UNITED;
      }
unknown's avatar
unknown committed
1937
    }
1938 1939
  is_correlated= TRUE;
  this->master_unit()->item->is_correlated= TRUE;
unknown's avatar
unknown committed
1940 1941
}

1942 1943 1944 1945 1946
bool st_select_lex_node::set_braces(bool value)      { return 1; }
bool st_select_lex_node::inc_in_sum_expr()           { return 1; }
uint st_select_lex_node::get_in_sum_expr()           { return 0; }
TABLE_LIST* st_select_lex_node::get_table_list()     { return 0; }
List<Item>* st_select_lex_node::get_item_list()      { return 0; }
1947
TABLE_LIST *st_select_lex_node::add_table_to_list (THD *thd, Table_ident *table,
1948
						  LEX_STRING *alias,
unknown's avatar
unknown committed
1949
						  ulong table_join_options,
1950
						  thr_lock_type flags,
unknown's avatar
unknown committed
1951
						  List<Index_hint> *hints,
unknown's avatar
unknown committed
1952
                                                  LEX_STRING *option)
1953 1954 1955
{
  return 0;
}
unknown's avatar
unknown committed
1956 1957 1958 1959 1960 1961 1962 1963
ulong st_select_lex_node::get_table_join_options()
{
  return 0;
}

/*
  prohibit using LIMIT clause
*/
unknown's avatar
unknown committed
1964
bool st_select_lex::test_limit()
unknown's avatar
unknown committed
1965
{
1966
  if (select_limit != 0)
unknown's avatar
unknown committed
1967 1968
  {
    my_error(ER_NOT_SUPPORTED_YET, MYF(0),
unknown's avatar
unknown committed
1969
             "LIMIT & IN/ALL/ANY/SOME subquery");
unknown's avatar
unknown committed
1970 1971 1972 1973
    return(1);
  }
  return(0);
}
1974

1975

1976 1977 1978 1979 1980
st_select_lex_unit* st_select_lex_unit::master_unit()
{
    return this;
}

1981

1982 1983 1984 1985 1986
st_select_lex* st_select_lex_unit::outer_select()
{
  return (st_select_lex*) master;
}

1987

unknown's avatar
unknown committed
1988
bool st_select_lex::add_order_to_list(THD *thd, Item *item, bool asc)
unknown's avatar
unknown committed
1989
{
unknown's avatar
unknown committed
1990
  return add_to_list(thd, order_list, item, asc);
unknown's avatar
unknown committed
1991
}
1992

1993

unknown's avatar
unknown committed
1994
bool st_select_lex::add_item_to_list(THD *thd, Item *item)
1995
{
1996
  DBUG_ENTER("st_select_lex::add_item_to_list");
unknown's avatar
unknown committed
1997
  DBUG_PRINT("info", ("Item: 0x%lx", (long) item));
1998
  DBUG_RETURN(item_list.push_back(item));
1999 2000
}

2001

unknown's avatar
unknown committed
2002
bool st_select_lex::add_group_to_list(THD *thd, Item *item, bool asc)
2003
{
unknown's avatar
unknown committed
2004
  return add_to_list(thd, group_list, item, asc);
2005 2006
}

2007

2008 2009 2010 2011 2012
bool st_select_lex::add_ftfunc_to_list(Item_func_match *func)
{
  return !func || ftfunc_list->push_back(func); // end of memory?
}

2013

2014 2015 2016 2017 2018
st_select_lex_unit* st_select_lex::master_unit()
{
  return (st_select_lex_unit*) master;
}

2019

2020 2021 2022 2023 2024
st_select_lex* st_select_lex::outer_select()
{
  return (st_select_lex*) master->get_master();
}

2025

2026 2027 2028 2029 2030 2031
bool st_select_lex::set_braces(bool value)
{
  braces= value;
  return 0; 
}

2032

2033 2034 2035 2036 2037 2038
bool st_select_lex::inc_in_sum_expr()
{
  in_sum_expr++;
  return 0;
}

2039

2040 2041 2042 2043 2044
uint st_select_lex::get_in_sum_expr()
{
  return in_sum_expr;
}

2045

2046 2047 2048 2049 2050 2051 2052 2053 2054 2055
TABLE_LIST* st_select_lex::get_table_list()
{
  return (TABLE_LIST*) table_list.first;
}

List<Item>* st_select_lex::get_item_list()
{
  return &item_list;
}

unknown's avatar
unknown committed
2056 2057 2058 2059 2060
ulong st_select_lex::get_table_join_options()
{
  return table_join_options;
}

2061

unknown's avatar
unknown committed
2062 2063 2064 2065
bool st_select_lex::setup_ref_array(THD *thd, uint order_group_num)
{
  if (ref_pointer_array)
    return 0;
2066 2067 2068 2069 2070

  /*
    We have to create array in prepared statement memory if it is
    prepared statement
  */
unknown's avatar
unknown committed
2071
  Query_arena *arena= thd->stmt_arena;
unknown's avatar
unknown committed
2072
  return (ref_pointer_array=
2073 2074 2075
          (Item **)arena->alloc(sizeof(Item*) * (n_child_sum_items +
                                                 item_list.elements +
                                                 select_n_having_items +
unknown's avatar
unknown committed
2076
                                                 select_n_where_fields +
2077
                                                 order_group_num)*5)) == 0;
unknown's avatar
unknown committed
2078 2079
}

2080

2081
void st_select_lex_unit::print(String *str, enum_query_type query_type)
unknown's avatar
unknown committed
2082
{
2083
  bool union_all= !union_distinct;
unknown's avatar
unknown committed
2084 2085 2086 2087
  for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
  {
    if (sl != first_select())
    {
2088
      str->append(STRING_WITH_LEN(" union "));
2089
      if (union_all)
2090
	str->append(STRING_WITH_LEN("all "));
2091
      else if (union_distinct == sl)
2092
        union_all= TRUE;
unknown's avatar
unknown committed
2093 2094 2095
    }
    if (sl->braces)
      str->append('(');
2096
    sl->print(thd, str, query_type);
unknown's avatar
unknown committed
2097 2098 2099 2100 2101 2102 2103
    if (sl->braces)
      str->append(')');
  }
  if (fake_select_lex == global_parameters)
  {
    if (fake_select_lex->order_list.elements)
    {
2104
      str->append(STRING_WITH_LEN(" order by "));
2105 2106 2107 2108
      fake_select_lex->print_order(
        str,
        (ORDER *) fake_select_lex->order_list.first,
        query_type);
unknown's avatar
unknown committed
2109
    }
2110
    fake_select_lex->print_limit(thd, str, query_type);
unknown's avatar
unknown committed
2111 2112 2113 2114
  }
}


2115 2116 2117
void st_select_lex::print_order(String *str,
                                ORDER *order,
                                enum_query_type query_type)
unknown's avatar
unknown committed
2118 2119 2120
{
  for (; order; order= order->next)
  {
2121 2122 2123
    if (order->counter_used)
    {
      char buffer[20];
2124 2125
      size_t length= my_snprintf(buffer, 20, "%d", order->counter);
      str->append(buffer, (uint) length);
2126 2127
    }
    else
2128
      (*order->item)->print(str, query_type);
unknown's avatar
unknown committed
2129
    if (!order->asc)
2130
      str->append(STRING_WITH_LEN(" desc"));
unknown's avatar
unknown committed
2131 2132 2133 2134 2135
    if (order->next)
      str->append(',');
  }
}
 
2136

2137 2138 2139
void st_select_lex::print_limit(THD *thd,
                                String *str,
                                enum_query_type query_type)
unknown's avatar
unknown committed
2140
{
2141 2142 2143
  SELECT_LEX_UNIT *unit= master_unit();
  Item_subselect *item= unit->item;
  if (item && unit->global_parameters == this &&
unknown's avatar
VIEW  
unknown committed
2144 2145 2146 2147
      (item->substype() == Item_subselect::EXISTS_SUBS ||
       item->substype() == Item_subselect::IN_SUBS ||
       item->substype() == Item_subselect::ALL_SUBS))
  {
2148
    DBUG_ASSERT(!item->fixed ||
2149
                (select_limit->val_int() == LL(1) && offset_limit == 0));
unknown's avatar
VIEW  
unknown committed
2150 2151 2152
    return;
  }

2153
  if (explicit_limit)
unknown's avatar
unknown committed
2154
  {
2155
    str->append(STRING_WITH_LEN(" limit "));
unknown's avatar
unknown committed
2156 2157
    if (offset_limit)
    {
2158
      offset_limit->print(str, query_type);
unknown's avatar
unknown committed
2159 2160
      str->append(',');
    }
2161
    select_limit->print(str, query_type);
unknown's avatar
unknown committed
2162 2163 2164
  }
}

2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176
/**
  @brief Restore the LEX and THD in case of a parse error.

  This is a clean up call that is invoked by the Bison generated
  parser before returning an error from MYSQLparse. If your
  semantic actions manipulate with the global thread state (which
  is a very bad practice and should not normally be employed) and
  need a clean-up in case of error, and you can not use %destructor
  rule in the grammar file itself, this function should be used
  to implement the clean up.
*/

Konstantin Osipov's avatar
Konstantin Osipov committed
2177
void LEX::cleanup_lex_after_parse_error(THD *thd)
2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188
{
  /*
    Delete sphead for the side effect of restoring of the original
    LEX state, thd->lex, thd->mem_root and thd->free_list if they
    were replaced when parsing stored procedure statements.  We
    will never use sphead object after a parse error, so it's okay
    to delete it only for the sake of the side effect.
    TODO: make this functionality explicit in sp_head class.
    Sic: we must nullify the member of the main lex, not the
    current one that will be thrown away
  */
2189
  if (thd->lex->sphead)
2190 2191 2192 2193 2194
  {
    delete thd->lex->sphead;
    thd->lex->sphead= NULL;
  }
}
unknown's avatar
VIEW  
unknown committed
2195

2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215
/*
  Initialize (or reset) Query_tables_list object.

  SYNOPSIS
    reset_query_tables_list()
      init  TRUE  - we should perform full initialization of object with
                    allocating needed memory
            FALSE - object is already initialized so we should only reset
                    its state so it can be used for parsing/processing
                    of new statement

  DESCRIPTION
    This method initializes Query_tables_list so it can be used as part
    of LEX object for parsing/processing of statement. One can also use
    this method to reset state of already initialized Query_tables_list
    so it can be used for processing of new statement.
*/

void Query_tables_list::reset_query_tables_list(bool init)
{
unknown's avatar
unknown committed
2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226
  if (!init && query_tables)
  {
    TABLE_LIST *table= query_tables;
    for (;;)
    {
      delete table->view;
      if (query_tables_last == &table->next_global ||
          !(table= table->next_global))
        break;
    }
  }
2227 2228 2229 2230
  query_tables= 0;
  query_tables_last= &query_tables;
  query_tables_own_last= 0;
  if (init)
2231 2232 2233 2234 2235
  {
    /*
      We delay real initialization of hash (and therefore related
      memory allocation) until first insertion into this hash.
    */
Konstantin Osipov's avatar
Konstantin Osipov committed
2236
    my_hash_clear(&sroutines);
2237
  }
2238
  else if (sroutines.records)
2239 2240
  {
    /* Non-zero sroutines.records means that hash was initialized. */
2241
    my_hash_reset(&sroutines);
2242
  }
2243 2244 2245
  sroutines_list.empty();
  sroutines_list_own_last= sroutines_list.next;
  sroutines_list_own_elements= 0;
2246
  binlog_stmt_flags= 0;
2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258
}


/*
  Destroy Query_tables_list object with freeing all resources used by it.

  SYNOPSIS
    destroy_query_tables_list()
*/

void Query_tables_list::destroy_query_tables_list()
{
Konstantin Osipov's avatar
Konstantin Osipov committed
2259
  my_hash_free(&sroutines);
2260 2261 2262
}


2263 2264 2265 2266
/*
  Initialize LEX object.

  SYNOPSIS
Konstantin Osipov's avatar
Konstantin Osipov committed
2267
    LEX::LEX()
2268 2269 2270 2271 2272 2273 2274 2275 2276

  NOTE
    LEX object initialized with this constructor can be used as part of
    THD object for which one can safely call open_tables(), lock_tables()
    and close_thread_tables() functions. But it is not yet ready for
    statement parsing. On should use lex_start() function to prepare LEX
    for this.
*/

Konstantin Osipov's avatar
Konstantin Osipov committed
2277
LEX::LEX()
2278
  :result(0),
2279
   sql_command(SQLCOM_END), option_type(OPT_DEFAULT), is_lex_started(0)
2280
{
unknown's avatar
unknown committed
2281

unknown's avatar
unknown committed
2282 2283 2284 2285
  my_init_dynamic_array2(&plugins, sizeof(plugin_ref),
                         plugins_static_buffer,
                         INITIAL_LEX_PLUGIN_LIST_SIZE, 
                         INITIAL_LEX_PLUGIN_LIST_SIZE);
2286
  reset_query_tables_list(TRUE);
2287 2288 2289
}


unknown's avatar
VIEW  
unknown committed
2290
/*
2291
  Check whether the merging algorithm can be used on this VIEW
unknown's avatar
VIEW  
unknown committed
2292 2293

  SYNOPSIS
Konstantin Osipov's avatar
Konstantin Osipov committed
2294
    LEX::can_be_merged()
unknown's avatar
VIEW  
unknown committed
2295

2296
  DESCRIPTION
2297 2298 2299
    We can apply merge algorithm if it is single SELECT view  with
    subqueries only in WHERE clause (we do not count SELECTs of underlying
    views, and second level subqueries) and we have not grpouping, ordering,
2300 2301 2302
    HAVING clause, aggregate functions, DISTINCT clause, LIMIT clause and
    several underlying tables.

unknown's avatar
VIEW  
unknown committed
2303 2304 2305 2306 2307
  RETURN
    FALSE - only temporary table algorithm can be used
    TRUE  - merge algorithm can be used
*/

Konstantin Osipov's avatar
Konstantin Osipov committed
2308
bool LEX::can_be_merged()
unknown's avatar
VIEW  
unknown committed
2309 2310 2311 2312
{
  // TODO: do not forget implement case when select_lex.table_list.elements==0

  /* find non VIEW subqueries/unions */
2313 2314 2315
  bool selects_allow_merge= select_lex.next_select() == 0;
  if (selects_allow_merge)
  {
2316 2317 2318
    for (SELECT_LEX_UNIT *tmp_unit= select_lex.first_inner_unit();
         tmp_unit;
         tmp_unit= tmp_unit->next_unit())
2319
    {
2320 2321 2322 2323
      if (tmp_unit->first_select()->parent_lex == this &&
          (tmp_unit->item == 0 ||
           (tmp_unit->item->place() != IN_WHERE &&
            tmp_unit->item->place() != IN_ON)))
2324 2325 2326 2327 2328 2329 2330 2331
      {
        selects_allow_merge= 0;
        break;
      }
    }
  }

  return (selects_allow_merge &&
unknown's avatar
VIEW  
unknown committed
2332 2333
	  select_lex.group_list.elements == 0 &&
	  select_lex.having == 0 &&
2334
          select_lex.with_sum_func == 0 &&
2335
	  select_lex.table_list.elements >= 1 &&
unknown's avatar
VIEW  
unknown committed
2336
	  !(select_lex.options & SELECT_DISTINCT) &&
2337
          select_lex.select_limit == 0);
unknown's avatar
VIEW  
unknown committed
2338 2339
}

2340

unknown's avatar
VIEW  
unknown committed
2341
/*
2342
  check if command can use VIEW with MERGE algorithm (for top VIEWs)
unknown's avatar
VIEW  
unknown committed
2343 2344

  SYNOPSIS
Konstantin Osipov's avatar
Konstantin Osipov committed
2345
    LEX::can_use_merged()
unknown's avatar
VIEW  
unknown committed
2346

2347 2348 2349
  DESCRIPTION
    Only listed here commands can use merge algorithm in top level
    SELECT_LEX (for subqueries will be used merge algorithm if
Konstantin Osipov's avatar
Konstantin Osipov committed
2350
    LEX::can_not_use_merged() is not TRUE).
2351

unknown's avatar
VIEW  
unknown committed
2352 2353 2354 2355 2356
  RETURN
    FALSE - command can't use merged VIEWs
    TRUE  - VIEWs with MERGE algorithms can be used
*/

Konstantin Osipov's avatar
Konstantin Osipov committed
2357
bool LEX::can_use_merged()
unknown's avatar
VIEW  
unknown committed
2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370
{
  switch (sql_command)
  {
  case SQLCOM_SELECT:
  case SQLCOM_CREATE_TABLE:
  case SQLCOM_UPDATE:
  case SQLCOM_UPDATE_MULTI:
  case SQLCOM_DELETE:
  case SQLCOM_DELETE_MULTI:
  case SQLCOM_INSERT:
  case SQLCOM_INSERT_SELECT:
  case SQLCOM_REPLACE:
  case SQLCOM_REPLACE_SELECT:
2371
  case SQLCOM_LOAD:
unknown's avatar
VIEW  
unknown committed
2372 2373 2374 2375 2376 2377
    return TRUE;
  default:
    return FALSE;
  }
}

2378
/*
2379
  Check if command can't use merged views in any part of command
2380 2381

  SYNOPSIS
Konstantin Osipov's avatar
Konstantin Osipov committed
2382
    LEX::can_not_use_merged()
2383

2384 2385
  DESCRIPTION
    Temporary table algorithm will be used on all SELECT levels for queries
Konstantin Osipov's avatar
Konstantin Osipov committed
2386
    listed here (see also LEX::can_use_merged()).
2387

2388 2389 2390 2391 2392
  RETURN
    FALSE - command can't use merged VIEWs
    TRUE  - VIEWs with MERGE algorithms can be used
*/

Konstantin Osipov's avatar
Konstantin Osipov committed
2393
bool LEX::can_not_use_merged()
2394 2395 2396 2397 2398
{
  switch (sql_command)
  {
  case SQLCOM_CREATE_VIEW:
  case SQLCOM_SHOW_CREATE:
2399 2400 2401 2402 2403 2404
  /*
    SQLCOM_SHOW_FIELDS is necessary to make 
    information schema tables working correctly with views.
    see get_schema_tables_result function
  */
  case SQLCOM_SHOW_FIELDS:
2405 2406 2407 2408 2409 2410
    return TRUE;
  default:
    return FALSE;
  }
}

unknown's avatar
VIEW  
unknown committed
2411 2412 2413 2414 2415 2416 2417 2418 2419 2420
/*
  Detect that we need only table structure of derived table/view

  SYNOPSIS
    only_view_structure()

  RETURN
    TRUE yes, we need only structure
    FALSE no, we need data
*/
unknown's avatar
unknown committed
2421

Konstantin Osipov's avatar
Konstantin Osipov committed
2422
bool LEX::only_view_structure()
unknown's avatar
VIEW  
unknown committed
2423
{
2424
  switch (sql_command) {
unknown's avatar
VIEW  
unknown committed
2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438
  case SQLCOM_SHOW_CREATE:
  case SQLCOM_SHOW_TABLES:
  case SQLCOM_SHOW_FIELDS:
  case SQLCOM_REVOKE_ALL:
  case SQLCOM_REVOKE:
  case SQLCOM_GRANT:
  case SQLCOM_CREATE_VIEW:
    return TRUE;
  default:
    return FALSE;
  }
}


unknown's avatar
unknown committed
2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450
/*
  Should Items_ident be printed correctly

  SYNOPSIS
    need_correct_ident()

  RETURN
    TRUE yes, we need only structure
    FALSE no, we need data
*/


Konstantin Osipov's avatar
Konstantin Osipov committed
2451
bool LEX::need_correct_ident()
unknown's avatar
unknown committed
2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463
{
  switch(sql_command)
  {
  case SQLCOM_SHOW_CREATE:
  case SQLCOM_SHOW_TABLES:
  case SQLCOM_CREATE_VIEW:
    return TRUE;
  default:
    return FALSE;
  }
}

2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480
/*
  Get effective type of CHECK OPTION for given view

  SYNOPSIS
    get_effective_with_check()
    view    given view

  NOTE
    It have not sense to set CHECK OPTION for SELECT satement or subqueries,
    so we do not.

  RETURN
    VIEW_CHECK_NONE      no need CHECK OPTION
    VIEW_CHECK_LOCAL     CHECK OPTION LOCAL
    VIEW_CHECK_CASCADED  CHECK OPTION CASCADED
*/

Konstantin Osipov's avatar
Konstantin Osipov committed
2481
uint8 LEX::get_effective_with_check(TABLE_LIST *view)
2482 2483 2484 2485 2486 2487 2488
{
  if (view->select_lex->master_unit() == &unit &&
      which_check_option_applicable())
    return (uint8)view->with_check;
  return VIEW_CHECK_NONE;
}

unknown's avatar
unknown committed
2489

2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509
/**
  This method should be called only during parsing.
  It is aware of compound statements (stored routine bodies)
  and will initialize the destination with the default
  database of the stored routine, rather than the default
  database of the connection it is parsed in.
  E.g. if one has no current database selected, or current database 
  set to 'bar' and then issues:

  CREATE PROCEDURE foo.p1() BEGIN SELECT * FROM t1 END//

  t1 is meant to refer to foo.t1, not to bar.t1.

  This method is needed to support this rule.

  @return TRUE in case of error (parsing should be aborted, FALSE in
  case of success
*/

bool
Konstantin Osipov's avatar
Konstantin Osipov committed
2510
LEX::copy_db_to(char **p_db, size_t *p_db_length) const
2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526
{
  if (sphead)
  {
    DBUG_ASSERT(sphead->m_db.str && sphead->m_db.length);
    /*
      It is safe to assign the string by-pointer, both sphead and
      its statements reside in the same memory root.
    */
    *p_db= sphead->m_db.str;
    if (p_db_length)
      *p_db_length= sphead->m_db.length;
    return FALSE;
  }
  return thd->copy_db_to(p_db, p_db_length);
}

unknown's avatar
unknown committed
2527 2528 2529 2530 2531 2532 2533
/*
  initialize limit counters

  SYNOPSIS
    st_select_lex_unit::set_limit()
    values	- SELECT_LEX with initial values for counters
*/
unknown's avatar
VIEW  
unknown committed
2534

unknown's avatar
unknown committed
2535
void st_select_lex_unit::set_limit(st_select_lex *sl)
2536
{
2537
  ha_rows select_limit_val;
2538
  ulonglong val;
2539

unknown's avatar
unknown committed
2540
  DBUG_ASSERT(! thd->stmt_arena->is_stmt_prepare());
2541 2542 2543
  val= sl->select_limit ? sl->select_limit->val_uint() : HA_POS_ERROR;
  select_limit_val= (ha_rows)val;
#ifndef BIG_TABLES
2544
  /*
2545 2546 2547 2548 2549 2550
    Check for overflow : ha_rows can be smaller then ulonglong if
    BIG_TABLES is off.
    */
  if (val != (ulonglong)select_limit_val)
    select_limit_val= HA_POS_ERROR;
#endif
2551 2552 2553 2554 2555 2556 2557
  val= sl->offset_limit ? sl->offset_limit->val_uint() : ULL(0);
  offset_limit_cnt= (ha_rows)val;
#ifndef BIG_TABLES
  /* Check for truncation. */
  if (val != (ulonglong)offset_limit_cnt)
    offset_limit_cnt= HA_POS_ERROR;
#endif
2558 2559
  select_limit_cnt= select_limit_val + offset_limit_cnt;
  if (select_limit_cnt < select_limit_val)
2560 2561 2562
    select_limit_cnt= HA_POS_ERROR;		// no limit
}

unknown's avatar
unknown committed
2563

2564
/**
2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584
  @brief Set the initial purpose of this TABLE_LIST object in the list of used
    tables.

  We need to track this information on table-by-table basis, since when this
  table becomes an element of the pre-locked list, it's impossible to identify
  which SQL sub-statement it has been originally used in.

  E.g.:

  User request:                 SELECT * FROM t1 WHERE f1();
  FUNCTION f1():                DELETE FROM t2; RETURN 1;
  BEFORE DELETE trigger on t2:  INSERT INTO t3 VALUES (old.a);

  For this user request, the pre-locked list will contain t1, t2, t3
  table elements, each needed for different DML.

  The trigger event map is updated to reflect INSERT, UPDATE, DELETE,
  REPLACE, LOAD DATA, CREATE TABLE .. SELECT, CREATE TABLE ..
  REPLACE SELECT statements, and additionally ON DUPLICATE KEY UPDATE
  clause.
2585 2586
*/

Konstantin Osipov's avatar
Konstantin Osipov committed
2587
void LEX::set_trg_event_type_for_tables()
2588
{
2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687
  uint8 new_trg_event_map= 0;

  /*
    Some auxiliary operations
    (e.g. GRANT processing) create TABLE_LIST instances outside
    the parser. Additionally, some commands (e.g. OPTIMIZE) change
    the lock type for a table only after parsing is done. Luckily,
    these do not fire triggers and do not need to pre-load them.
    For these TABLE_LISTs set_trg_event_type is never called, and
    trg_event_map is always empty. That means that the pre-locking
    algorithm will ignore triggers defined on these tables, if
    any, and the execution will either fail with an assert in
    sql_trigger.cc or with an error that a used table was not
    pre-locked, in case of a production build.

    TODO: this usage pattern creates unnecessary module dependencies
    and should be rewritten to go through the parser.
    Table list instances created outside the parser in most cases
    refer to mysql.* system tables. It is not allowed to have
    a trigger on a system table, but keeping track of
    initialization provides extra safety in case this limitation
    is circumvented.
  */

  switch (sql_command) {
  case SQLCOM_LOCK_TABLES:
  /*
    On a LOCK TABLE, all triggers must be pre-loaded for this TABLE_LIST
    when opening an associated TABLE.
  */
    new_trg_event_map= static_cast<uint8>
                        (1 << static_cast<int>(TRG_EVENT_INSERT)) |
                      static_cast<uint8>
                        (1 << static_cast<int>(TRG_EVENT_UPDATE)) |
                      static_cast<uint8>
                        (1 << static_cast<int>(TRG_EVENT_DELETE));
    break;
  /*
    Basic INSERT. If there is an additional ON DUPLIATE KEY UPDATE
    clause, it will be handled later in this method.
  */
  case SQLCOM_INSERT:                           /* fall through */
  case SQLCOM_INSERT_SELECT:
  /*
    LOAD DATA ... INFILE is expected to fire BEFORE/AFTER INSERT
    triggers.
    If the statement also has REPLACE clause, it will be
    handled later in this method.
  */
  case SQLCOM_LOAD:                             /* fall through */
  /*
    REPLACE is semantically equivalent to INSERT. In case
    of a primary or unique key conflict, it deletes the old
    record and inserts a new one. So we also may need to
    fire ON DELETE triggers. This functionality is handled
    later in this method.
  */
  case SQLCOM_REPLACE:                          /* fall through */
  case SQLCOM_REPLACE_SELECT:
  /*
    CREATE TABLE ... SELECT defaults to INSERT if the table or
    view already exists. REPLACE option of CREATE TABLE ...
    REPLACE SELECT is handled later in this method.
  */
  case SQLCOM_CREATE_TABLE:
    new_trg_event_map|= static_cast<uint8>
                          (1 << static_cast<int>(TRG_EVENT_INSERT));
    break;
  /* Basic update and multi-update */
  case SQLCOM_UPDATE:                           /* fall through */
  case SQLCOM_UPDATE_MULTI:
    new_trg_event_map|= static_cast<uint8>
                          (1 << static_cast<int>(TRG_EVENT_UPDATE));
    break;
  /* Basic delete and multi-delete */
  case SQLCOM_DELETE:                           /* fall through */
  case SQLCOM_DELETE_MULTI:
    new_trg_event_map|= static_cast<uint8>
                          (1 << static_cast<int>(TRG_EVENT_DELETE));
    break;
  default:
    break;
  }

  switch (duplicates) {
  case DUP_UPDATE:
    new_trg_event_map|= static_cast<uint8>
                          (1 << static_cast<int>(TRG_EVENT_UPDATE));
    break;
  case DUP_REPLACE:
    new_trg_event_map|= static_cast<uint8>
                          (1 << static_cast<int>(TRG_EVENT_DELETE));
    break;
  case DUP_ERROR:
  default:
    break;
  }


2688 2689 2690 2691 2692 2693 2694 2695
  /*
    Do not iterate over sub-selects, only the tables in the outermost
    SELECT_LEX can be modified, if any.
  */
  TABLE_LIST *tables= select_lex.get_table_list();

  while (tables)
  {
2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706
    /*
      This is a fast check to filter out statements that do
      not change data, or tables  on the right side, in case of
      INSERT .. SELECT, CREATE TABLE .. SELECT and so on.
      Here we also filter out OPTIMIZE statement and non-updateable
      views, for which lock_type is TL_UNLOCK or TL_READ after
      parsing.
    */
    if (static_cast<int>(tables->lock_type) >=
        static_cast<int>(TL_WRITE_ALLOW_WRITE))
      tables->trg_event_map= new_trg_event_map;
2707 2708 2709 2710 2711
    tables= tables->next_local;
  }
}


2712
/*
2713 2714
  Unlink the first table from the global table list and the first table from
  outer select (lex->select_lex) local list
2715 2716 2717

  SYNOPSIS
    unlink_first_table()
2718
    link_to_local	Set to 1 if caller should link this table to local list
unknown's avatar
unknown committed
2719

unknown's avatar
VIEW  
unknown committed
2720
  NOTES
2721 2722
    We assume that first tables in both lists is the same table or the local
    list is empty.
2723 2724

  RETURN
2725
    0	If 'query_tables' == 0
unknown's avatar
VIEW  
unknown committed
2726
    unlinked table
2727
      In this case link_to_local is set.
unknown's avatar
unknown committed
2728

2729
*/
Konstantin Osipov's avatar
Konstantin Osipov committed
2730
TABLE_LIST *LEX::unlink_first_table(bool *link_to_local)
2731
{
unknown's avatar
VIEW  
unknown committed
2732 2733 2734 2735 2736 2737 2738 2739
  TABLE_LIST *first;
  if ((first= query_tables))
  {
    /*
      Exclude from global table list
    */
    if ((query_tables= query_tables->next_global))
      query_tables->prev_global= &query_tables;
2740 2741
    else
      query_tables_last= &query_tables;
unknown's avatar
VIEW  
unknown committed
2742 2743 2744 2745 2746 2747 2748
    first->next_global= 0;

    /*
      and from local list if it is not empty
    */
    if ((*link_to_local= test(select_lex.table_list.first)))
    {
2749 2750
      select_lex.context.table_list= 
        select_lex.context.first_name_resolution_table= first->next_local;
2751
      select_lex.table_list.first= (uchar*) (first->next_local);
unknown's avatar
VIEW  
unknown committed
2752 2753 2754
      select_lex.table_list.elements--;	//safety
      first->next_local= 0;
      /*
2755 2756
        Ensure that the global list has the same first table as the local
        list.
unknown's avatar
VIEW  
unknown committed
2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769
      */
      first_lists_tables_same();
    }
  }
  return first;
}


/*
  Bring first local table of first most outer select to first place in global
  table list

  SYNOPSYS
Konstantin Osipov's avatar
Konstantin Osipov committed
2770
     LEX::first_lists_tables_same()
unknown's avatar
VIEW  
unknown committed
2771 2772

  NOTES
2773 2774 2775 2776 2777 2778
    In many cases (for example, usual INSERT/DELETE/...) the first table of
    main SELECT_LEX have special meaning => check that it is the first table
    in global list and re-link to be first in the global list if it is
    necessary.  We need such re-linking only for queries with sub-queries in
    the select list, as only in this case tables of sub-queries will go to
    the global list first.
unknown's avatar
VIEW  
unknown committed
2779 2780
*/

Konstantin Osipov's avatar
Konstantin Osipov committed
2781
void LEX::first_lists_tables_same()
unknown's avatar
VIEW  
unknown committed
2782 2783 2784 2785
{
  TABLE_LIST *first_table= (TABLE_LIST*) select_lex.table_list.first;
  if (query_tables != first_table && first_table != 0)
  {
2786
    TABLE_LIST *next;
unknown's avatar
VIEW  
unknown committed
2787 2788
    if (query_tables_last == &first_table->next_global)
      query_tables_last= first_table->prev_global;
2789

2790
    if ((next= *first_table->prev_global= first_table->next_global))
unknown's avatar
VIEW  
unknown committed
2791 2792 2793 2794
      next->prev_global= first_table->prev_global;
    /* include in new place */
    first_table->next_global= query_tables;
    /*
2795 2796 2797
       We are sure that query_tables is not 0, because first_table was not
       first table in the global list => we can use
       query_tables->prev_global without check of query_tables
unknown's avatar
VIEW  
unknown committed
2798 2799 2800 2801 2802
    */
    query_tables->prev_global= &first_table->next_global;
    first_table->prev_global= &query_tables;
    query_tables= first_table;
  }
2803 2804
}

unknown's avatar
unknown committed
2805

2806
/*
unknown's avatar
unknown committed
2807
  Link table back that was unlinked with unlink_first_table()
2808 2809 2810

  SYNOPSIS
    link_first_table_back()
unknown's avatar
VIEW  
unknown committed
2811
    link_to_local	do we need link this table to local
2812 2813 2814 2815

  RETURN
    global list
*/
unknown's avatar
VIEW  
unknown committed
2816

Konstantin Osipov's avatar
Konstantin Osipov committed
2817
void LEX::link_first_table_back(TABLE_LIST *first,
unknown's avatar
VIEW  
unknown committed
2818
				   bool link_to_local)
2819
{
unknown's avatar
VIEW  
unknown committed
2820
  if (first)
2821
  {
unknown's avatar
VIEW  
unknown committed
2822 2823
    if ((first->next_global= query_tables))
      query_tables->prev_global= &first->next_global;
2824 2825
    else
      query_tables_last= &first->next_global;
unknown's avatar
VIEW  
unknown committed
2826 2827 2828 2829 2830
    query_tables= first;

    if (link_to_local)
    {
      first->next_local= (TABLE_LIST*) select_lex.table_list.first;
unknown's avatar
unknown committed
2831
      select_lex.context.table_list= first;
2832
      select_lex.table_list.first= (uchar*) first;
unknown's avatar
VIEW  
unknown committed
2833 2834 2835 2836 2837 2838
      select_lex.table_list.elements++;	//safety
    }
  }
}


2839 2840 2841 2842 2843

/*
  cleanup lex for case when we open table by table for processing

  SYNOPSIS
Konstantin Osipov's avatar
Konstantin Osipov committed
2844
    LEX::cleanup_after_one_table_open()
2845 2846 2847 2848 2849

  NOTE
    This method is mostly responsible for cleaning up of selects lists and
    derived tables state. To rollback changes in Query_tables_list one has
    to call Query_tables_list::reset_query_tables_list(FALSE).
2850 2851
*/

Konstantin Osipov's avatar
Konstantin Osipov committed
2852
void LEX::cleanup_after_one_table_open()
2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874
{
  /*
    thd->lex->derived_tables & additional units may be set if we open
    a view. It is necessary to clear thd->lex->derived_tables flag
    to prevent processing of derived tables during next open_and_lock_tables
    if next table is a real table and cleanup & remove underlying units
    NOTE: all units will be connected to thd->lex->select_lex, because we
    have not UNION on most upper level.
    */
  if (all_selects_list != &select_lex)
  {
    derived_tables= 0;
    /* cleunup underlying units (units of VIEW) */
    for (SELECT_LEX_UNIT *un= select_lex.first_inner_unit();
         un;
         un= un->next_unit())
      un->cleanup();
    /* reduce all selects list to default state */
    all_selects_list= &select_lex;
    /* remove underlying units (units of VIEW) subtree */
    select_lex.cut_subtree();
  }
2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886
}


/*
  Save current state of Query_tables_list for this LEX, and prepare it
  for processing of new statemnt.

  SYNOPSIS
    reset_n_backup_query_tables_list()
      backup  Pointer to Query_tables_list instance to be used for backup
*/

Konstantin Osipov's avatar
Konstantin Osipov committed
2887
void LEX::reset_n_backup_query_tables_list(Query_tables_list *backup)
2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905
{
  backup->set_query_tables_list(this);
  /*
    We have to perform full initialization here since otherwise we
    will damage backed up state.
  */
  this->reset_query_tables_list(TRUE);
}


/*
  Restore state of Query_tables_list for this LEX from backup.

  SYNOPSIS
    restore_backup_query_tables_list()
      backup  Pointer to Query_tables_list instance used for backup
*/

Konstantin Osipov's avatar
Konstantin Osipov committed
2906
void LEX::restore_backup_query_tables_list(Query_tables_list *backup)
2907 2908 2909
{
  this->destroy_query_tables_list();
  this->set_query_tables_list(backup);
2910 2911 2912
}


unknown's avatar
unknown committed
2913 2914 2915 2916
/*
  Checks for usage of routines and/or tables in a parsed statement

  SYNOPSIS
Konstantin Osipov's avatar
Konstantin Osipov committed
2917
    LEX:table_or_sp_used()
unknown's avatar
unknown committed
2918 2919 2920 2921 2922 2923

  RETURN
    FALSE  No routines and tables used
    TRUE   Either or both routines and tables are used.
*/

Konstantin Osipov's avatar
Konstantin Osipov committed
2924
bool LEX::table_or_sp_used()
unknown's avatar
unknown committed
2925 2926 2927 2928 2929 2930 2931 2932 2933 2934
{
  DBUG_ENTER("table_or_sp_used");

  if (sroutines.records || query_tables)
    DBUG_RETURN(TRUE);

  DBUG_RETURN(FALSE);
}


2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963
/*
  Do end-of-prepare fixup for list of tables and their merge-VIEWed tables

  SYNOPSIS
    fix_prepare_info_in_table_list()
      thd  Thread handle
      tbl  List of tables to process

  DESCRIPTION
    Perform end-end-of prepare fixup for list of tables, if any of the tables
    is a merge-algorithm VIEW, recursively fix up its underlying tables as
    well.

*/

static void fix_prepare_info_in_table_list(THD *thd, TABLE_LIST *tbl)
{
  for (; tbl; tbl= tbl->next_local)
  {
    if (tbl->on_expr)
    {
      tbl->prep_on_expr= tbl->on_expr;
      tbl->on_expr= tbl->on_expr->copy_andor_structure(thd);
    }
    fix_prepare_info_in_table_list(thd, tbl->merge_underlying_list);
  }
}


unknown's avatar
VIEW  
unknown committed
2964
/*
2965
  Save WHERE/HAVING/ON clauses and replace them with disposable copies
unknown's avatar
VIEW  
unknown committed
2966 2967 2968

  SYNOPSIS
    st_select_lex::fix_prepare_information
2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979
      thd          thread handler
      conds        in/out pointer to WHERE condition to be met at execution
      having_conds in/out pointer to HAVING condition to be met at execution
  
  DESCRIPTION
    The passed WHERE and HAVING are to be saved for the future executions.
    This function saves it, and returns a copy which can be thrashed during
    this execution of the statement. By saving/thrashing here we mean only
    AND/OR trees.
    The function also calls fix_prepare_info_in_table_list that saves all
    ON expressions.    
unknown's avatar
VIEW  
unknown committed
2980 2981
*/

2982 2983
void st_select_lex::fix_prepare_information(THD *thd, Item **conds, 
                                            Item **having_conds)
unknown's avatar
VIEW  
unknown committed
2984
{
unknown's avatar
unknown committed
2985
  if (!thd->stmt_arena->is_conventional() && first_execution)
unknown's avatar
VIEW  
unknown committed
2986 2987
  {
    first_execution= 0;
2988 2989 2990 2991 2992
    if (*conds)
    {
      prep_where= *conds;
      *conds= where= prep_where->copy_andor_structure(thd);
    }
2993 2994 2995 2996 2997
    if (*having_conds)
    {
      prep_having= *having_conds;
      *having_conds= having= prep_having->copy_andor_structure(thd);
    }
2998
    fix_prepare_info_in_table_list(thd, (TABLE_LIST *)table_list.first);
2999 3000 3001
  }
}

unknown's avatar
unknown committed
3002

unknown's avatar
unknown committed
3003
/*
unknown's avatar
VIEW  
unknown committed
3004
  There are st_select_lex::add_table_to_list &
unknown's avatar
unknown committed
3005
  st_select_lex::set_lock_for_tables are in sql_parse.cc
unknown's avatar
unknown committed
3006

unknown's avatar
VIEW  
unknown committed
3007
  st_select_lex::print is in sql_select.cc
unknown's avatar
unknown committed
3008 3009

  st_select_lex_unit::prepare, st_select_lex_unit::exec,
3010 3011
  st_select_lex_unit::cleanup, st_select_lex_unit::reinit_exec_mechanism,
  st_select_lex_unit::change_result
unknown's avatar
unknown committed
3012
  are in sql_union.cc
unknown's avatar
unknown committed
3013
*/
3014

3015 3016 3017 3018 3019
/*
  Sets the kind of hints to be added by the calls to add_index_hint().

  SYNOPSIS
    set_index_hint_type()
3020 3021
      type_arg     The kind of hints to be added from now on.
      clause       The clause to use for hints to be added from now on.
3022 3023 3024 3025 3026 3027 3028 3029

  DESCRIPTION
    Used in filling up the tagged hints list.
    This list is filled by first setting the kind of the hint as a 
    context variable and then adding hints of the current kind.
    Then the context variable index_hint_type can be reset to the
    next hint type.
*/
3030
void st_select_lex::set_index_hint_type(enum index_hint_type type_arg,
3031 3032
                                        index_clause_map clause)
{ 
3033
  current_index_hint_type= type_arg;
3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047
  current_index_hint_clause= clause;
}


/*
  Makes an array to store index usage hints (ADD/FORCE/IGNORE INDEX).

  SYNOPSIS
    alloc_index_hints()
      thd         current thread.
*/

void st_select_lex::alloc_index_hints (THD *thd)
{ 
unknown's avatar
unknown committed
3048
  index_hints= new (thd->mem_root) List<Index_hint>(); 
3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068
}



/*
  adds an element to the array storing index usage hints 
  (ADD/FORCE/IGNORE INDEX).

  SYNOPSIS
    add_index_hint()
      thd         current thread.
      str         name of the index.
      length      number of characters in str.

  RETURN VALUE
    0 on success, non-zero otherwise
*/
bool st_select_lex::add_index_hint (THD *thd, char *str, uint length)
{
  return index_hints->push_front (new (thd->mem_root) 
unknown's avatar
unknown committed
3069
                                 Index_hint(current_index_hint_type,
3070 3071 3072
                                            current_index_hint_clause,
                                            str, length));
}
3073 3074 3075 3076 3077 3078

/**
  A routine used by the parser to decide whether we are specifying a full
  partitioning or if only partitions to add or to split.

  @note  This needs to be outside of WITH_PARTITION_STORAGE_ENGINE since it
unknown's avatar
unknown committed
3079
  is used from the sql parser that doesn't have any ifdef's
3080 3081 3082 3083 3084

  @retval  TRUE    Yes, it is part of a management partition command
  @retval  FALSE          No, not a management partition command
*/

Konstantin Osipov's avatar
Konstantin Osipov committed
3085
bool LEX::is_partition_management() const
3086 3087 3088 3089 3090 3091
{
  return (sql_command == SQLCOM_ALTER_TABLE &&
          (alter_info.flags == ALTER_ADD_PARTITION ||
           alter_info.flags == ALTER_REORGANIZE_PARTITION));
}