sql_lex.cc 66.4 KB
Newer Older
1
/* Copyright (C) 2000-2006 MySQL AB
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
2

bk@work.mysql.com's avatar
bk@work.mysql.com 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
5
   the Free Software Foundation; version 2 of the License.
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
6

bk@work.mysql.com's avatar
bk@work.mysql.com 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.
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
11

bk@work.mysql.com's avatar
bk@work.mysql.com 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
bk@work.mysql.com's avatar
bk@work.mysql.com 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"
bk@work.mysql.com's avatar
bk@work.mysql.com committed
26

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

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

34
/* Longest standard keyword name */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
35 36
#define TOCK_NAME_LENGTH 24

37 38
/*
  The following data is based on the latin1 character set, and is only
bk@work.mysql.com's avatar
bk@work.mysql.com committed
39 40 41
  used when comparing keywords
*/

monty@mysql.com's avatar
monty@mysql.com committed
42 43
static uchar to_upper_lex[]=
{
bk@work.mysql.com's avatar
bk@work.mysql.com committed
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
    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
};

62 63 64 65 66 67 68 69 70 71 72
/* 
  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"
};
73

bk@work.mysql.com's avatar
bk@work.mysql.com committed
74 75 76 77 78 79 80
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;
}

serg@serg.mylan's avatar
serg@serg.mylan committed
81
#include <lex_hash.h>
bk@work.mysql.com's avatar
bk@work.mysql.com committed
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103


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;
}


104 105 106 107 108 109 110 111 112
void
st_parsing_options::reset()
{
  allows_variable= TRUE;
  allows_select_into= TRUE;
  allows_select_procedure= TRUE;
  allows_derived= TRUE;
}

113 114 115 116 117 118 119
Lex_input_stream::Lex_input_stream(THD *thd,
                                   const char* buffer,
                                   unsigned int length)
: m_thd(thd),
  yylineno(1),
  yytoklen(0),
  yylval(NULL),
120 121 122 123 124 125 126 127 128 129
  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),
  m_echo(true),
  m_cpp_tok_start(NULL),
  m_cpp_tok_start_prev(NULL),
  m_cpp_tok_end(NULL),
130 131
  next_state(MY_LEX_START),
  found_semicolon(NULL),
132
  ignore_space(test(thd->variables.sql_mode & MODE_IGNORE_SPACE)),
133 134
  stmt_prepare_mode(FALSE),
  in_comment(NO_COMMENT)
135
{
136 137
  m_cpp_buf= (char*) thd->alloc(length + 1);
  m_cpp_ptr= m_cpp_buf;
138 139 140 141 142
}

Lex_input_stream::~Lex_input_stream()
{}

143

144 145 146 147 148 149
/*
  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)
*/

150
void lex_start(THD *thd)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
151
{
152
  LEX *lex= thd->lex;
153 154 155 156
  DBUG_ENTER("lex_start");

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

157
  lex->context_stack.empty();
158 159
  lex->unit.init_query();
  lex->unit.init_select();
160 161
  /* 'parent_lex' is used in init_query() so it must be before it. */
  lex->select_lex.parent_lex= lex;
162 163
  lex->select_lex.init_query();
  lex->value_list.empty();
164
  lex->update_list.empty();
165
  lex->param_list.empty();
monty@mysql.com's avatar
monty@mysql.com committed
166
  lex->view_list.empty();
167
  lex->prepared_stmt_params.empty();
168
  lex->auxiliary_table_list.empty();
169 170 171 172 173 174 175 176 177 178
  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;
179
  lex->select_lex.sql_cache= SELECT_LEX::SQL_CACHE_UNSPECIFIED;
monty@mysql.com's avatar
monty@mysql.com committed
180 181
  lex->select_lex.init_order();
  lex->select_lex.group_list.empty();
182
  lex->describe= 0;
monty@mysql.com's avatar
monty@mysql.com committed
183
  lex->subqueries= FALSE;
monty@mysql.com's avatar
monty@mysql.com committed
184
  lex->view_prepare_mode= FALSE;
monty@mysql.com's avatar
monty@mysql.com committed
185
  lex->derived_tables= 0;
186 187
  lex->lock_option= TL_READ;
  lex->safe_to_cache_query= 1;
188
  lex->leaf_tables_insert= 0;
189
  lex->parsing_options.reset();
monty@mysql.com's avatar
monty@mysql.com committed
190
  lex->empty_field_list_on_rset= 0;
191
  lex->select_lex.select_number= 1;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
192
  lex->length=0;
193
  lex->part_info= 0;
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
194 195
  lex->select_lex.in_sum_expr=0;
  lex->select_lex.expr_list.empty();
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
196
  lex->select_lex.ftfunc_list_alloc.empty();
197
  lex->select_lex.ftfunc_list= &lex->select_lex.ftfunc_list_alloc;
198 199
  lex->select_lex.group_list.empty();
  lex->select_lex.order_list.empty();
200
  lex->sql_command= SQLCOM_END;
201
  lex->duplicates= DUP_ERROR;
202
  lex->ignore= 0;
203
  lex->spname= NULL;
204 205
  lex->sphead= NULL;
  lex->spcont= NULL;
206
  lex->proc_list.first= 0;
207
  lex->escape_used= FALSE;
antony@ppcg5.local's avatar
antony@ppcg5.local committed
208
  lex->query_tables= 0;
209
  lex->reset_query_tables_list(FALSE);
210
  lex->expr_allows_subselect= TRUE;
211

212 213
  lex->name.str= 0;
  lex->name.length= 0;
214
  lex->event_parse_data= NULL;
215

igor@rurik.mysql.com's avatar
igor@rurik.mysql.com committed
216 217 218
  lex->nest_level=0 ;
  lex->allow_sum_func= 0;
  lex->in_sum_func= NULL;
patg@radha.tangent.org's avatar
patg@radha.tangent.org committed
219 220 221 222 223 224 225 226 227 228 229 230 231 232 233
  /*
    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;
234
  DBUG_VOID_RETURN;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
235 236 237 238
}

void lex_end(LEX *lex)
{
monty@mysql.com's avatar
monty@mysql.com committed
239
  DBUG_ENTER("lex_end");
240
  DBUG_PRINT("enter", ("lex: 0x%lx", (long) lex));
monty@mysql.com's avatar
monty@mysql.com committed
241 242 243 244 245 246 247
  if (lex->yacc_yyss)
  {
    my_free(lex->yacc_yyss, MYF(0));
    my_free(lex->yacc_yyvs, MYF(0));
    lex->yacc_yyss= 0;
    lex->yacc_yyvs= 0;
  }
antony@ppcg5.local's avatar
antony@ppcg5.local committed
248 249 250 251 252 253

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

monty@mysql.com's avatar
monty@mysql.com committed
254
  DBUG_VOID_RETURN;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
255 256 257
}


258
static int find_keyword(Lex_input_stream *lip, uint len, bool function)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
259
{
260
  const char *tok= lip->get_tok_start();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
261

262
  SYMBOL *symbol= get_hash_symbol(tok, len, function);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
263 264
  if (symbol)
  {
265 266 267 268
    lip->yylval->symbol.symbol=symbol;
    lip->yylval->symbol.str= (char*) tok;
    lip->yylval->symbol.length=len;

269
    if ((symbol->tok == NOT_SYM) &&
270
        (lip->m_thd->variables.sql_mode & MODE_HIGH_NOT_PRECEDENCE))
271 272
      return NOT2_SYM;
    if ((symbol->tok == OR_OR_SYM) &&
273
	!(lip->m_thd->variables.sql_mode & MODE_PIPES_AS_CONCAT))
274
      return OR2_SYM;
275

bk@work.mysql.com's avatar
bk@work.mysql.com committed
276 277 278 279 280
    return symbol->tok;
  }
  return 0;
}

281 282 283 284 285
/*
  Check if name is a keyword

  SYNOPSIS
    is_keyword()
286
    name      checked name (must not be empty)
287 288 289 290 291 292 293 294 295
    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)
{
296
  DBUG_ASSERT(len != 0);
297 298
  return get_hash_symbol(name,len,0)!=0;
}
bk@work.mysql.com's avatar
bk@work.mysql.com committed
299

300 301 302 303 304 305
bool is_lex_native_function(const LEX_STRING *name)
{
  DBUG_ASSERT(name != NULL);
  return (get_hash_symbol(name->str, name->length, 1) != 0);
}

bk@work.mysql.com's avatar
bk@work.mysql.com committed
306 307
/* make a copy of token before ptr and set yytoklen */

308
static LEX_STRING get_token(Lex_input_stream *lip, uint skip, uint length)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
309 310
{
  LEX_STRING tmp;
311
  lip->yyUnget();                       // ptr points now after last token char
312
  tmp.length=lip->yytoklen=length;
313
  tmp.str= lip->m_thd->strmake(lip->get_tok_start() + skip, tmp.length);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
314 315 316
  return tmp;
}

317 318 319 320 321 322 323
/* 
 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)
*/

324
static LEX_STRING get_quoted_token(Lex_input_stream *lip,
325
                                   uint skip,
326
                                   uint length, char quote)
327 328
{
  LEX_STRING tmp;
329 330
  const char *from, *end;
  char *to;
331
  lip->yyUnget();                       // ptr points now after last token char
332 333
  tmp.length= lip->yytoklen=length;
  tmp.str=(char*) lip->m_thd->alloc(tmp.length+1);
334
  from= lip->get_tok_start() + skip;
335
  to= tmp.str;
336 337
  end= to+length;
  for ( ; to != end; )
338
  {
339
    if ((*to++= *from++) == quote)
340 341 342 343 344 345 346 347 348 349 350
      from++;					// Skip double quotes
  }
  *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
*/
bk@work.mysql.com's avatar
bk@work.mysql.com committed
351

352
static char *get_text(Lex_input_stream *lip, int pre_skip, int post_skip)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
353 354 355
{
  reg1 uchar c,sep;
  uint found_escape=0;
356
  CHARSET_INFO *cs= lip->m_thd->charset();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
357

358 359
  sep= lip->yyGetLast();                        // String should end with this
  while (! lip->eof())
bk@work.mysql.com's avatar
bk@work.mysql.com committed
360
  {
361
    c= lip->yyGet();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
362
#ifdef USE_MB
363 364 365
    {
      int l;
      if (use_mb(cs) &&
366 367 368 369 370
          (l = my_ismbchar(cs,
                           lip->get_ptr() -1,
                           lip->get_end_of_query()))) {
        lip->skip_binary(l-1);
        continue;
371
      }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
372 373
    }
#endif
374
    if (c == '\\' &&
375
        !(lip->m_thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
376 377
    {					// Escaped character
      found_escape=1;
378
      if (lip->eof())
bk@work.mysql.com's avatar
bk@work.mysql.com committed
379
	return 0;
380
      lip->yySkip();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
381 382 383
    }
    else if (c == sep)
    {
384
      if (c == lip->yyGet())            // Check if two separators in a row
bk@work.mysql.com's avatar
bk@work.mysql.com committed
385
      {
386
        found_escape=1;                 // duplicate. Remember for delete
bk@work.mysql.com's avatar
bk@work.mysql.com committed
387 388 389
	continue;
      }
      else
390
        lip->yyUnget();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
391 392

      /* Found end. Unescape and return string */
393 394
      const char *str, *end;
      char *start;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
395

396 397 398 399 400 401 402
      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);

403
      if (!(start= (char*) lip->m_thd->alloc((uint) (end-str)+1)))
404
	return (char*) "";		// Sql_alloc has set error flag
bk@work.mysql.com's avatar
bk@work.mysql.com committed
405 406
      if (!found_escape)
      {
407 408 409
	lip->yytoklen=(uint) (end-str);
	memcpy(start,str,lip->yytoklen);
	start[lip->yytoklen]=0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
410 411 412
      }
      else
      {
413
        char *to;
414

bk@work.mysql.com's avatar
bk@work.mysql.com committed
415 416 417 418
	for (to=start ; str != end ; str++)
	{
#ifdef USE_MB
	  int l;
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
419
	  if (use_mb(cs) &&
420
              (l = my_ismbchar(cs, str, end))) {
bk@work.mysql.com's avatar
bk@work.mysql.com committed
421 422 423 424 425 426
	      while (l--)
		  *to++ = *str++;
	      str--;
	      continue;
	  }
#endif
427
	  if (!(lip->m_thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES) &&
428
              *str == '\\' && str+1 != end)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453
	  {
	    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:
454
              *to++= *str;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
455 456 457
	      break;
	    }
	  }
458 459
	  else if (*str == sep)
	    *to++= *str++;		// Two ' or "
bk@work.mysql.com's avatar
bk@work.mysql.com committed
460 461 462 463
	  else
	    *to++ = *str;
	}
	*to=0;
464
	lip->yytoklen=(uint) (to-start);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
465
      }
466
      return start;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487
    }
  }
  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;
488 489
static const char *unsigned_longlong_str="18446744073709551615";
static const uint unsigned_longlong_len=20;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
490

monty@mysql.com's avatar
monty@mysql.com committed
491
static inline uint int_token(const char *str,uint length)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525
{
  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)
526
      return DECIMAL_NUM;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
527 528 529 530
    else
    {
      cmp=signed_longlong_str+1;
      smaller=LONG_NUM;				// If <= signed_longlong_str
531
      bigger=DECIMAL_NUM;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
532 533 534 535 536 537 538 539 540 541 542 543 544
    }
  }
  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)
545 546
    {
      if (length > unsigned_longlong_len)
547
        return DECIMAL_NUM;
548 549
      cmp=unsigned_longlong_str;
      smaller=ULONGLONG_NUM;
550
      bigger=DECIMAL_NUM;
551
    }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
552 553 554 555
    else
    {
      cmp=longlong_str;
      smaller=LONG_NUM;
556
      bigger= ULONGLONG_NUM;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
557 558 559 560 561 562
    }
  }
  while (*cmp && *cmp++ == *str++) ;
  return ((uchar) str[-1] <= (uchar) cmp[-1]) ? smaller : bigger;
}

563
/*
564
  MYSQLlex remember the following states from the following MYSQLlex()
565 566 567 568 569

  - 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)
*/
bk@work.mysql.com's avatar
bk@work.mysql.com committed
570

571
int MYSQLlex(void *arg, void *yythd)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
572 573
{
  reg1	uchar c;
574
  int	tokval, result_state;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
575
  uint length;
576
  enum my_lex_states state;
577 578 579
  THD *thd= (THD *)yythd;
  Lex_input_stream *lip= thd->m_lip;
  LEX *lex= thd->lex;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
580
  YYSTYPE *yylval=(YYSTYPE*) arg;
581
  CHARSET_INFO *cs= thd->charset();
582 583
  uchar *state_map= cs->state_map;
  uchar *ident_map= cs->ident_map;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
584

585
  lip->yylval=yylval;			// The global state
586

587
  lip->start_token();
588 589
  state=lip->next_state;
  lip->next_state=MY_LEX_OPERATOR_OR_IDENT;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
590 591 592
  LINT_INIT(c);
  for (;;)
  {
593
    switch (state) {
594 595
    case MY_LEX_OPERATOR_OR_IDENT:	// Next is operator or keyword
    case MY_LEX_START:			// Start of token
596 597
      // Skip starting whitespace
      while(state_map[c= lip->yyPeek()] == MY_LEX_SKIP)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
598 599
      {
	if (c == '\n')
600
	  lip->yylineno++;
601 602

        lip->yySkip();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
603
      }
604 605 606 607

      /* Start of real token */
      lip->restart_token();
      c= lip->yyGet();
608
      state= (enum my_lex_states) state_map[c];
bk@work.mysql.com's avatar
bk@work.mysql.com committed
609
      break;
610
    case MY_LEX_ESCAPE:
611
      if (lip->yyGet() == 'N')
bk@work.mysql.com's avatar
bk@work.mysql.com committed
612 613 614 615 616
      {					// Allow \N as shortcut for NULL
	yylval->lex_str.str=(char*) "\\N";
	yylval->lex_str.length=2;
	return NULL_SYM;
      }
617 618
    case MY_LEX_CHAR:			// Unknown or single char token
    case MY_LEX_SKIP:			// This should not happen
619 620 621
      if (c == '-' && lip->yyPeek() == '-' &&
          (my_isspace(cs,lip->yyPeekn(1)) ||
           my_iscntrl(cs,lip->yyPeekn(1))))
622 623 624 625
      {
        state=MY_LEX_COMMENT;
        break;
      }
626

bk@work.mysql.com's avatar
bk@work.mysql.com committed
627
      if (c != ')')
628
	lip->next_state= MY_LEX_START;	// Allow signed numbers
629

bk@work.mysql.com's avatar
bk@work.mysql.com committed
630
      if (c == ',')
631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651
      {
        /*
          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()])
652
        return(PARAM_MARKER);
653 654
      }

bk@work.mysql.com's avatar
bk@work.mysql.com committed
655 656
      return((int) c);

bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
657
    case MY_LEX_IDENT_OR_NCHAR:
658 659
      if (lip->yyPeek() != '\'')
      {
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
660 661 662
	state= MY_LEX_IDENT;
	break;
      }
663
      /* Found N'string' */
664 665
      lip->yySkip();                         // Skip '
      if (!(yylval->lex_str.str = get_text(lip, 2, 1)))
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
666
      {
667 668
	state= MY_LEX_CHAR;             // Read char by char
	break;
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
669
      }
670
      yylval->lex_str.length= lip->yytoklen;
671
      return(NCHAR_STRING);
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
672

673
    case MY_LEX_IDENT_OR_HEX:
674
      if (lip->yyPeek() == '\'')
675
      {					// Found x'hex-number'
676
	state= MY_LEX_HEX_NUMBER;
677 678
	break;
      }
ram@gw.mysql.r18.ru's avatar
ram@gw.mysql.r18.ru committed
679
    case MY_LEX_IDENT_OR_BIN:
680
      if (lip->yyPeek() == '\'')
ram@gw.mysql.r18.ru's avatar
ram@gw.mysql.r18.ru committed
681 682 683 684
      {                                 // Found b'bin-number'
        state= MY_LEX_BIN_NUMBER;
        break;
      }
685
    case MY_LEX_IDENT:
686
      const char *start;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
687
#if defined(USE_MB) && defined(USE_MB_IDENT)
688
      if (use_mb(cs))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
689
      {
690
	result_state= IDENT_QUOTED;
691
        if (my_mbcharlen(cs, lip->yyGetLast()) > 1)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
692
        {
693 694 695
          int l = my_ismbchar(cs,
                              lip->get_ptr() -1,
                              lip->get_end_of_query());
bk@work.mysql.com's avatar
bk@work.mysql.com committed
696
          if (l == 0) {
697
            state = MY_LEX_CHAR;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
698 699
            continue;
          }
700
          lip->skip_binary(l - 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
701
        }
702
        while (ident_map[c=lip->yyGet()])
bk@work.mysql.com's avatar
bk@work.mysql.com committed
703
        {
704
          if (my_mbcharlen(cs, c) > 1)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
705 706
          {
            int l;
707 708 709
            if ((l = my_ismbchar(cs,
                                 lip->get_ptr() -1,
                                 lip->get_end_of_query())) == 0)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
710
              break;
711
            lip->skip_binary(l-1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
712 713 714 715 716
          }
        }
      }
      else
#endif
717
      {
718
        for (result_state= c; ident_map[c= lip->yyGet()]; result_state|= c);
719 720
        /* If there were non-ASCII characters, mark that we must convert */
        result_state= result_state & 0x80 ? IDENT_QUOTED : IDENT;
721
      }
722 723
      length= lip->yyLength();
      start= lip->get_ptr();
724
      if (lip->ignore_space)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
725
      {
726 727 728 729
        /*
          If we find a space then this can't be an identifier. We notice this
          below by checking start != lex->ptr.
        */
730
        for (; state_map[c] == MY_LEX_SKIP ; c= lip->yyGet());
bk@work.mysql.com's avatar
bk@work.mysql.com committed
731
      }
732
      if (start == lip->get_ptr() && c == '.' && ident_map[lip->yyPeek()])
733
	lip->next_state=MY_LEX_IDENT_SEP;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
734 735
      else
      {					// '(' must follow directly if function
736 737
        lip->yyUnget();
	if ((tokval = find_keyword(lip, length, c == '(')))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
738
	{
739
	  lip->next_state= MY_LEX_START;	// Allow signed numbers
bk@work.mysql.com's avatar
bk@work.mysql.com committed
740 741
	  return(tokval);		// Was keyword
	}
742
        lip->yySkip();                  // next state does a unget
bk@work.mysql.com's avatar
bk@work.mysql.com committed
743
      }
744
      yylval->lex_str=get_token(lip, 0, length);
745 746 747 748

      /* 
         Note: "SELECT _bla AS 'alias'"
         _bla should be considered as a IDENT if charset haven't been found.
749
         So we don't use MYF(MY_WME) with get_charset_by_csname to avoid 
750 751 752 753
         producing an error.
      */

      if ((yylval->lex_str.str[0]=='_') && 
754 755 756
          (lex->underscore_charset=
             get_charset_by_csname(yylval->lex_str.str + 1,
                                   MY_CS_PRIMARY,MYF(0))))
757
        return(UNDERSCORE_CHARSET);
758
      return(result_state);			// IDENT or IDENT_QUOTED
bk@work.mysql.com's avatar
bk@work.mysql.com committed
759

760
    case MY_LEX_IDENT_SEP:		// Found ident and now '.'
761 762 763
      yylval->lex_str.str= (char*) lip->get_ptr();
      yylval->lex_str.length= 1;
      c= lip->yyGet();                  // should be '.'
764
      lip->next_state= MY_LEX_IDENT_START;// Next is an ident (not a keyword)
765
      if (!ident_map[lip->yyPeek()])            // Probably ` or "
766
	lip->next_state= MY_LEX_START;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
767 768
      return((int) c);

769
    case MY_LEX_NUMBER_IDENT:		// number or ident which num-start
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
      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')
        {
          while ((c= lip->yyGet()) == '0' || c == '1');
          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()))) ;
803
      if (!ident_map[c])
bk@work.mysql.com's avatar
bk@work.mysql.com committed
804
      {					// Can't be identifier
805
	state=MY_LEX_INT_OR_REAL;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
806 807 808 809
	break;
      }
      if (c == 'e' || c == 'E')
      {
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
810
	// The following test is written this way to allow numbers of type 1e1
811 812
        if (my_isdigit(cs,lip->yyPeek()) ||
            (c=(lip->yyGet())) == '+' || c == '-')
bk@work.mysql.com's avatar
bk@work.mysql.com committed
813
	{				// Allow 1E+10
814
          if (my_isdigit(cs,lip->yyPeek()))     // Number must have digit after sign
bk@work.mysql.com's avatar
bk@work.mysql.com committed
815
	  {
816 817 818
            lip->yySkip();
            while (my_isdigit(cs,lip->yyGet())) ;
            yylval->lex_str=get_token(lip, 0, lip->yyLength());
bk@work.mysql.com's avatar
bk@work.mysql.com committed
819 820 821
	    return(FLOAT_NUM);
	  }
	}
822
        lip->yyUnget();
ram@gw.mysql.r18.ru's avatar
ram@gw.mysql.r18.ru committed
823
      }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
824
      // fall through
825
    case MY_LEX_IDENT_START:			// We come here after '.'
826
      result_state= IDENT;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
827
#if defined(USE_MB) && defined(USE_MB_IDENT)
828
      if (use_mb(cs))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
829
      {
830
	result_state= IDENT_QUOTED;
831
        while (ident_map[c=lip->yyGet()])
bk@work.mysql.com's avatar
bk@work.mysql.com committed
832
        {
833
          if (my_mbcharlen(cs, c) > 1)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
834 835
          {
            int l;
836 837 838
            if ((l = my_ismbchar(cs,
                                 lip->get_ptr() -1,
                                 lip->get_end_of_query())) == 0)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
839
              break;
840
            lip->skip_binary(l-1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
841 842 843 844 845
          }
        }
      }
      else
#endif
846
      {
847
        for (result_state=0; ident_map[c= lip->yyGet()]; result_state|= c);
848 849 850
        /* If there were non-ASCII characters, mark that we must convert */
        result_state= result_state & 0x80 ? IDENT_QUOTED : IDENT;
      }
851
      if (c == '.' && ident_map[lip->yyPeek()])
852
	lip->next_state=MY_LEX_IDENT_SEP;// Next is '.'
bk@work.mysql.com's avatar
bk@work.mysql.com committed
853

854
      yylval->lex_str= get_token(lip, 0, lip->yyLength());
855
      return(result_state);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
856

857
    case MY_LEX_USER_VARIABLE_DELIMITER:	// Found quote char
858
    {
859 860
      uint double_quotes= 0;
      char quote_char= c;                       // Used char
861
      while ((c=lip->yyGet()))
862
      {
863 864
	int var_length;
	if ((var_length= my_mbcharlen(cs, c)) == 1)
865 866 867
	{
	  if (c == quote_char)
	  {
868
            if (lip->yyPeek() != quote_char)
869
	      break;
870
            c=lip->yyGet();
871 872 873
	    double_quotes++;
	    continue;
	  }
874 875
	}
#ifdef USE_MB
876
	else if (var_length < 1)
877
	  break;				// Error
878
        lip->skip_binary(var_length-1);
879
#endif
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
880
      }
881
      if (double_quotes)
882
	yylval->lex_str=get_quoted_token(lip, 1,
883
                                         lip->yyLength() - double_quotes -1,
884 885
					 quote_char);
      else
886
        yylval->lex_str=get_token(lip, 1, lip->yyLength() -1);
887
      if (c == quote_char)
888
        lip->yySkip();                  // Skip end `
889
      lip->next_state= MY_LEX_START;
890
      return(IDENT_QUOTED);
891
    }
892
    case MY_LEX_INT_OR_REAL:		// Complete int or incomplete real
bk@work.mysql.com's avatar
bk@work.mysql.com committed
893 894
      if (c != '.')
      {					// Found complete integer number.
895
        yylval->lex_str=get_token(lip, 0, lip->yyLength());
bk@work.mysql.com's avatar
bk@work.mysql.com committed
896 897 898
	return int_token(yylval->lex_str.str,yylval->lex_str.length);
      }
      // fall through
899
    case MY_LEX_REAL:			// Incomplete real number
900
      while (my_isdigit(cs,c = lip->yyGet())) ;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
901 902 903

      if (c == 'e' || c == 'E')
      {
904
        c = lip->yyGet();
905
	if (c == '-' || c == '+')
906
          c = lip->yyGet();                     // Skip sign
907
	if (!my_isdigit(cs,c))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
908
	{				// No digit after sign
909
	  state= MY_LEX_CHAR;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
910 911
	  break;
	}
912 913
        while (my_isdigit(cs,lip->yyGet())) ;
        yylval->lex_str=get_token(lip, 0, lip->yyLength());
bk@work.mysql.com's avatar
bk@work.mysql.com committed
914 915
	return(FLOAT_NUM);
      }
916
      yylval->lex_str=get_token(lip, 0, lip->yyLength());
917
      return(DECIMAL_NUM);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
918

919
    case MY_LEX_HEX_NUMBER:		// Found x'hexstring'
920 921 922 923 924 925 926 927
      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
928 929 930
      yylval->lex_str=get_token(lip,
                                2,          // skip x'
                                length-3);  // don't count x' and last '
931 932
      return (HEX_NUM);

ram@gw.mysql.r18.ru's avatar
ram@gw.mysql.r18.ru committed
933
    case MY_LEX_BIN_NUMBER:           // Found b'bin-string'
934 935
      lip->yySkip();                  // Accept opening '
      while ((c= lip->yyGet()) == '0' || c == '1');
ram@gw.mysql.r18.ru's avatar
ram@gw.mysql.r18.ru committed
936
      if (c != '\'')
937 938 939
        return(ABORT_SYM);            // Illegal hex constant
      lip->yySkip();                  // Accept closing '
      length= lip->yyLength();        // Length of bin-num + 3
940 941 942 943
      yylval->lex_str= get_token(lip,
                                 2,         // skip b'
                                 length-3); // don't count b' and last '
      return (BIN_NUM);
ram@gw.mysql.r18.ru's avatar
ram@gw.mysql.r18.ru committed
944

945
    case MY_LEX_CMP_OP:			// Incomplete comparison operator
946 947 948 949
      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)))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
950
      {
951
	lip->next_state= MY_LEX_START;	// Allow signed numbers
bk@work.mysql.com's avatar
bk@work.mysql.com committed
952 953
	return(tokval);
      }
954
      state = MY_LEX_CHAR;		// Something fishy found
bk@work.mysql.com's avatar
bk@work.mysql.com committed
955 956
      break;

957
    case MY_LEX_LONG_CMP_OP:		// Incomplete comparison operator
958 959
      if (state_map[lip->yyPeek()] == MY_LEX_CMP_OP ||
          state_map[lip->yyPeek()] == MY_LEX_LONG_CMP_OP)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
960
      {
961 962 963
        lip->yySkip();
        if (state_map[lip->yyPeek()] == MY_LEX_CMP_OP)
          lip->yySkip();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
964
      }
965
      if ((tokval = find_keyword(lip, lip->yyLength() + 1, 0)))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
966
      {
967
	lip->next_state= MY_LEX_START;	// Found long op
bk@work.mysql.com's avatar
bk@work.mysql.com committed
968 969
	return(tokval);
      }
970
      state = MY_LEX_CHAR;		// Something fishy found
bk@work.mysql.com's avatar
bk@work.mysql.com committed
971 972
      break;

973
    case MY_LEX_BOOL:
974
      if (c != lip->yyPeek())
bk@work.mysql.com's avatar
bk@work.mysql.com committed
975
      {
976
	state=MY_LEX_CHAR;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
977 978
	break;
      }
979
      lip->yySkip();
980 981
      tokval = find_keyword(lip,2,0);	// Is a bool operator
      lip->next_state= MY_LEX_START;	// Allow signed numbers
bk@work.mysql.com's avatar
bk@work.mysql.com committed
982 983
      return(tokval);

984
    case MY_LEX_STRING_OR_DELIMITER:
985
      if (thd->variables.sql_mode & MODE_ANSI_QUOTES)
986
      {
987
	state= MY_LEX_USER_VARIABLE_DELIMITER;
988 989 990
	break;
      }
      /* " used for strings */
991
    case MY_LEX_STRING:			// Incomplete text string
992
      if (!(yylval->lex_str.str = get_text(lip, 1, 1)))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
993
      {
994
	state= MY_LEX_CHAR;		// Read char by char
bk@work.mysql.com's avatar
bk@work.mysql.com committed
995 996
	break;
      }
997
      yylval->lex_str.length=lip->yytoklen;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
998 999
      return(TEXT_STRING);

1000
    case MY_LEX_COMMENT:			//  Comment
1001
      lex->select_lex.options|= OPTION_FOUND_COMMENT;
1002 1003
      while ((c = lip->yyGet()) != '\n' && c) ;
      lip->yyUnget();                   // Safety against eof
1004
      state = MY_LEX_START;		// Try again
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1005
      break;
1006
    case MY_LEX_LONG_COMMENT:		/* Long C comment? */
1007
      if (lip->yyPeek() != '*')
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1008
      {
1009
	state=MY_LEX_CHAR;		// Probable division
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1010 1011
	break;
      }
1012
      lex->select_lex.options|= OPTION_FOUND_COMMENT;
1013 1014 1015 1016
      /* Reject '/' '*', since we might need to turn off the echo */
      lip->yyUnget();

      if (lip->yyPeekn(2) == '!')
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1017
      {
1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063
        lip->in_comment= DISCARD_COMMENT;
        /* Accept '/' '*' '!', but do not keep this marker. */
        lip->set_echo(false);
        lip->yySkip();
        lip->yySkip();
        lip->yySkip();

        /*
          The special comment format is very strict:
          '/' '*' '!', followed by exactly
          2 digits (major), then 3 digits (minor).
        */
        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);

          /* Accept 'M' 'M' 'm' 'm' 'm' */
          lip->yySkipn(5);

          if (version <= MYSQL_VERSION_ID)
          {
            /* Expand the content of the special comment as real code */
            lip->set_echo(true);
            state=MY_LEX_START;
            break;
          }
        }
        else
        {
          state=MY_LEX_START;
          lip->set_echo(true);
          break;
        }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1064
      }
1065
      else
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1066
      {
1067 1068 1069
        lip->in_comment= PRESERVE_COMMENT;
        lip->yySkip();                  // Accept /
        lip->yySkip();                  // Accept *
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1070
      }
1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081

      while (! lip->eof() &&
            ((c=lip->yyGet()) != '*' || lip->yyPeek() != '/'))
      {
        if (c == '\n')
          lip->yylineno++;
      }
      if (! lip->eof())
        lip->yySkip();                  // remove last '/'
      state = MY_LEX_START;             // Try again
      lip->set_echo(true);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1082
      break;
1083
    case MY_LEX_END_LONG_COMMENT:
1084
      if ((lip->in_comment != NO_COMMENT) && lip->yyPeek() == '/')
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1085
      {
1086 1087 1088 1089 1090 1091 1092 1093 1094
        /* 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 */
        lip->set_echo(true);
        lip->in_comment=NO_COMMENT;
        state=MY_LEX_START;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1095 1096
      }
      else
1097
	state=MY_LEX_CHAR;		// Return '*'
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1098
      break;
1099
    case MY_LEX_SET_VAR:		// Check if ':='
1100
      if (lip->yyPeek() != '=')
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1101
      {
1102
	state=MY_LEX_CHAR;		// Return ':'
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1103 1104
	break;
      }
1105
      lip->yySkip();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1106
      return (SET_VAR);
1107
    case MY_LEX_SEMICOLON:			// optional line terminator
1108
      if (lip->yyPeek())
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1109
      {
1110
        if ((thd->client_capabilities & CLIENT_MULTI_STATEMENTS) && 
1111
            !lip->stmt_prepare_mode)
1112
        {
monty@mysql.com's avatar
monty@mysql.com committed
1113
	  lex->safe_to_cache_query= 0;
1114
          lip->found_semicolon= lip->get_ptr();
monty@mysql.com's avatar
monty@mysql.com committed
1115
          thd->server_status|= SERVER_MORE_RESULTS_EXISTS;
1116
          lip->next_state= MY_LEX_END;
1117
          lip->set_echo(true);
monty@mysql.com's avatar
monty@mysql.com committed
1118
          return (END_OF_INPUT);
1119
        }
monty@mysql.com's avatar
monty@mysql.com committed
1120
        state= MY_LEX_CHAR;		// Return ';'
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1121 1122
	break;
      }
1123 1124
      lip->next_state=MY_LEX_END;       // Mark for next loop
      return(END_OF_INPUT);
1125
    case MY_LEX_EOL:
1126
      if (lip->eof())
1127
      {
1128 1129 1130 1131 1132 1133
        lip->yyUnget();                 // Reject the last '\0'
        lip->set_echo(false);
        lip->yySkip();
        lip->set_echo(true);
        lip->next_state=MY_LEX_END;     // Mark for next loop
        return(END_OF_INPUT);
1134 1135 1136
      }
      state=MY_LEX_CHAR;
      break;
1137
    case MY_LEX_END:
1138
      lip->next_state=MY_LEX_END;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1139
      return(0);			// We found end of input last time
1140 1141
      
      /* Actually real shouldn't start with . but allow them anyhow */
1142
    case MY_LEX_REAL_OR_POINT:
1143
      if (my_isdigit(cs,lip->yyPeek()))
1144
	state = MY_LEX_REAL;		// Real
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1145 1146
      else
      {
1147
	state= MY_LEX_IDENT_SEP;	// return '.'
1148
        lip->yyUnget();                 // Put back '.'
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1149 1150
      }
      break;
1151
    case MY_LEX_USER_END:		// end '@' of user@hostname
1152
      switch (state_map[lip->yyPeek()]) {
1153 1154 1155
      case MY_LEX_STRING:
      case MY_LEX_USER_VARIABLE_DELIMITER:
      case MY_LEX_STRING_OR_DELIMITER:
1156
	break;
1157
      case MY_LEX_USER_END:
1158
	lip->next_state=MY_LEX_SYSTEM_VAR;
1159 1160
	break;
      default:
1161
	lip->next_state=MY_LEX_HOSTNAME;
1162 1163
	break;
      }
1164
      yylval->lex_str.str=(char*) lip->get_ptr();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1165 1166
      yylval->lex_str.length=1;
      return((int) '@');
1167
    case MY_LEX_HOSTNAME:		// end '@' of user@hostname
1168
      for (c=lip->yyGet() ;
1169
	   my_isalnum(cs,c) || c == '.' || c == '_' ||  c == '$';
1170 1171
           c= lip->yyGet()) ;
      yylval->lex_str=get_token(lip, 0, lip->yyLength());
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1172
      return(LEX_HOSTNAME);
1173
    case MY_LEX_SYSTEM_VAR:
1174
      yylval->lex_str.str=(char*) lip->get_ptr();
1175
      yylval->lex_str.length=1;
1176 1177
      lip->yySkip();                                    // Skip '@'
      lip->next_state= (state_map[lip->yyPeek()] ==
1178 1179 1180
			MY_LEX_USER_VARIABLE_DELIMITER ?
			MY_LEX_OPERATOR_OR_IDENT :
			MY_LEX_IDENT_OR_KEYWORD);
1181
      return((int) '@');
1182
    case MY_LEX_IDENT_OR_KEYWORD:
1183 1184 1185 1186 1187
      /*
	We come here when we have found two '@' in a row.
	We should now be able to handle:
	[(global | local | session) .]variable_name
      */
1188 1189

      for (result_state= 0; ident_map[c= lip->yyGet()]; result_state|= c);
1190 1191
      /* If there were non-ASCII characters, mark that we must convert */
      result_state= result_state & 0x80 ? IDENT_QUOTED : IDENT;
1192

1193
      if (c == '.')
1194
	lip->next_state=MY_LEX_IDENT_SEP;
1195 1196
      length= lip->yyLength();
      if (length == 0)
1197
        return(ABORT_SYM);              // Names must be nonempty.
1198
      if ((tokval= find_keyword(lip, length,0)))
1199
      {
1200
        lip->yyUnget();                         // Put back 'c'
1201 1202
	return(tokval);				// Was keyword
      }
1203
      yylval->lex_str=get_token(lip, 0, length);
1204
      return(result_state);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1205 1206 1207
    }
  }
}
1208

1209

1210 1211 1212 1213 1214 1215 1216 1217 1218
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),
igor@olga.mysql.com's avatar
igor@olga.mysql.com committed
1219 1220 1221 1222
  no_parts(rhs.no_parts),
  change_level(rhs.change_level),
  datetime_field(rhs.datetime_field),
  error_if_not_empty(rhs.error_if_not_empty)
1223 1224 1225 1226
{
  /*
    Make deep copies of used objects.
    This is not a fully deep copy - clone() implementations
1227
    of Alter_drop, Alter_column, Key, foreign_key, Key_part_spec
1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240
    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 */
}


1241 1242 1243 1244 1245 1246 1247
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.
  */
1248

1249 1250 1251 1252 1253
  while ((str->length > 0) && (my_isspace(cs, str->str[0])))
  {
    str->length --;
    str->str ++;
  }
1254

1255 1256 1257 1258 1259 1260 1261 1262
  /*
    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 --;
  }
1263 1264
}

1265

1266 1267 1268 1269 1270 1271
/*
  st_select_lex structures initialisations
*/

void st_select_lex_node::init_query()
{
1272
  options= 0;
1273
  sql_cache= SQL_CACHE_UNSPECIFIED;
1274
  linkage= UNSPECIFIED_TYPE;
1275 1276
  no_error= no_table_names_allowed= 0;
  uncacheable= 0;
1277 1278 1279 1280 1281 1282 1283 1284 1285
}

void st_select_lex_node::init_select()
{
}

void st_select_lex_unit::init_query()
{
  st_select_lex_node::init_query();
1286
  linkage= GLOBAL_OPTIONS_TYPE;
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
1287
  global_parameters= first_select();
1288 1289
  select_limit_cnt= HA_POS_ERROR;
  offset_limit_cnt= 0;
1290
  union_distinct= 0;
1291
  prepared= optimized= executed= 0;
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
1292
  item= 0;
1293 1294
  union_result= 0;
  table= 0;
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
1295
  fake_select_lex= 0;
1296
  cleaned= 0;
1297
  item_list.empty();
1298
  describe= 0;
1299
  found_rows_for_union= 0;
1300 1301 1302 1303 1304
}

void st_select_lex::init_query()
{
  st_select_lex_node::init_query();
1305
  table_list.empty();
1306 1307
  top_join_list.empty();
  join_list= &top_join_list;
1308
  embedding= leaf_tables= 0;
1309
  item_list.empty();
1310
  join= 0;
1311
  having= prep_having= where= prep_where= 0;
1312
  olap= UNSPECIFIED_OLAP_TYPE;
1313
  having_fix_field= 0;
1314 1315
  context.select_lex= this;
  context.init();
1316 1317 1318
  /*
    Add the name resolution context of the current (sub)query to the
    stack of contexts for the whole query.
1319 1320 1321 1322 1323
    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.
1324 1325
  */
  parent_lex->push_context(&context);
1326
  cond_count= between_count= with_wild= 0;
1327
  conds_processed_with_permanent_arena= 0;
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
1328
  ref_pointer_array= 0;
evgen@moonbone.local's avatar
evgen@moonbone.local committed
1329
  select_n_where_fields= 0;
bell@laptop.sanja.is.com.ua's avatar
bell@laptop.sanja.is.com.ua committed
1330
  select_n_having_items= 0;
1331
  subquery_in_having= explicit_limit= 0;
1332
  is_item_list_lookup= 0;
1333
  first_execution= 1;
1334
  first_cond_optimization= 1;
1335
  parsing_place= NO_MATTER;
1336
  exclude_from_table_unique_test= no_wrap_view_item= FALSE;
igor@rurik.mysql.com's avatar
igor@rurik.mysql.com committed
1337
  nest_level= 0;
1338
  link_next= 0;
1339 1340 1341 1342 1343
}

void st_select_lex::init_select()
{
  st_select_lex_node::init_select();
1344
  group_list.empty();
1345
  type= db= 0;
1346 1347 1348
  having= 0;
  table_join_options= 0;
  in_sum_expr= with_wild= 0;
1349
  options= 0;
1350
  sql_cache= SQL_CACHE_UNSPECIFIED;
1351
  braces= 0;
1352
  expr_list.empty();
1353
  interval_list.empty();
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
1354
  ftfunc_list_alloc.empty();
igor@rurik.mysql.com's avatar
igor@rurik.mysql.com committed
1355
  inner_sum_func_list= 0;
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
1356
  ftfunc_list= &ftfunc_list_alloc;
1357
  linkage= UNSPECIFIED_TYPE;
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
1358 1359
  order_list.elements= 0;
  order_list.first= 0;
1360
  order_list.next= (uchar**) &order_list.first;
1361 1362 1363
  /* 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 */
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
1364
  with_sum_func= 0;
1365
  is_correlated= 0;
1366 1367
  cur_pos_in_select_list= UNDEF_POS;
  non_agg_fields.empty();
1368
  cond_value= having_value= Item::COND_UNDEF;
1369
  inner_refs_list.empty();
1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383
}

/*
  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;
1384
  slave= 0;
1385 1386
}

bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
1387 1388
/*
  include on level down (but do not link)
1389

bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403
  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;
}

1404 1405 1406 1407 1408 1409 1410 1411
/* 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;
1412
  slave= 0;
1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426
}

/* 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()
{
1427
  if (link_prev)
1428 1429 1430 1431
  {
    if ((*link_prev= link_next))
      link_next->link_prev= link_prev;
  }
1432 1433 1434 1435
  // Remove slave structure
  for (; slave; slave= slave->next)
    slave->fast_exclude();
  
1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455
}

/*
  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;
  */
}
1456

1457 1458 1459 1460 1461 1462 1463 1464 1465 1466

/*
  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 
*/
1467 1468 1469
void st_select_lex_unit::exclude_level()
{
  SELECT_LEX_UNIT *units= 0, **units_last= &units;
1470
  for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
1471
  {
1472
    // unlink current level from global SELECTs list
1473 1474
    if (sl->link_prev && (*sl->link_prev= sl->link_next))
      sl->link_next->link_prev= sl->link_prev;
1475 1476

    // bring up underlay levels
1477 1478
    SELECT_LEX_UNIT **last= 0;
    for (SELECT_LEX_UNIT *u= sl->first_inner_unit(); u; u= u->next_unit())
1479 1480
    {
      u->master= master;
1481
      last= (SELECT_LEX_UNIT**)&(u->next);
1482
    }
1483 1484 1485 1486 1487 1488 1489 1490
    if (last)
    {
      (*units_last)= sl->first_inner_unit();
      units_last= last;
    }
  }
  if (units)
  {
1491
    // include brought up levels in place of current
1492 1493
    (*prev)= units;
    (*units_last)= (SELECT_LEX_UNIT*)next;
1494 1495 1496
    if (next)
      next->prev= (SELECT_LEX_NODE**)units_last;
    units->prev= prev;
1497 1498
  }
  else
1499 1500
  {
    // exclude currect unit from list of nodes
1501
    (*prev)= next;
1502 1503 1504
    if (next)
      next->prev= prev;
  }
1505 1506
}

1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517

/*
  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())
  {
1518
    // unlink current level from global SELECTs list
1519 1520 1521
    if (sl->link_prev && (*sl->link_prev= sl->link_next))
      sl->link_next->link_prev= sl->link_prev;

1522
    // unlink underlay levels
1523 1524 1525 1526 1527
    for (SELECT_LEX_UNIT *u= sl->first_inner_unit(); u; u= u->next_unit())
    {
      u->exclude_level();
    }
  }
1528
  // exclude currect unit from list of nodes
1529
  (*prev)= next;
1530 1531
  if (next)
    next->prev= prev;
1532 1533 1534
}


1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546
/*
  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
*/

bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
1547
void st_select_lex::mark_as_dependent(SELECT_LEX *last)
1548 1549 1550 1551 1552
{
  /*
    Mark all selects from resolved to 1 before select where was
    found table as depended (of select where was found table)
  */
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
1553
  for (SELECT_LEX *s= this;
1554
       s && s != last;
1555
       s= s->outer_select())
1556
    if (!(s->uncacheable & UNCACHEABLE_DEPENDENT))
1557 1558
    {
      // Select is dependent of outer select
1559 1560
      s->uncacheable= (s->uncacheable & ~UNCACHEABLE_UNITED) |
                       UNCACHEABLE_DEPENDENT;
1561
      SELECT_LEX_UNIT *munit= s->master_unit();
1562 1563 1564 1565 1566 1567 1568 1569
      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;
      }
1570
    }
1571 1572
  is_correlated= TRUE;
  this->master_unit()->item->is_correlated= TRUE;
1573 1574
}

1575 1576 1577 1578 1579
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; }
1580
TABLE_LIST *st_select_lex_node::add_table_to_list (THD *thd, Table_ident *table,
1581
						  LEX_STRING *alias,
monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
1582
						  ulong table_join_options,
1583
						  thr_lock_type flags,
1584
						  List<index_hint> *hints,
igor@rurik.mysql.com's avatar
igor@rurik.mysql.com committed
1585
                                                  LEX_STRING *option)
1586 1587 1588
{
  return 0;
}
1589 1590 1591 1592 1593 1594 1595 1596
ulong st_select_lex_node::get_table_join_options()
{
  return 0;
}

/*
  prohibit using LIMIT clause
*/
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
1597
bool st_select_lex::test_limit()
1598
{
1599
  if (select_limit != 0)
1600 1601
  {
    my_error(ER_NOT_SUPPORTED_YET, MYF(0),
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
1602
             "LIMIT & IN/ALL/ANY/SOME subquery");
1603 1604 1605 1606 1607 1608
    return(1);
  }
  // no sense in ORDER BY without LIMIT
  order_list.empty();
  return(0);
}
1609

1610

1611 1612 1613 1614 1615
st_select_lex_unit* st_select_lex_unit::master_unit()
{
    return this;
}

1616

1617 1618 1619 1620 1621
st_select_lex* st_select_lex_unit::outer_select()
{
  return (st_select_lex*) master;
}

1622

bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
1623
bool st_select_lex::add_order_to_list(THD *thd, Item *item, bool asc)
1624
{
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
1625
  return add_to_list(thd, order_list, item, asc);
1626
}
1627

1628

monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
1629
bool st_select_lex::add_item_to_list(THD *thd, Item *item)
1630
{
1631
  DBUG_ENTER("st_select_lex::add_item_to_list");
1632
  DBUG_PRINT("info", ("Item: 0x%lx", (long) item));
1633
  DBUG_RETURN(item_list.push_back(item));
1634 1635
}

1636

monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
1637
bool st_select_lex::add_group_to_list(THD *thd, Item *item, bool asc)
1638
{
monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
1639
  return add_to_list(thd, group_list, item, asc);
1640 1641
}

1642

1643 1644 1645 1646 1647
bool st_select_lex::add_ftfunc_to_list(Item_func_match *func)
{
  return !func || ftfunc_list->push_back(func); // end of memory?
}

1648

1649 1650 1651 1652 1653
st_select_lex_unit* st_select_lex::master_unit()
{
  return (st_select_lex_unit*) master;
}

1654

1655 1656 1657 1658 1659
st_select_lex* st_select_lex::outer_select()
{
  return (st_select_lex*) master->get_master();
}

1660

1661 1662 1663 1664 1665 1666
bool st_select_lex::set_braces(bool value)
{
  braces= value;
  return 0; 
}

1667

1668 1669 1670 1671 1672 1673
bool st_select_lex::inc_in_sum_expr()
{
  in_sum_expr++;
  return 0;
}

1674

1675 1676 1677 1678 1679
uint st_select_lex::get_in_sum_expr()
{
  return in_sum_expr;
}

1680

1681 1682 1683 1684 1685 1686 1687 1688 1689 1690
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;
}

monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
1691 1692 1693 1694 1695
ulong st_select_lex::get_table_join_options()
{
  return table_join_options;
}

1696

bell@laptop.sanja.is.com.ua's avatar
bell@laptop.sanja.is.com.ua committed
1697 1698 1699 1700
bool st_select_lex::setup_ref_array(THD *thd, uint order_group_num)
{
  if (ref_pointer_array)
    return 0;
1701 1702 1703 1704 1705

  /*
    We have to create array in prepared statement memory if it is
    prepared statement
  */
konstantin@mysql.com's avatar
konstantin@mysql.com committed
1706
  Query_arena *arena= thd->stmt_arena;
serg@serg.mylan's avatar
serg@serg.mylan committed
1707
  return (ref_pointer_array=
1708 1709 1710
          (Item **)arena->alloc(sizeof(Item*) * (n_child_sum_items +
                                                 item_list.elements +
                                                 select_n_having_items +
evgen@moonbone.local's avatar
evgen@moonbone.local committed
1711
                                                 select_n_where_fields +
1712
                                                 order_group_num)*5)) == 0;
bell@laptop.sanja.is.com.ua's avatar
bell@laptop.sanja.is.com.ua committed
1713 1714
}

1715

1716 1717
void st_select_lex_unit::print(String *str)
{
1718
  bool union_all= !union_distinct;
1719 1720 1721 1722
  for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
  {
    if (sl != first_select())
    {
1723
      str->append(STRING_WITH_LEN(" union "));
1724
      if (union_all)
1725
	str->append(STRING_WITH_LEN("all "));
1726
      else if (union_distinct == sl)
1727
        union_all= TRUE;
1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738
    }
    if (sl->braces)
      str->append('(');
    sl->print(thd, str);
    if (sl->braces)
      str->append(')');
  }
  if (fake_select_lex == global_parameters)
  {
    if (fake_select_lex->order_list.elements)
    {
1739
      str->append(STRING_WITH_LEN(" order by "));
1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752
      fake_select_lex->print_order(str,
				   (ORDER *) fake_select_lex->
				   order_list.first);
    }
    fake_select_lex->print_limit(thd, str);
  }
}


void st_select_lex::print_order(String *str, ORDER *order)
{
  for (; order; order= order->next)
  {
1753 1754 1755
    if (order->counter_used)
    {
      char buffer[20];
monty@mysql.com's avatar
monty@mysql.com committed
1756 1757
      uint length= my_snprintf(buffer, 20, "%d", order->counter);
      str->append(buffer, length);
1758 1759 1760
    }
    else
      (*order->item)->print(str);
1761
    if (!order->asc)
1762
      str->append(STRING_WITH_LEN(" desc"));
1763 1764 1765 1766 1767
    if (order->next)
      str->append(',');
  }
}
 
1768

1769 1770
void st_select_lex::print_limit(THD *thd, String *str)
{
1771 1772 1773
  SELECT_LEX_UNIT *unit= master_unit();
  Item_subselect *item= unit->item;
  if (item && unit->global_parameters == this &&
bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
1774 1775 1776 1777
      (item->substype() == Item_subselect::EXISTS_SUBS ||
       item->substype() == Item_subselect::IN_SUBS ||
       item->substype() == Item_subselect::ALL_SUBS))
  {
1778 1779
    DBUG_ASSERT(!item->fixed ||
                select_limit->val_int() == LL(1) && offset_limit == 0);
bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
1780 1781 1782
    return;
  }

1783
  if (explicit_limit)
1784
  {
1785
    str->append(STRING_WITH_LEN(" limit "));
1786 1787
    if (offset_limit)
    {
1788
      offset_limit->print(str);
1789 1790
      str->append(',');
    }
1791
    select_limit->print(str);
1792 1793 1794
  }
}

1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818
/**
  @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.
*/

void st_lex::cleanup_lex_after_parse_error(THD *thd)
{
  /*
    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
  */
1819
  if (thd->lex->sphead)
1820 1821 1822 1823 1824
  {
    delete thd->lex->sphead;
    thd->lex->sphead= NULL;
  }
}
bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
1825

1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845
/*
  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)
{
antony@ppcg5.local's avatar
antony@ppcg5.local committed
1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856
  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;
    }
  }
1857 1858 1859 1860
  query_tables= 0;
  query_tables_last= &query_tables;
  query_tables_own_last= 0;
  if (init)
1861 1862 1863 1864 1865 1866 1867
  {
    /*
      We delay real initialization of hash (and therefore related
      memory allocation) until first insertion into this hash.
    */
    hash_clear(&sroutines);
  }
1868
  else if (sroutines.records)
1869 1870
  {
    /* Non-zero sroutines.records means that hash was initialized. */
1871
    my_hash_reset(&sroutines);
1872
  }
1873 1874 1875
  sroutines_list.empty();
  sroutines_list_own_last= sroutines_list.next;
  sroutines_list_own_elements= 0;
1876
  binlog_stmt_flags= 0;
1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892
}


/*
  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()
{
  hash_free(&sroutines);
}


1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907
/*
  Initialize LEX object.

  SYNOPSIS
    st_lex::st_lex()

  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.
*/

st_lex::st_lex()
monty@mysql.com's avatar
monty@mysql.com committed
1908
  :result(0), yacc_yyss(0), yacc_yyvs(0),
1909
   sql_command(SQLCOM_END), option_type(OPT_DEFAULT)
1910
{
antony@ppcg5.local's avatar
antony@ppcg5.local committed
1911

antony@ppcg5.local's avatar
antony@ppcg5.local committed
1912 1913 1914 1915
  my_init_dynamic_array2(&plugins, sizeof(plugin_ref),
                         plugins_static_buffer,
                         INITIAL_LEX_PLUGIN_LIST_SIZE, 
                         INITIAL_LEX_PLUGIN_LIST_SIZE);
1916
  reset_query_tables_list(TRUE);
1917 1918 1919
}


bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
1920
/*
1921
  Check whether the merging algorithm can be used on this VIEW
bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
1922 1923 1924 1925

  SYNOPSIS
    st_lex::can_be_merged()

1926
  DESCRIPTION
1927 1928 1929
    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,
1930 1931 1932
    HAVING clause, aggregate functions, DISTINCT clause, LIMIT clause and
    several underlying tables.

bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
1933 1934 1935 1936 1937 1938 1939 1940 1941 1942
  RETURN
    FALSE - only temporary table algorithm can be used
    TRUE  - merge algorithm can be used
*/

bool st_lex::can_be_merged()
{
  // TODO: do not forget implement case when select_lex.table_list.elements==0

  /* find non VIEW subqueries/unions */
1943 1944 1945
  bool selects_allow_merge= select_lex.next_select() == 0;
  if (selects_allow_merge)
  {
1946 1947 1948
    for (SELECT_LEX_UNIT *tmp_unit= select_lex.first_inner_unit();
         tmp_unit;
         tmp_unit= tmp_unit->next_unit())
1949
    {
1950 1951 1952 1953
      if (tmp_unit->first_select()->parent_lex == this &&
          (tmp_unit->item == 0 ||
           (tmp_unit->item->place() != IN_WHERE &&
            tmp_unit->item->place() != IN_ON)))
1954 1955 1956 1957 1958 1959 1960 1961
      {
        selects_allow_merge= 0;
        break;
      }
    }
  }

  return (selects_allow_merge &&
bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
1962 1963
	  select_lex.group_list.elements == 0 &&
	  select_lex.having == 0 &&
1964
          select_lex.with_sum_func == 0 &&
1965
	  select_lex.table_list.elements >= 1 &&
bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
1966
	  !(select_lex.options & SELECT_DISTINCT) &&
1967
          select_lex.select_limit == 0);
bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
1968 1969
}

1970

bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
1971
/*
1972
  check if command can use VIEW with MERGE algorithm (for top VIEWs)
bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
1973 1974 1975 1976

  SYNOPSIS
    st_lex::can_use_merged()

1977 1978 1979 1980 1981
  DESCRIPTION
    Only listed here commands can use merge algorithm in top level
    SELECT_LEX (for subqueries will be used merge algorithm if
    st_lex::can_not_use_merged() is not TRUE).

bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000
  RETURN
    FALSE - command can't use merged VIEWs
    TRUE  - VIEWs with MERGE algorithms can be used
*/

bool st_lex::can_use_merged()
{
  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:
2001
  case SQLCOM_LOAD:
bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
2002 2003 2004 2005 2006 2007
    return TRUE;
  default:
    return FALSE;
  }
}

2008
/*
2009
  Check if command can't use merged views in any part of command
2010 2011 2012 2013

  SYNOPSIS
    st_lex::can_not_use_merged()

2014 2015 2016 2017
  DESCRIPTION
    Temporary table algorithm will be used on all SELECT levels for queries
    listed here (see also st_lex::can_use_merged()).

2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028
  RETURN
    FALSE - command can't use merged VIEWs
    TRUE  - VIEWs with MERGE algorithms can be used
*/

bool st_lex::can_not_use_merged()
{
  switch (sql_command)
  {
  case SQLCOM_CREATE_VIEW:
  case SQLCOM_SHOW_CREATE:
2029 2030 2031 2032 2033 2034
  /*
    SQLCOM_SHOW_FIELDS is necessary to make 
    information schema tables working correctly with views.
    see get_schema_tables_result function
  */
  case SQLCOM_SHOW_FIELDS:
2035 2036 2037 2038 2039 2040
    return TRUE;
  default:
    return FALSE;
  }
}

bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
2041 2042 2043 2044 2045 2046 2047 2048 2049 2050
/*
  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
*/
2051

bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
2052 2053
bool st_lex::only_view_structure()
{
2054
  switch (sql_command) {
bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068
  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;
  }
}


2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093
/*
  Should Items_ident be printed correctly

  SYNOPSIS
    need_correct_ident()

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


bool st_lex::need_correct_ident()
{
  switch(sql_command)
  {
  case SQLCOM_SHOW_CREATE:
  case SQLCOM_SHOW_TABLES:
  case SQLCOM_CREATE_VIEW:
    return TRUE;
  default:
    return FALSE;
  }
}

2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118
/*
  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
*/

uint8 st_lex::get_effective_with_check(st_table_list *view)
{
  if (view->select_lex->master_unit() == &unit &&
      which_check_option_applicable())
    return (uint8)view->with_check;
  return VIEW_CHECK_NONE;
}

2119

bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
2120 2121 2122 2123 2124 2125 2126
/*
  initialize limit counters

  SYNOPSIS
    st_select_lex_unit::set_limit()
    values	- SELECT_LEX with initial values for counters
*/
bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
2127

2128
void st_select_lex_unit::set_limit(SELECT_LEX *sl)
2129
{
2130
  ha_rows select_limit_val;
2131

konstantin@mysql.com's avatar
konstantin@mysql.com committed
2132
  DBUG_ASSERT(! thd->stmt_arena->is_stmt_prepare());
2133 2134 2135 2136
  select_limit_val= (ha_rows)(sl->select_limit ? sl->select_limit->val_uint() :
                                                 HA_POS_ERROR);
  offset_limit_cnt= (ha_rows)(sl->offset_limit ? sl->offset_limit->val_uint() :
                                                 ULL(0));
2137 2138
  select_limit_cnt= select_limit_val + offset_limit_cnt;
  if (select_limit_cnt < select_limit_val)
2139 2140 2141
    select_limit_cnt= HA_POS_ERROR;		// no limit
}

bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
2142

2143
/*
2144 2145
  Unlink the first table from the global table list and the first table from
  outer select (lex->select_lex) local list
2146 2147 2148

  SYNOPSIS
    unlink_first_table()
2149
    link_to_local	Set to 1 if caller should link this table to local list
2150

bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
2151
  NOTES
2152 2153
    We assume that first tables in both lists is the same table or the local
    list is empty.
2154 2155

  RETURN
2156
    0	If 'query_tables' == 0
bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
2157
    unlinked table
2158
      In this case link_to_local is set.
2159

2160
*/
bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
2161
TABLE_LIST *st_lex::unlink_first_table(bool *link_to_local)
2162
{
bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
2163 2164 2165 2166 2167 2168 2169 2170
  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;
2171 2172
    else
      query_tables_last= &query_tables;
bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
2173 2174 2175 2176 2177 2178 2179
    first->next_global= 0;

    /*
      and from local list if it is not empty
    */
    if ((*link_to_local= test(select_lex.table_list.first)))
    {
2180 2181
      select_lex.context.table_list= 
        select_lex.context.first_name_resolution_table= first->next_local;
2182
      select_lex.table_list.first= (uchar*) (first->next_local);
bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
2183 2184 2185
      select_lex.table_list.elements--;	//safety
      first->next_local= 0;
      /*
2186 2187
        Ensure that the global list has the same first table as the local
        list.
bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203
      */
      first_lists_tables_same();
    }
  }
  return first;
}


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

  SYNOPSYS
     st_lex::first_lists_tables_same()

  NOTES
2204 2205 2206 2207 2208 2209
    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.
bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
2210 2211 2212 2213 2214 2215 2216
*/

void st_lex::first_lists_tables_same()
{
  TABLE_LIST *first_table= (TABLE_LIST*) select_lex.table_list.first;
  if (query_tables != first_table && first_table != 0)
  {
2217
    TABLE_LIST *next;
bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
2218 2219
    if (query_tables_last == &first_table->next_global)
      query_tables_last= first_table->prev_global;
2220

2221
    if ((next= *first_table->prev_global= first_table->next_global))
bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
2222 2223 2224 2225
      next->prev_global= first_table->prev_global;
    /* include in new place */
    first_table->next_global= query_tables;
    /*
2226 2227 2228
       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
bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
2229 2230 2231 2232 2233
    */
    query_tables->prev_global= &first_table->next_global;
    first_table->prev_global= &query_tables;
    query_tables= first_table;
  }
2234 2235
}

bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
2236

2237
/*
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
2238
  Link table back that was unlinked with unlink_first_table()
2239 2240 2241

  SYNOPSIS
    link_first_table_back()
bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
2242
    link_to_local	do we need link this table to local
2243 2244 2245 2246

  RETURN
    global list
*/
bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
2247 2248 2249

void st_lex::link_first_table_back(TABLE_LIST *first,
				   bool link_to_local)
2250
{
bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
2251
  if (first)
2252
  {
bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
2253 2254
    if ((first->next_global= query_tables))
      query_tables->prev_global= &first->next_global;
2255 2256
    else
      query_tables_last= &first->next_global;
bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
2257 2258 2259 2260 2261
    query_tables= first;

    if (link_to_local)
    {
      first->next_local= (TABLE_LIST*) select_lex.table_list.first;
2262
      select_lex.context.table_list= first;
2263
      select_lex.table_list.first= (uchar*) first;
bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
2264 2265 2266 2267 2268 2269
      select_lex.table_list.elements++;	//safety
    }
  }
}


2270 2271 2272 2273 2274 2275

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

  SYNOPSIS
    st_lex::cleanup_after_one_table_open()
2276 2277 2278 2279 2280

  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).
2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305
*/

void st_lex::cleanup_after_one_table_open()
{
  /*
    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();
  }
2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340
}


/*
  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
*/

void st_lex::reset_n_backup_query_tables_list(Query_tables_list *backup)
{
  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
*/

void st_lex::restore_backup_query_tables_list(Query_tables_list *backup)
{
  this->destroy_query_tables_list();
  this->set_query_tables_list(backup);
2341 2342 2343
}


2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365
/*
  Checks for usage of routines and/or tables in a parsed statement

  SYNOPSIS
    st_lex:table_or_sp_used()

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

bool st_lex::table_or_sp_used()
{
  DBUG_ENTER("table_or_sp_used");

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

  DBUG_RETURN(FALSE);
}


2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394
/*
  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);
  }
}


bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
2395
/*
2396
  Save WHERE/HAVING/ON clauses and replace them with disposable copies
bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
2397 2398 2399

  SYNOPSIS
    st_select_lex::fix_prepare_information
2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410
      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.    
bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
2411 2412
*/

2413 2414
void st_select_lex::fix_prepare_information(THD *thd, Item **conds, 
                                            Item **having_conds)
bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
2415
{
konstantin@mysql.com's avatar
konstantin@mysql.com committed
2416
  if (!thd->stmt_arena->is_conventional() && first_execution)
bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
2417 2418
  {
    first_execution= 0;
2419 2420 2421 2422 2423
    if (*conds)
    {
      prep_where= *conds;
      *conds= where= prep_where->copy_andor_structure(thd);
    }
2424 2425 2426 2427 2428
    if (*having_conds)
    {
      prep_having= *having_conds;
      *having_conds= having= prep_having->copy_andor_structure(thd);
    }
2429
    fix_prepare_info_in_table_list(thd, (TABLE_LIST *)table_list.first);
2430 2431 2432
  }
}

2433

2434
/*
bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
2435
  There are st_select_lex::add_table_to_list &
2436
  st_select_lex::set_lock_for_tables are in sql_parse.cc
2437

bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
2438
  st_select_lex::print is in sql_select.cc
2439 2440

  st_select_lex_unit::prepare, st_select_lex_unit::exec,
2441 2442
  st_select_lex_unit::cleanup, st_select_lex_unit::reinit_exec_mechanism,
  st_select_lex_unit::change_result
2443
  are in sql_union.cc
2444
*/
2445

2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503
/*
  Sets the kind of hints to be added by the calls to add_index_hint().

  SYNOPSIS
    set_index_hint_type()
      type         the kind of hints to be added from now on.
      clause       the clause to use for hints to be added from now on.

  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.
*/
void st_select_lex::set_index_hint_type(enum index_hint_type type, 
                                        index_clause_map clause)
{ 
  current_index_hint_type= type;
  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)
{ 
  index_hints= new (thd->mem_root) List<index_hint>(); 
}



/*
  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) 
                                 index_hint(current_index_hint_type,
                                            current_index_hint_clause,
                                            str, length));
}
2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522

/**
  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
  is used from the sql parser that doesn't have any #ifdef's

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

bool st_lex::is_partition_management() const
{
  return (sql_command == SQLCOM_ALTER_TABLE &&
          (alter_info.flags == ALTER_ADD_PARTITION ||
           alter_info.flags == ALTER_REORGANIZE_PARTITION));
}