sql_lex.cc 57.4 KB
Newer Older
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult 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 5 6
   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
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
7

bk@work.mysql.com's avatar
bk@work.mysql.com committed
8 9 10 11
   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
12

bk@work.mysql.com's avatar
bk@work.mysql.com committed
13 14 15 16 17 18 19
   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 */

20
#define MYSQL_LEX 1
bk@work.mysql.com's avatar
bk@work.mysql.com committed
21 22 23 24
#include "mysql_priv.h"
#include "item_create.h"
#include <m_ctype.h>
#include <hash.h>
25 26
#include "sp.h"
#include "sp_head.h"
bk@work.mysql.com's avatar
bk@work.mysql.com committed
27

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

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

bk@work.mysql.com's avatar
bk@work.mysql.com committed
35 36 37 38 39 40 41 42 43 44
/* Macros to look like lex */

#define yyGet()		*(lex->ptr++)
#define yyGetLast()	lex->ptr[-1]
#define yyPeek()	lex->ptr[0]
#define yyPeek2()	lex->ptr[1]
#define yyUnget()	lex->ptr--
#define yySkip()	lex->ptr++
#define yyLength()	((uint) (lex->ptr - lex->tok_start)-1)

45
/* Longest standard keyword name */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
46 47
#define TOCK_NAME_LENGTH 24

48 49
/*
  The following data is based on the latin1 character set, and is only
bk@work.mysql.com's avatar
bk@work.mysql.com committed
50 51 52
  used when comparing keywords
*/

monty@mysql.com's avatar
monty@mysql.com committed
53 54
static uchar to_upper_lex[]=
{
bk@work.mysql.com's avatar
bk@work.mysql.com committed
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
    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
};

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

110
void lex_start(THD *thd, const uchar *buf, uint length)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
111
{
112
  LEX *lex= thd->lex;
113 114 115 116 117 118
  DBUG_ENTER("lex_start");

  lex->thd= lex->unit.thd= thd;
  lex->buf= lex->ptr= buf;
  lex->end_of_query= buf+length;

119
  lex->context_stack.empty();
120 121
  lex->unit.init_query();
  lex->unit.init_select();
122 123
  /* 'parent_lex' is used in init_query() so it must be before it. */
  lex->select_lex.parent_lex= lex;
124 125
  lex->select_lex.init_query();
  lex->value_list.empty();
126
  lex->update_list.empty();
127
  lex->param_list.empty();
monty@mysql.com's avatar
monty@mysql.com committed
128
  lex->view_list.empty();
129
  lex->prepared_stmt_params.empty();
130
  lex->auxiliary_table_list.empty();
131 132 133 134 135 136 137 138 139 140
  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;
141
  lex->select_lex.sql_cache= SELECT_LEX::SQL_CACHE_UNSPECIFIED;
monty@mysql.com's avatar
monty@mysql.com committed
142 143
  lex->select_lex.init_order();
  lex->select_lex.group_list.empty();
144
  lex->describe= 0;
monty@mysql.com's avatar
monty@mysql.com committed
145
  lex->subqueries= FALSE;
monty@mysql.com's avatar
monty@mysql.com committed
146
  lex->view_prepare_mode= FALSE;
147
  lex->stmt_prepare_mode= FALSE;
monty@mysql.com's avatar
monty@mysql.com committed
148
  lex->derived_tables= 0;
149
  lex->lock_option= TL_READ;
150
  lex->found_semicolon= 0;
151 152
  lex->safe_to_cache_query= 1;
  lex->time_zone_tables_used= 0;
153
  lex->leaf_tables_insert= 0;
monty@mysql.com's avatar
monty@mysql.com committed
154
  lex->empty_field_list_on_rset= 0;
155
  lex->select_lex.select_number= 1;
156
  lex->next_state=MY_LEX_START;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
157
  lex->yylineno = 1;
158
  lex->in_comment=0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
159
  lex->length=0;
160
  lex->part_info= 0;
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
161 162
  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
163
  lex->select_lex.ftfunc_list_alloc.empty();
164
  lex->select_lex.ftfunc_list= &lex->select_lex.ftfunc_list_alloc;
165 166
  lex->select_lex.group_list.empty();
  lex->select_lex.order_list.empty();
167
  lex->ignore_space=test(thd->variables.sql_mode & MODE_IGNORE_SPACE);
168
  lex->sql_command= SQLCOM_END;
169
  lex->duplicates= DUP_ERROR;
170
  lex->ignore= 0;
171
  lex->spname= NULL;
172 173
  lex->sphead= NULL;
  lex->spcont= NULL;
174
  lex->proc_list.first= 0;
175
  lex->escape_used= FALSE;
176
  lex->reset_query_tables_list(FALSE);
177
  lex->expr_allows_subselect= TRUE;
178

179
  lex->name= 0;
180
  lex->event_parse_data= NULL;
181

igor@rurik.mysql.com's avatar
igor@rurik.mysql.com committed
182 183 184
  lex->nest_level=0 ;
  lex->allow_sum_func= 0;
  lex->in_sum_func= NULL;
185
  DBUG_VOID_RETURN;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
186 187 188 189
}

void lex_end(LEX *lex)
{
monty@mysql.com's avatar
monty@mysql.com committed
190
  DBUG_ENTER("lex_end");
191
  DBUG_PRINT("enter", ("lex: 0x%lx", (long) lex));
monty@mysql.com's avatar
monty@mysql.com committed
192 193 194 195 196 197 198 199
  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;
  }
  DBUG_VOID_RETURN;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
200 201 202 203 204
}


static int find_keyword(LEX *lex, uint len, bool function)
{
205
  const uchar *tok=lex->tok_start;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
206

207
  SYMBOL *symbol= get_hash_symbol((const char *)tok,len,function);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
208 209 210 211 212
  if (symbol)
  {
    lex->yylval->symbol.symbol=symbol;
    lex->yylval->symbol.str= (char*) tok;
    lex->yylval->symbol.length=len;
213 214
    
    if ((symbol->tok == NOT_SYM) &&
215
        (lex->thd->variables.sql_mode & MODE_HIGH_NOT_PRECEDENCE))
216 217 218 219 220
      return NOT2_SYM;
    if ((symbol->tok == OR_OR_SYM) &&
	!(lex->thd->variables.sql_mode & MODE_PIPES_AS_CONCAT))
      return OR2_SYM;
    
bk@work.mysql.com's avatar
bk@work.mysql.com committed
221 222 223 224 225
    return symbol->tok;
  }
  return 0;
}

226 227 228 229 230
/*
  Check if name is a keyword

  SYNOPSIS
    is_keyword()
231
    name      checked name (must not be empty)
232 233 234 235 236 237 238 239 240
    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)
{
241
  DBUG_ASSERT(len != 0);
242 243
  return get_hash_symbol(name,len,0)!=0;
}
bk@work.mysql.com's avatar
bk@work.mysql.com committed
244 245 246

/* make a copy of token before ptr and set yytoklen */

247
static LEX_STRING get_token(LEX *lex,uint length)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
248 249 250 251
{
  LEX_STRING tmp;
  yyUnget();			// ptr points now after last token char
  tmp.length=lex->yytoklen=length;
252
  tmp.str=(char*) lex->thd->strmake((char*) lex->tok_start,tmp.length);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
253 254 255
  return tmp;
}

256 257 258 259 260 261 262
/* 
 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)
*/

263 264 265
static LEX_STRING get_quoted_token(LEX *lex,uint length, char quote)
{
  LEX_STRING tmp;
266 267
  const uchar *from, *end;
  uchar *to;
268 269 270
  yyUnget();			// ptr points now after last token char
  tmp.length=lex->yytoklen=length;
  tmp.str=(char*) lex->thd->alloc(tmp.length+1);
271
  for (from= lex->tok_start, to= (uchar*) tmp.str, end= to+length ;
272 273
       to != end ;
       )
274
  {
275
    if ((*to++= *from++) == (uchar) quote)
276 277 278 279 280 281 282 283 284 285 286
      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
287 288 289 290 291

static char *get_text(LEX *lex)
{
  reg1 uchar c,sep;
  uint found_escape=0;
292
  CHARSET_INFO *cs= lex->thd->charset();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
293 294 295 296 297 298 299

  sep= yyGetLast();			// String should end with this
  while (lex->ptr != lex->end_of_query)
  {
    c = yyGet();
#ifdef USE_MB
    int l;
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
300 301
    if (use_mb(cs) &&
        (l = my_ismbchar(cs,
bk@work.mysql.com's avatar
bk@work.mysql.com committed
302 303 304 305 306 307
                         (const char *)lex->ptr-1,
                         (const char *)lex->end_of_query))) {
	lex->ptr += l-1;
	continue;
    }
#endif
308 309
    if (c == '\\' &&
	!(lex->thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
310 311 312 313
    {					// Escaped character
      found_escape=1;
      if (lex->ptr == lex->end_of_query)
	return 0;
314
      yySkip();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
315 316 317 318 319 320 321 322 323 324 325 326
    }
    else if (c == sep)
    {
      if (c == yyGet())			// Check if two separators in a row
      {
	found_escape=1;			// dupplicate. Remember for delete
	continue;
      }
      else
	yyUnget();

      /* Found end. Unescape and return string */
327 328
      const uchar *str, *end;
      uchar *start;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
329 330 331

      str=lex->tok_start+1;
      end=lex->ptr-1;
332
      if (!(start=(uchar*) lex->thd->alloc((uint) (end-str)+1)))
333
	return (char*) "";		// Sql_alloc has set error flag
bk@work.mysql.com's avatar
bk@work.mysql.com committed
334 335 336 337 338 339 340 341 342
      if (!found_escape)
      {
	lex->yytoklen=(uint) (end-str);
	memcpy(start,str,lex->yytoklen);
	start[lex->yytoklen]=0;
      }
      else
      {
	uchar *to;
343

bk@work.mysql.com's avatar
bk@work.mysql.com committed
344 345 346 347
	for (to=start ; str != end ; str++)
	{
#ifdef USE_MB
	  int l;
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
348 349
	  if (use_mb(cs) &&
              (l = my_ismbchar(cs,
bk@work.mysql.com's avatar
bk@work.mysql.com committed
350 351 352 353 354 355 356
                               (const char *)str, (const char *)end))) {
	      while (l--)
		  *to++ = *str++;
	      str--;
	      continue;
	  }
#endif
357
	  if (!(lex->thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES) &&
358
              *str == '\\' && str+1 != end)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383
	  {
	    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:
384
              *to++= *str;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
385 386 387
	      break;
	    }
	  }
388 389
	  else if (*str == sep)
	    *to++= *str++;		// Two ' or "
bk@work.mysql.com's avatar
bk@work.mysql.com committed
390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417
	  else
	    *to++ = *str;
	}
	*to=0;
	lex->yytoklen=(uint) (to-start);
      }
      return (char*) start;
    }
  }
  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;
418 419
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
420

monty@mysql.com's avatar
monty@mysql.com committed
421
static inline uint int_token(const char *str,uint length)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
422 423 424 425 426 427 428 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 454 455
{
  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)
456
      return DECIMAL_NUM;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
457 458 459 460
    else
    {
      cmp=signed_longlong_str+1;
      smaller=LONG_NUM;				// If <= signed_longlong_str
461
      bigger=DECIMAL_NUM;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
462 463 464 465 466 467 468 469 470 471 472 473 474
    }
  }
  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)
475 476
    {
      if (length > unsigned_longlong_len)
477
        return DECIMAL_NUM;
478 479
      cmp=unsigned_longlong_str;
      smaller=ULONGLONG_NUM;
480
      bigger=DECIMAL_NUM;
481
    }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
482 483 484 485
    else
    {
      cmp=longlong_str;
      smaller=LONG_NUM;
486
      bigger= ULONGLONG_NUM;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
487 488 489 490 491 492
    }
  }
  while (*cmp && *cmp++ == *str++) ;
  return ((uchar) str[-1] <= (uchar) cmp[-1]) ? smaller : bigger;
}

493
/*
494
  MYSQLlex remember the following states from the following MYSQLlex()
495 496 497 498 499

  - 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
500

501
int MYSQLlex(void *arg, void *yythd)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
502 503
{
  reg1	uchar c;
504
  int	tokval, result_state;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
505
  uint length;
506
  enum my_lex_states state;
507
  LEX	*lex= ((THD *)yythd)->lex;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
508
  YYSTYPE *yylval=(YYSTYPE*) arg;
509
  CHARSET_INFO *cs= ((THD *) yythd)->charset();
510 511
  uchar *state_map= cs->state_map;
  uchar *ident_map= cs->ident_map;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
512 513

  lex->yylval=yylval;			// The global state
514 515 516 517

  lex->tok_end_prev= lex->tok_end;
  lex->tok_start_prev= lex->tok_start;

bk@work.mysql.com's avatar
bk@work.mysql.com committed
518
  lex->tok_start=lex->tok_end=lex->ptr;
519
  state=lex->next_state;
520
  lex->next_state=MY_LEX_OPERATOR_OR_IDENT;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
521 522 523
  LINT_INIT(c);
  for (;;)
  {
524
    switch (state) {
525 526
    case MY_LEX_OPERATOR_OR_IDENT:	// Next is operator or keyword
    case MY_LEX_START:			// Start of token
527
      // Skip startspace
528
      for (c=yyGet() ; (state_map[c] == MY_LEX_SKIP) ; c= yyGet())
bk@work.mysql.com's avatar
bk@work.mysql.com committed
529 530 531 532 533
      {
	if (c == '\n')
	  lex->yylineno++;
      }
      lex->tok_start=lex->ptr-1;	// Start of real token
534
      state= (enum my_lex_states) state_map[c];
bk@work.mysql.com's avatar
bk@work.mysql.com committed
535
      break;
536
    case MY_LEX_ESCAPE:
bk@work.mysql.com's avatar
bk@work.mysql.com committed
537 538 539 540 541 542
      if (yyGet() == 'N')
      {					// Allow \N as shortcut for NULL
	yylval->lex_str.str=(char*) "\\N";
	yylval->lex_str.length=2;
	return NULL_SYM;
      }
543 544
    case MY_LEX_CHAR:			// Unknown or single char token
    case MY_LEX_SKIP:			// This should not happen
545 546 547 548 549 550 551
      if (c == '-' && yyPeek() == '-' &&
          (my_isspace(cs,yyPeek2()) || 
           my_iscntrl(cs,yyPeek2())))
      {
        state=MY_LEX_COMMENT;
        break;
      }
552
      yylval->lex_str.str=(char*) (lex->ptr=lex->tok_start);// Set to first chr
bk@work.mysql.com's avatar
bk@work.mysql.com committed
553 554 555
      yylval->lex_str.length=1;
      c=yyGet();
      if (c != ')')
556
	lex->next_state= MY_LEX_START;	// Allow signed numbers
bk@work.mysql.com's avatar
bk@work.mysql.com committed
557 558
      if (c == ',')
	lex->tok_start=lex->ptr;	// Let tok_start point at next item
559 560 561 562 563 564
      /*
        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.
      */
565
      else if (c == '?' && lex->stmt_prepare_mode && !ident_map[yyPeek()])
566
        return(PARAM_MARKER);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
567 568
      return((int) c);

bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
569 570
    case MY_LEX_IDENT_OR_NCHAR:
      if (yyPeek() != '\'')
571
      {					
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
572 573 574
	state= MY_LEX_IDENT;
	break;
      }
575 576 577 578
      /* Found N'string' */
      lex->tok_start++;                 // Skip N
      yySkip();                         // Skip '
      if (!(yylval->lex_str.str = get_text(lex)))
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
579
      {
580 581
	state= MY_LEX_CHAR;             // Read char by char
	break;
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
582
      }
583 584
      yylval->lex_str.length= lex->yytoklen;
      return(NCHAR_STRING);
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
585

586
    case MY_LEX_IDENT_OR_HEX:
587
      if (yyPeek() == '\'')
588
      {					// Found x'hex-number'
589
	state= MY_LEX_HEX_NUMBER;
590 591
	break;
      }
ram@gw.mysql.r18.ru's avatar
ram@gw.mysql.r18.ru committed
592 593 594 595 596 597
    case MY_LEX_IDENT_OR_BIN:
      if (yyPeek() == '\'')
      {                                 // Found b'bin-number'
        state= MY_LEX_BIN_NUMBER;
        break;
      }
598
    case MY_LEX_IDENT:
599
      const uchar *start;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
600
#if defined(USE_MB) && defined(USE_MB_IDENT)
601
      if (use_mb(cs))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
602
      {
603
	result_state= IDENT_QUOTED;
604
        if (my_mbcharlen(cs, yyGetLast()) > 1)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
605
        {
606
          int l = my_ismbchar(cs,
bk@work.mysql.com's avatar
bk@work.mysql.com committed
607 608 609
                              (const char *)lex->ptr-1,
                              (const char *)lex->end_of_query);
          if (l == 0) {
610
            state = MY_LEX_CHAR;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
611 612 613 614
            continue;
          }
          lex->ptr += l - 1;
        }
615
        while (ident_map[c=yyGet()])
bk@work.mysql.com's avatar
bk@work.mysql.com committed
616
        {
617
          if (my_mbcharlen(cs, c) > 1)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
618 619
          {
            int l;
620
            if ((l = my_ismbchar(cs,
bk@work.mysql.com's avatar
bk@work.mysql.com committed
621 622 623 624 625 626 627 628 629
                              (const char *)lex->ptr-1,
                              (const char *)lex->end_of_query)) == 0)
              break;
            lex->ptr += l-1;
          }
        }
      }
      else
#endif
630
      {
631 632 633
        for (result_state= c; ident_map[c= yyGet()]; result_state|= c);
        /* If there were non-ASCII characters, mark that we must convert */
        result_state= result_state & 0x80 ? IDENT_QUOTED : IDENT;
634
      }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
635
      length= (uint) (lex->ptr - lex->tok_start)-1;
636
      start= lex->ptr;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
637 638
      if (lex->ignore_space)
      {
639 640 641 642 643
        /*
          If we find a space then this can't be an identifier. We notice this
          below by checking start != lex->ptr.
        */
        for (; state_map[c] == MY_LEX_SKIP ; c= yyGet());
bk@work.mysql.com's avatar
bk@work.mysql.com committed
644
      }
645
      if (start == lex->ptr && c == '.' && ident_map[yyPeek()])
646
	lex->next_state=MY_LEX_IDENT_SEP;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
647 648 649 650 651
      else
      {					// '(' must follow directly if function
	yyUnget();
	if ((tokval = find_keyword(lex,length,c == '(')))
	{
652
	  lex->next_state= MY_LEX_START;	// Allow signed numbers
bk@work.mysql.com's avatar
bk@work.mysql.com committed
653 654 655 656 657
	  return(tokval);		// Was keyword
	}
	yySkip();			// next state does a unget
      }
      yylval->lex_str=get_token(lex,length);
658 659 660 661

      /* 
         Note: "SELECT _bla AS 'alias'"
         _bla should be considered as a IDENT if charset haven't been found.
662
         So we don't use MYF(MY_WME) with get_charset_by_csname to avoid 
663 664 665 666
         producing an error.
      */

      if ((yylval->lex_str.str[0]=='_') && 
667 668 669
          (lex->underscore_charset=
             get_charset_by_csname(yylval->lex_str.str + 1,
                                   MY_CS_PRIMARY,MYF(0))))
670
        return(UNDERSCORE_CHARSET);
671
      return(result_state);			// IDENT or IDENT_QUOTED
bk@work.mysql.com's avatar
bk@work.mysql.com committed
672

673
    case MY_LEX_IDENT_SEP:		// Found ident and now '.'
bk@work.mysql.com's avatar
bk@work.mysql.com committed
674 675 676
      yylval->lex_str.str=(char*) lex->ptr;
      yylval->lex_str.length=1;
      c=yyGet();			// should be '.'
677 678 679
      lex->next_state= MY_LEX_IDENT_START;// Next is an ident (not a keyword)
      if (!ident_map[yyPeek()])		// Probably ` or "
	lex->next_state= MY_LEX_START;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
680 681
      return((int) c);

682 683
    case MY_LEX_NUMBER_IDENT:		// number or ident which num-start
      while (my_isdigit(cs,(c = yyGet()))) ;
684
      if (!ident_map[c])
bk@work.mysql.com's avatar
bk@work.mysql.com committed
685
      {					// Can't be identifier
686
	state=MY_LEX_INT_OR_REAL;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
687 688 689 690
	break;
      }
      if (c == 'e' || c == 'E')
      {
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
691
	// The following test is written this way to allow numbers of type 1e1
692
	if (my_isdigit(cs,yyPeek()) || 
693
            (c=(yyGet())) == '+' || c == '-')
bk@work.mysql.com's avatar
bk@work.mysql.com committed
694
	{				// Allow 1E+10
695
	  if (my_isdigit(cs,yyPeek()))	// Number must have digit after sign
bk@work.mysql.com's avatar
bk@work.mysql.com committed
696 697
	  {
	    yySkip();
698
	    while (my_isdigit(cs,yyGet())) ;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
699 700 701 702 703 704 705 706 707
	    yylval->lex_str=get_token(lex,yyLength());
	    return(FLOAT_NUM);
	  }
	}
	yyUnget(); /* purecov: inspected */
      }
      else if (c == 'x' && (lex->ptr - lex->tok_start) == 2 &&
	  lex->tok_start[0] == '0' )
      {						// Varbinary
708
	while (my_isxdigit(cs,(c = yyGet()))) ;
709
	if ((lex->ptr - lex->tok_start) >= 4 && !ident_map[c])
bk@work.mysql.com's avatar
bk@work.mysql.com committed
710 711
	{
	  yylval->lex_str=get_token(lex,yyLength());
712
	  yylval->lex_str.str+=2;		// Skip 0x
bk@work.mysql.com's avatar
bk@work.mysql.com committed
713 714 715 716 717 718
	  yylval->lex_str.length-=2;
	  lex->yytoklen-=2;
	  return (HEX_NUM);
	}
	yyUnget();
      }
ram@gw.mysql.r18.ru's avatar
ram@gw.mysql.r18.ru committed
719 720 721 722 723 724 725 726 727 728 729 730 731 732
      else if (c == 'b' && (lex->ptr - lex->tok_start) == 2 &&
               lex->tok_start[0] == '0' )
      {						// b'bin-number'
	while (my_isxdigit(cs,(c = yyGet()))) ;
	if ((lex->ptr - lex->tok_start) >= 4 && !ident_map[c])
	{
	  yylval->lex_str= get_token(lex, yyLength());
	  yylval->lex_str.str+= 2;		// Skip 0x
	  yylval->lex_str.length-= 2;
	  lex->yytoklen-= 2;
	  return (BIN_NUM);
	}
	yyUnget();
      }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
733
      // fall through
734
    case MY_LEX_IDENT_START:			// We come here after '.'
735
      result_state= IDENT;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
736
#if defined(USE_MB) && defined(USE_MB_IDENT)
737
      if (use_mb(cs))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
738
      {
739
	result_state= IDENT_QUOTED;
740
        while (ident_map[c=yyGet()])
bk@work.mysql.com's avatar
bk@work.mysql.com committed
741
        {
742
          if (my_mbcharlen(cs, c) > 1)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
743 744
          {
            int l;
745
            if ((l = my_ismbchar(cs,
bk@work.mysql.com's avatar
bk@work.mysql.com committed
746 747 748 749 750 751 752 753 754
                                 (const char *)lex->ptr-1,
                                 (const char *)lex->end_of_query)) == 0)
              break;
            lex->ptr += l-1;
          }
        }
      }
      else
#endif
755 756 757 758 759
      {
        for (result_state=0; ident_map[c= yyGet()]; result_state|= c);
        /* If there were non-ASCII characters, mark that we must convert */
        result_state= result_state & 0x80 ? IDENT_QUOTED : IDENT;
      }
760
      if (c == '.' && ident_map[yyPeek()])
761
	lex->next_state=MY_LEX_IDENT_SEP;// Next is '.'
bk@work.mysql.com's avatar
bk@work.mysql.com committed
762

763 764
      yylval->lex_str= get_token(lex,yyLength());
      return(result_state);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
765

766
    case MY_LEX_USER_VARIABLE_DELIMITER:	// Found quote char
767
    {
768 769
      uint double_quotes= 0;
      char quote_char= c;                       // Used char
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
770
      lex->tok_start=lex->ptr;			// Skip first `
771
      while ((c=yyGet()))
772
      {
773 774
	int length;
	if ((length= my_mbcharlen(cs, c)) == 1)
775 776 777 778 779 780 781 782 783
	{
	  if (c == quote_char)
	  {
	    if (yyPeek() != quote_char)
	      break;
	    c=yyGet();
	    double_quotes++;
	    continue;
	  }
784 785
	}
#ifdef USE_MB
786 787 788
	else if (length < 1)
	  break;				// Error
	lex->ptr+= length-1;
789
#endif
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
790
      }
791 792 793 794 795 796
      if (double_quotes)
	yylval->lex_str=get_quoted_token(lex,yyLength() - double_quotes,
					 quote_char);
      else
	yylval->lex_str=get_token(lex,yyLength());
      if (c == quote_char)
797
	yySkip();			// Skip end `
798
      lex->next_state= MY_LEX_START;
799
      return(IDENT_QUOTED);
800
    }
801
    case MY_LEX_INT_OR_REAL:		// Compleat int or incompleat real
bk@work.mysql.com's avatar
bk@work.mysql.com committed
802 803 804 805 806 807
      if (c != '.')
      {					// Found complete integer number.
	yylval->lex_str=get_token(lex,yyLength());
	return int_token(yylval->lex_str.str,yylval->lex_str.length);
      }
      // fall through
808 809
    case MY_LEX_REAL:			// Incomplete real number
      while (my_isdigit(cs,c = yyGet())) ;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
810 811 812 813

      if (c == 'e' || c == 'E')
      {
	c = yyGet();
814
	if (c == '-' || c == '+')
815
	  c = yyGet();			// Skip sign
816
	if (!my_isdigit(cs,c))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
817
	{				// No digit after sign
818
	  state= MY_LEX_CHAR;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
819 820
	  break;
	}
821
	while (my_isdigit(cs,yyGet())) ;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
822 823 824 825
	yylval->lex_str=get_token(lex,yyLength());
	return(FLOAT_NUM);
      }
      yylval->lex_str=get_token(lex,yyLength());
826
      return(DECIMAL_NUM);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
827

828
    case MY_LEX_HEX_NUMBER:		// Found x'hexstring'
829
      yyGet();				// Skip '
830
      while (my_isxdigit(cs,(c = yyGet()))) ;
831 832 833 834 835 836 837 838 839 840 841 842
      length=(lex->ptr - lex->tok_start);	// Length of hexnum+3
      if (!(length & 1) || c != '\'')
      {
	return(ABORT_SYM);		// Illegal hex constant
      }
      yyGet();				// get_token makes an unget
      yylval->lex_str=get_token(lex,length);
      yylval->lex_str.str+=2;		// Skip x'
      yylval->lex_str.length-=3;	// Don't count x' and last '
      lex->yytoklen-=3;
      return (HEX_NUM);

ram@gw.mysql.r18.ru's avatar
ram@gw.mysql.r18.ru committed
843 844 845 846 847 848 849 850 851 852 853 854 855
    case MY_LEX_BIN_NUMBER:           // Found b'bin-string'
      yyGet();                                // Skip '
      while ((c= yyGet()) == '0' || c == '1');
      length= (lex->ptr - lex->tok_start);    // Length of bin-num + 3
      if (c != '\'')
      return(ABORT_SYM);              // Illegal hex constant
      yyGet();                        // get_token makes an unget
      yylval->lex_str= get_token(lex, length);
      yylval->lex_str.str+= 2;        // Skip b'
      yylval->lex_str.length-= 3;     // Don't count b' and last '
      lex->yytoklen-= 3;
      return (BIN_NUM); 

856 857 858
    case MY_LEX_CMP_OP:			// Incomplete comparison operator
      if (state_map[yyPeek()] == MY_LEX_CMP_OP ||
	  state_map[yyPeek()] == MY_LEX_LONG_CMP_OP)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
859 860 861
	yySkip();
      if ((tokval = find_keyword(lex,(uint) (lex->ptr - lex->tok_start),0)))
      {
862
	lex->next_state= MY_LEX_START;	// Allow signed numbers
bk@work.mysql.com's avatar
bk@work.mysql.com committed
863 864
	return(tokval);
      }
865
      state = MY_LEX_CHAR;		// Something fishy found
bk@work.mysql.com's avatar
bk@work.mysql.com committed
866 867
      break;

868 869 870
    case MY_LEX_LONG_CMP_OP:		// Incomplete comparison operator
      if (state_map[yyPeek()] == MY_LEX_CMP_OP ||
	  state_map[yyPeek()] == MY_LEX_LONG_CMP_OP)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
871 872
      {
	yySkip();
873
	if (state_map[yyPeek()] == MY_LEX_CMP_OP)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
874 875 876 877
	  yySkip();
      }
      if ((tokval = find_keyword(lex,(uint) (lex->ptr - lex->tok_start),0)))
      {
878
	lex->next_state= MY_LEX_START;	// Found long op
bk@work.mysql.com's avatar
bk@work.mysql.com committed
879 880
	return(tokval);
      }
881
      state = MY_LEX_CHAR;		// Something fishy found
bk@work.mysql.com's avatar
bk@work.mysql.com committed
882 883
      break;

884
    case MY_LEX_BOOL:
bk@work.mysql.com's avatar
bk@work.mysql.com committed
885 886
      if (c != yyPeek())
      {
887
	state=MY_LEX_CHAR;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
888 889 890 891
	break;
      }
      yySkip();
      tokval = find_keyword(lex,2,0);	// Is a bool operator
892
      lex->next_state= MY_LEX_START;	// Allow signed numbers
bk@work.mysql.com's avatar
bk@work.mysql.com committed
893 894
      return(tokval);

895
    case MY_LEX_STRING_OR_DELIMITER:
896 897
      if (((THD *) yythd)->variables.sql_mode & MODE_ANSI_QUOTES)
      {
898
	state= MY_LEX_USER_VARIABLE_DELIMITER;
899 900 901
	break;
      }
      /* " used for strings */
902
    case MY_LEX_STRING:			// Incomplete text string
bk@work.mysql.com's avatar
bk@work.mysql.com committed
903 904
      if (!(yylval->lex_str.str = get_text(lex)))
      {
905
	state= MY_LEX_CHAR;		// Read char by char
bk@work.mysql.com's avatar
bk@work.mysql.com committed
906 907 908 909 910
	break;
      }
      yylval->lex_str.length=lex->yytoklen;
      return(TEXT_STRING);

911
    case MY_LEX_COMMENT:			//  Comment
912
      lex->select_lex.options|= OPTION_FOUND_COMMENT;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
913 914
      while ((c = yyGet()) != '\n' && c) ;
      yyUnget();			// Safety against eof
915
      state = MY_LEX_START;		// Try again
bk@work.mysql.com's avatar
bk@work.mysql.com committed
916
      break;
917
    case MY_LEX_LONG_COMMENT:		/* Long C comment? */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
918 919
      if (yyPeek() != '*')
      {
920
	state=MY_LEX_CHAR;		// Probable division
bk@work.mysql.com's avatar
bk@work.mysql.com committed
921 922 923
	break;
      }
      yySkip();				// Skip '*'
924
      lex->select_lex.options|= OPTION_FOUND_COMMENT;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
925 926 927 928
      if (yyPeek() == '!')		// MySQL command in comment
      {
	ulong version=MYSQL_VERSION_ID;
	yySkip();
929 930
	state=MY_LEX_START;
	if (my_isdigit(cs,yyPeek()))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947
	{				// Version number
	  version=strtol((char*) lex->ptr,(char**) &lex->ptr,10);
	}
	if (version <= MYSQL_VERSION_ID)
	{
	  lex->in_comment=1;
	  break;
	}
      }
      while (lex->ptr != lex->end_of_query &&
	     ((c=yyGet()) != '*' || yyPeek() != '/'))
      {
	if (c == '\n')
	  lex->yylineno++;
      }
      if (lex->ptr != lex->end_of_query)
	yySkip();			// remove last '/'
948
      state = MY_LEX_START;		// Try again
bk@work.mysql.com's avatar
bk@work.mysql.com committed
949
      break;
950
    case MY_LEX_END_LONG_COMMENT:
bk@work.mysql.com's avatar
bk@work.mysql.com committed
951 952 953 954
      if (lex->in_comment && yyPeek() == '/')
      {
	yySkip();
	lex->in_comment=0;
955
	state=MY_LEX_START;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
956 957
      }
      else
958
	state=MY_LEX_CHAR;		// Return '*'
bk@work.mysql.com's avatar
bk@work.mysql.com committed
959
      break;
960
    case MY_LEX_SET_VAR:		// Check if ':='
bk@work.mysql.com's avatar
bk@work.mysql.com committed
961 962
      if (yyPeek() != '=')
      {
963
	state=MY_LEX_CHAR;		// Return ':'
bk@work.mysql.com's avatar
bk@work.mysql.com committed
964 965 966 967
	break;
      }
      yySkip();
      return (SET_VAR);
968
    case MY_LEX_SEMICOLON:			// optional line terminator
bk@work.mysql.com's avatar
bk@work.mysql.com committed
969 970
      if (yyPeek())
      {
971 972
        THD* thd= (THD*)yythd;
        if ((thd->client_capabilities & CLIENT_MULTI_STATEMENTS) && 
973
            !lex->stmt_prepare_mode)
974
        {
monty@mysql.com's avatar
monty@mysql.com committed
975
	  lex->safe_to_cache_query= 0;
serg@serg.mylan's avatar
serg@serg.mylan committed
976
          lex->found_semicolon=(char*) lex->ptr;
monty@mysql.com's avatar
monty@mysql.com committed
977 978 979
          thd->server_status|= SERVER_MORE_RESULTS_EXISTS;
          lex->next_state=     MY_LEX_END;
          return (END_OF_INPUT);
980
        }
monty@mysql.com's avatar
monty@mysql.com committed
981
        state= MY_LEX_CHAR;		// Return ';'
bk@work.mysql.com's avatar
bk@work.mysql.com committed
982 983 984
	break;
      }
      /* fall true */
985
    case MY_LEX_EOL:
986 987 988 989 990 991 992
      if (lex->ptr >= lex->end_of_query)
      {
	lex->next_state=MY_LEX_END;	// Mark for next loop
	return(END_OF_INPUT);
      }
      state=MY_LEX_CHAR;
      break;
993 994
    case MY_LEX_END:
      lex->next_state=MY_LEX_END;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
995
      return(0);			// We found end of input last time
996 997
      
      /* Actually real shouldn't start with . but allow them anyhow */
998 999 1000
    case MY_LEX_REAL_OR_POINT:
      if (my_isdigit(cs,yyPeek()))
	state = MY_LEX_REAL;		// Real
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1001 1002
      else
      {
1003 1004
	state= MY_LEX_IDENT_SEP;	// return '.'
	yyUnget();			// Put back '.'
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1005 1006
      }
      break;
1007
    case MY_LEX_USER_END:		// end '@' of user@hostname
1008
      switch (state_map[yyPeek()]) {
1009 1010 1011
      case MY_LEX_STRING:
      case MY_LEX_USER_VARIABLE_DELIMITER:
      case MY_LEX_STRING_OR_DELIMITER:
1012
	break;
1013 1014
      case MY_LEX_USER_END:
	lex->next_state=MY_LEX_SYSTEM_VAR;
1015 1016
	break;
      default:
1017
	lex->next_state=MY_LEX_HOSTNAME;
1018 1019
	break;
      }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1020 1021 1022
      yylval->lex_str.str=(char*) lex->ptr;
      yylval->lex_str.length=1;
      return((int) '@');
1023 1024 1025
    case MY_LEX_HOSTNAME:		// end '@' of user@hostname
      for (c=yyGet() ; 
	   my_isalnum(cs,c) || c == '.' || c == '_' ||  c == '$';
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1026 1027 1028
	   c= yyGet()) ;
      yylval->lex_str=get_token(lex,yyLength());
      return(LEX_HOSTNAME);
1029
    case MY_LEX_SYSTEM_VAR:
1030 1031 1032
      yylval->lex_str.str=(char*) lex->ptr;
      yylval->lex_str.length=1;
      yySkip();					// Skip '@'
1033 1034 1035 1036
      lex->next_state= (state_map[yyPeek()] ==
			MY_LEX_USER_VARIABLE_DELIMITER ?
			MY_LEX_OPERATOR_OR_IDENT :
			MY_LEX_IDENT_OR_KEYWORD);
1037
      return((int) '@');
1038
    case MY_LEX_IDENT_OR_KEYWORD:
1039 1040 1041 1042 1043
      /*
	We come here when we have found two '@' in a row.
	We should now be able to handle:
	[(global | local | session) .]variable_name
      */
1044 1045 1046 1047 1048
      
      for (result_state= 0; ident_map[c= yyGet()]; result_state|= c);
      /* If there were non-ASCII characters, mark that we must convert */
      result_state= result_state & 0x80 ? IDENT_QUOTED : IDENT;
      
1049
      if (c == '.')
1050
	lex->next_state=MY_LEX_IDENT_SEP;
1051
      length= (uint) (lex->ptr - lex->tok_start)-1;
1052 1053
      if (length == 0) 
        return(ABORT_SYM);              // Names must be nonempty.
1054 1055 1056 1057 1058 1059
      if ((tokval= find_keyword(lex,length,0)))
      {
	yyUnget();				// Put back 'c'
	return(tokval);				// Was keyword
      }
      yylval->lex_str=get_token(lex,length);
1060
      return(result_state);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1061 1062 1063
    }
  }
}
1064

1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080

/*
  Skip comment in the end of statement.

  SYNOPSIS
    skip_rear_comments()
      begin   pointer to the beginning of statement
      end     pointer to the end of statement

  DESCRIPTION
    The function is intended to trim comments at the end of the statement.

  RETURN
    Pointer to the last non-comment symbol of the statement.
*/

1081
const uchar *skip_rear_comments(const uchar *begin, const uchar *end)
1082 1083 1084 1085 1086 1087 1088
{
  while (begin < end && (end[-1] <= ' ' || end[-1] == '*' ||
                         end[-1] == '/' || end[-1] == ';'))
    end-= 1;
  return end;
}

1089 1090 1091 1092 1093 1094
/*
  st_select_lex structures initialisations
*/

void st_select_lex_node::init_query()
{
1095
  options= 0;
1096
  sql_cache= SQL_CACHE_UNSPECIFIED;
1097
  linkage= UNSPECIFIED_TYPE;
1098 1099
  no_error= no_table_names_allowed= 0;
  uncacheable= 0;
1100 1101 1102 1103 1104 1105 1106 1107 1108
}

void st_select_lex_node::init_select()
{
}

void st_select_lex_unit::init_query()
{
  st_select_lex_node::init_query();
1109
  linkage= GLOBAL_OPTIONS_TYPE;
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
1110
  global_parameters= first_select();
1111 1112
  select_limit_cnt= HA_POS_ERROR;
  offset_limit_cnt= 0;
1113
  union_distinct= 0;
1114
  prepared= optimized= executed= 0;
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
1115
  item= 0;
1116 1117
  union_result= 0;
  table= 0;
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
1118
  fake_select_lex= 0;
1119
  cleaned= 0;
1120
  item_list.empty();
1121
  describe= 0;
1122
  found_rows_for_union= 0;
1123 1124 1125 1126 1127
}

void st_select_lex::init_query()
{
  st_select_lex_node::init_query();
1128
  table_list.empty();
1129 1130
  top_join_list.empty();
  join_list= &top_join_list;
1131
  embedding= leaf_tables= 0;
1132
  item_list.empty();
1133
  join= 0;
1134
  having= prep_having= where= prep_where= 0;
1135
  olap= UNSPECIFIED_OLAP_TYPE;
1136
  having_fix_field= 0;
1137 1138
  context.select_lex= this;
  context.init();
1139 1140 1141
  /*
    Add the name resolution context of the current (sub)query to the
    stack of contexts for the whole query.
1142 1143 1144 1145 1146
    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.
1147 1148
  */
  parent_lex->push_context(&context);
1149
  cond_count= between_count= with_wild= 0;
1150
  conds_processed_with_permanent_arena= 0;
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
1151
  ref_pointer_array= 0;
bell@laptop.sanja.is.com.ua's avatar
bell@laptop.sanja.is.com.ua committed
1152
  select_n_having_items= 0;
1153
  subquery_in_having= explicit_limit= 0;
1154
  is_item_list_lookup= 0;
1155
  first_execution= 1;
1156
  first_cond_optimization= 1;
1157
  parsing_place= NO_MATTER;
1158
  exclude_from_table_unique_test= no_wrap_view_item= FALSE;
igor@rurik.mysql.com's avatar
igor@rurik.mysql.com committed
1159
  nest_level= 0;
1160
  link_next= 0;
1161 1162 1163 1164 1165
}

void st_select_lex::init_select()
{
  st_select_lex_node::init_select();
1166
  group_list.empty();
1167
  type= db= 0;
1168 1169 1170 1171
  having= 0;
  use_index_ptr= ignore_index_ptr= 0;
  table_join_options= 0;
  in_sum_expr= with_wild= 0;
1172
  options= 0;
1173
  sql_cache= SQL_CACHE_UNSPECIFIED;
1174
  braces= 0;
1175
  when_list.empty();
1176
  expr_list.empty();
1177
  interval_list.empty();
1178
  use_index.empty();
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
1179
  ftfunc_list_alloc.empty();
igor@rurik.mysql.com's avatar
igor@rurik.mysql.com committed
1180
  inner_sum_func_list= 0;
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
1181
  ftfunc_list= &ftfunc_list_alloc;
1182
  linkage= UNSPECIFIED_TYPE;
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
1183 1184 1185
  order_list.elements= 0;
  order_list.first= 0;
  order_list.next= (byte**) &order_list.first;
1186 1187 1188
  /* 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
1189
  with_sum_func= 0;
1190

1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204
}

/*
  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;
1205
  slave= 0;
1206 1207
}

bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
1208 1209
/*
  include on level down (but do not link)
1210

bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224
  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;
}

1225 1226 1227 1228 1229 1230 1231 1232
/* 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;
1233
  slave= 0;
1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247
}

/* 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()
{
1248
  if (link_prev)
1249 1250 1251 1252
  {
    if ((*link_prev= link_next))
      link_next->link_prev= link_prev;
  }
1253 1254 1255 1256
  // Remove slave structure
  for (; slave; slave= slave->next)
    slave->fast_exclude();
  
1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276
}

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

1278 1279 1280 1281 1282 1283 1284 1285 1286 1287

/*
  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 
*/
1288 1289 1290
void st_select_lex_unit::exclude_level()
{
  SELECT_LEX_UNIT *units= 0, **units_last= &units;
1291
  for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
1292
  {
1293
    // unlink current level from global SELECTs list
1294 1295
    if (sl->link_prev && (*sl->link_prev= sl->link_next))
      sl->link_next->link_prev= sl->link_prev;
1296 1297

    // bring up underlay levels
1298 1299
    SELECT_LEX_UNIT **last= 0;
    for (SELECT_LEX_UNIT *u= sl->first_inner_unit(); u; u= u->next_unit())
1300 1301
    {
      u->master= master;
1302
      last= (SELECT_LEX_UNIT**)&(u->next);
1303
    }
1304 1305 1306 1307 1308 1309 1310 1311
    if (last)
    {
      (*units_last)= sl->first_inner_unit();
      units_last= last;
    }
  }
  if (units)
  {
1312
    // include brought up levels in place of current
1313 1314
    (*prev)= units;
    (*units_last)= (SELECT_LEX_UNIT*)next;
1315 1316 1317
    if (next)
      next->prev= (SELECT_LEX_NODE**)units_last;
    units->prev= prev;
1318 1319
  }
  else
1320 1321
  {
    // exclude currect unit from list of nodes
1322
    (*prev)= next;
1323 1324 1325
    if (next)
      next->prev= prev;
  }
1326 1327
}

1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338

/*
  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())
  {
1339
    // unlink current level from global SELECTs list
1340 1341 1342
    if (sl->link_prev && (*sl->link_prev= sl->link_next))
      sl->link_next->link_prev= sl->link_prev;

1343
    // unlink underlay levels
1344 1345 1346 1347 1348
    for (SELECT_LEX_UNIT *u= sl->first_inner_unit(); u; u= u->next_unit())
    {
      u->exclude_level();
    }
  }
1349
  // exclude currect unit from list of nodes
1350
  (*prev)= next;
1351 1352
  if (next)
    next->prev= prev;
1353 1354 1355
}


1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367
/*
  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
1368
void st_select_lex::mark_as_dependent(SELECT_LEX *last)
1369 1370 1371 1372 1373
{
  /*
    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
1374
  for (SELECT_LEX *s= this;
1375
       s && s != last;
1376
       s= s->outer_select())
1377
    if (!(s->uncacheable & UNCACHEABLE_DEPENDENT))
1378 1379
    {
      // Select is dependent of outer select
1380
      s->uncacheable|= UNCACHEABLE_DEPENDENT;
1381
      SELECT_LEX_UNIT *munit= s->master_unit();
1382
      munit->uncacheable|= UNCACHEABLE_DEPENDENT;
1383 1384 1385
    }
}

1386 1387 1388 1389 1390 1391 1392
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; }
List<String>* st_select_lex_node::get_use_index()    { return 0; }
List<String>* st_select_lex_node::get_ignore_index() { return 0; }
monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
1393
TABLE_LIST *st_select_lex_node::add_table_to_list(THD *thd, Table_ident *table,
1394
						  LEX_STRING *alias,
monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
1395
						  ulong table_join_options,
1396 1397
						  thr_lock_type flags,
						  List<String> *use_index,
igor@rurik.mysql.com's avatar
igor@rurik.mysql.com committed
1398 1399
						  List<String> *ignore_index,
                                                  LEX_STRING *option)
1400 1401 1402
{
  return 0;
}
1403 1404 1405 1406 1407 1408 1409 1410
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
1411
bool st_select_lex::test_limit()
1412
{
1413
  if (select_limit != 0)
1414 1415
  {
    my_error(ER_NOT_SUPPORTED_YET, MYF(0),
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
1416
             "LIMIT & IN/ALL/ANY/SOME subquery");
1417 1418 1419 1420 1421 1422
    return(1);
  }
  // no sense in ORDER BY without LIMIT
  order_list.empty();
  return(0);
}
1423

1424

1425 1426 1427 1428 1429
st_select_lex_unit* st_select_lex_unit::master_unit()
{
    return this;
}

1430

1431 1432 1433 1434 1435
st_select_lex* st_select_lex_unit::outer_select()
{
  return (st_select_lex*) master;
}

1436

bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
1437
bool st_select_lex::add_order_to_list(THD *thd, Item *item, bool asc)
1438
{
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
1439
  return add_to_list(thd, order_list, item, asc);
1440
}
1441

1442

monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
1443
bool st_select_lex::add_item_to_list(THD *thd, Item *item)
1444
{
1445 1446 1447
  DBUG_ENTER("st_select_lex::add_item_to_list");
  DBUG_PRINT("info", ("Item: %p", item));
  DBUG_RETURN(item_list.push_back(item));
1448 1449
}

1450

monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
1451
bool st_select_lex::add_group_to_list(THD *thd, Item *item, bool asc)
1452
{
monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
1453
  return add_to_list(thd, group_list, item, asc);
1454 1455
}

1456

1457 1458 1459 1460 1461
bool st_select_lex::add_ftfunc_to_list(Item_func_match *func)
{
  return !func || ftfunc_list->push_back(func); // end of memory?
}

1462

1463 1464 1465 1466 1467
st_select_lex_unit* st_select_lex::master_unit()
{
  return (st_select_lex_unit*) master;
}

1468

1469 1470 1471 1472 1473
st_select_lex* st_select_lex::outer_select()
{
  return (st_select_lex*) master->get_master();
}

1474

1475 1476 1477 1478 1479 1480
bool st_select_lex::set_braces(bool value)
{
  braces= value;
  return 0; 
}

1481

1482 1483 1484 1485 1486 1487
bool st_select_lex::inc_in_sum_expr()
{
  in_sum_expr++;
  return 0;
}

1488

1489 1490 1491 1492 1493
uint st_select_lex::get_in_sum_expr()
{
  return in_sum_expr;
}

1494

1495 1496 1497 1498 1499 1500 1501 1502 1503 1504
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;
}

1505

1506 1507 1508 1509 1510
List<String>* st_select_lex::get_use_index()
{
  return use_index_ptr;
}

1511

1512 1513 1514 1515 1516
List<String>* st_select_lex::get_ignore_index()
{
  return ignore_index_ptr;
}

1517

monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
1518 1519 1520 1521 1522
ulong st_select_lex::get_table_join_options()
{
  return table_join_options;
}

1523

bell@laptop.sanja.is.com.ua's avatar
bell@laptop.sanja.is.com.ua committed
1524 1525 1526 1527
bool st_select_lex::setup_ref_array(THD *thd, uint order_group_num)
{
  if (ref_pointer_array)
    return 0;
1528 1529 1530 1531 1532

  /*
    We have to create array in prepared statement memory if it is
    prepared statement
  */
konstantin@mysql.com's avatar
konstantin@mysql.com committed
1533
  Query_arena *arena= thd->stmt_arena;
serg@serg.mylan's avatar
serg@serg.mylan committed
1534
  return (ref_pointer_array=
1535 1536 1537 1538
          (Item **)arena->alloc(sizeof(Item*) * (n_child_sum_items +
                                                 item_list.elements +
                                                 select_n_having_items +
                                                 order_group_num)*5)) == 0;
bell@laptop.sanja.is.com.ua's avatar
bell@laptop.sanja.is.com.ua committed
1539 1540
}

1541

1542 1543
void st_select_lex_unit::print(String *str)
{
1544
  bool union_all= !union_distinct;
1545 1546 1547 1548
  for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
  {
    if (sl != first_select())
    {
1549
      str->append(STRING_WITH_LEN(" union "));
1550
      if (union_all)
1551
	str->append(STRING_WITH_LEN("all "));
1552
      else if (union_distinct == sl)
1553
        union_all= TRUE;
1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564
    }
    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)
    {
1565
      str->append(STRING_WITH_LEN(" order by "));
1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578
      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)
  {
1579 1580 1581
    if (order->counter_used)
    {
      char buffer[20];
monty@mysql.com's avatar
monty@mysql.com committed
1582 1583
      uint length= my_snprintf(buffer, 20, "%d", order->counter);
      str->append(buffer, length);
1584 1585 1586
    }
    else
      (*order->item)->print(str);
1587
    if (!order->asc)
1588
      str->append(STRING_WITH_LEN(" desc"));
1589 1590 1591 1592 1593
    if (order->next)
      str->append(',');
  }
}
 
1594

1595 1596
void st_select_lex::print_limit(THD *thd, String *str)
{
1597 1598 1599
  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
1600 1601 1602 1603
      (item->substype() == Item_subselect::EXISTS_SUBS ||
       item->substype() == Item_subselect::IN_SUBS ||
       item->substype() == Item_subselect::ALL_SUBS))
  {
1604 1605
    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
1606 1607 1608
    return;
  }

1609
  if (explicit_limit)
1610
  {
1611
    str->append(STRING_WITH_LEN(" limit "));
1612 1613
    if (offset_limit)
    {
1614
      offset_limit->print(str);
1615 1616
      str->append(',');
    }
1617
    select_limit->print(str);
1618 1619 1620
  }
}

bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
1621

1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645
/*
  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)
{
  query_tables= 0;
  query_tables_last= &query_tables;
  query_tables_own_last= 0;
  if (init)
1646 1647 1648 1649 1650 1651 1652
  {
    /*
      We delay real initialization of hash (and therefore related
      memory allocation) until first insertion into this hash.
    */
    hash_clear(&sroutines);
  }
1653
  else if (sroutines.records)
1654 1655
  {
    /* Non-zero sroutines.records means that hash was initialized. */
1656
    my_hash_reset(&sroutines);
1657
  }
1658 1659 1660
  sroutines_list.empty();
  sroutines_list_own_last= sroutines_list.next;
  sroutines_list_own_elements= 0;
1661 1662 1663
#ifdef HAVE_ROW_BASED_REPLICATION
  binlog_row_based_if_mixed= FALSE;
#endif
1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679
}


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


1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694
/*
  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
1695
  :result(0), yacc_yyss(0), yacc_yyvs(0),
1696
   sql_command(SQLCOM_END)
1697
{
1698
  reset_query_tables_list(TRUE);
1699 1700 1701
}


bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
1702
/*
1703
  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
1704 1705 1706 1707

  SYNOPSIS
    st_lex::can_be_merged()

1708
  DESCRIPTION
1709 1710 1711
    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,
1712 1713 1714
    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
1715 1716 1717 1718 1719 1720 1721 1722 1723 1724
  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 */
1725 1726 1727 1728 1729 1730 1731 1732
  bool selects_allow_merge= select_lex.next_select() == 0;
  if (selects_allow_merge)
  {
    for (SELECT_LEX_UNIT *unit= select_lex.first_inner_unit();
         unit;
         unit= unit->next_unit())
    {
      if (unit->first_select()->parent_lex == this &&
igor@rurik.mysql.com's avatar
igor@rurik.mysql.com committed
1733 1734
          (unit->item == 0 ||
           (unit->item->place() != IN_WHERE && unit->item->place() != IN_ON)))
1735 1736 1737 1738 1739 1740 1741 1742
      {
        selects_allow_merge= 0;
        break;
      }
    }
  }

  return (selects_allow_merge &&
bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
1743 1744 1745
	  select_lex.order_list.elements == 0 &&
	  select_lex.group_list.elements == 0 &&
	  select_lex.having == 0 &&
1746
          select_lex.with_sum_func == 0 &&
1747
	  select_lex.table_list.elements >= 1 &&
bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
1748
	  !(select_lex.options & SELECT_DISTINCT) &&
1749
          select_lex.select_limit == 0);
bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
1750 1751
}

1752

bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
1753
/*
1754
  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
1755 1756 1757 1758

  SYNOPSIS
    st_lex::can_use_merged()

1759 1760 1761 1762 1763
  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
1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782
  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:
1783
  case SQLCOM_LOAD:
bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
1784 1785 1786 1787 1788 1789
    return TRUE;
  default:
    return FALSE;
  }
}

1790
/*
1791
  Check if command can't use merged views in any part of command
1792 1793 1794 1795

  SYNOPSIS
    st_lex::can_not_use_merged()

1796 1797 1798 1799
  DESCRIPTION
    Temporary table algorithm will be used on all SELECT levels for queries
    listed here (see also st_lex::can_use_merged()).

1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810
  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:
1811 1812 1813 1814 1815 1816
  /*
    SQLCOM_SHOW_FIELDS is necessary to make 
    information schema tables working correctly with views.
    see get_schema_tables_result function
  */
  case SQLCOM_SHOW_FIELDS:
1817 1818 1819 1820 1821 1822
    return TRUE;
  default:
    return FALSE;
  }
}

bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
1823 1824 1825 1826 1827 1828 1829 1830 1831 1832
/*
  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
*/
1833

bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
1834 1835
bool st_lex::only_view_structure()
{
1836
  switch (sql_command) {
bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850
  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;
  }
}


1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875
/*
  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;
  }
}

1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900
/*
  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;
}

1901

bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
1902 1903 1904 1905 1906 1907 1908
/*
  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
1909

1910
void st_select_lex_unit::set_limit(SELECT_LEX *sl)
1911
{
1912
  ha_rows select_limit_val;
1913

konstantin@mysql.com's avatar
konstantin@mysql.com committed
1914
  DBUG_ASSERT(! thd->stmt_arena->is_stmt_prepare());
1915 1916 1917 1918
  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));
1919 1920
  select_limit_cnt= select_limit_val + offset_limit_cnt;
  if (select_limit_cnt < select_limit_val)
1921 1922 1923
    select_limit_cnt= HA_POS_ERROR;		// no limit
}

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

1925
/*
1926 1927
  Unlink the first table from the global table list and the first table from
  outer select (lex->select_lex) local list
1928 1929 1930

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

bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
1933
  NOTES
1934 1935
    We assume that first tables in both lists is the same table or the local
    list is empty.
1936 1937

  RETURN
1938
    0	If 'query_tables' == 0
bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
1939
    unlinked table
1940
      In this case link_to_local is set.
1941

1942
*/
bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
1943
TABLE_LIST *st_lex::unlink_first_table(bool *link_to_local)
1944
{
bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
1945 1946 1947 1948 1949 1950 1951 1952
  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;
1953 1954
    else
      query_tables_last= &query_tables;
bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
1955 1956 1957 1958 1959 1960 1961
    first->next_global= 0;

    /*
      and from local list if it is not empty
    */
    if ((*link_to_local= test(select_lex.table_list.first)))
    {
1962 1963
      select_lex.context.table_list= 
        select_lex.context.first_name_resolution_table= first->next_local;
1964
      select_lex.table_list.first= (byte*) (first->next_local);
bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
1965 1966 1967
      select_lex.table_list.elements--;	//safety
      first->next_local= 0;
      /*
1968 1969
        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
1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985
      */
      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
1986 1987 1988 1989 1990 1991
    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
1992 1993 1994 1995 1996 1997 1998
*/

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)
  {
1999
    TABLE_LIST *next;
bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
2000 2001
    if (query_tables_last == &first_table->next_global)
      query_tables_last= first_table->prev_global;
2002

2003
    if ((next= *first_table->prev_global= first_table->next_global))
bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
2004 2005 2006 2007
      next->prev_global= first_table->prev_global;
    /* include in new place */
    first_table->next_global= query_tables;
    /*
2008 2009 2010
       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
2011 2012 2013 2014 2015
    */
    query_tables->prev_global= &first_table->next_global;
    first_table->prev_global= &query_tables;
    query_tables= first_table;
  }
2016 2017
}

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

2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043
/*
  Add implicitly used time zone description tables to global table list
  (if needed).

  SYNOPSYS
    st_lex::add_time_zone_tables_to_query_tables()
      thd - pointer to current thread context

  RETURN VALUE
   TRUE  - error
   FALSE - success
*/

bool st_lex::add_time_zone_tables_to_query_tables(THD *thd)
{
  /* We should not add these tables twice */
  if (!time_zone_tables_used)
  {
    time_zone_tables_used= my_tz_get_table_list(thd, &query_tables_last);
    if (time_zone_tables_used == &fake_time_zone_tables_list)
      return TRUE;
  }
  return FALSE;
}

2044
/*
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
2045
  Link table back that was unlinked with unlink_first_table()
2046 2047 2048

  SYNOPSIS
    link_first_table_back()
bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
2049
    link_to_local	do we need link this table to local
2050 2051 2052 2053

  RETURN
    global list
*/
bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
2054 2055 2056

void st_lex::link_first_table_back(TABLE_LIST *first,
				   bool link_to_local)
2057
{
bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
2058
  if (first)
2059
  {
bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
2060 2061
    if ((first->next_global= query_tables))
      query_tables->prev_global= &first->next_global;
2062 2063
    else
      query_tables_last= &first->next_global;
bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
2064 2065 2066 2067 2068
    query_tables= first;

    if (link_to_local)
    {
      first->next_local= (TABLE_LIST*) select_lex.table_list.first;
2069 2070
      select_lex.context.table_list= first;
      select_lex.table_list.first= (byte*) first;
bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
2071 2072 2073 2074 2075 2076
      select_lex.table_list.elements++;	//safety
    }
  }
}


2077 2078 2079 2080 2081 2082

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

  SYNOPSIS
    st_lex::cleanup_after_one_table_open()
2083 2084 2085 2086 2087

  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).
2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113
*/

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();
  }
  time_zone_tables_used= 0;
2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148
}


/*
  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);
2149 2150 2151
}


2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173
/*
  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);
}


2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202
/*
  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
2203
/*
2204
  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
2205 2206 2207

  SYNOPSIS
    st_select_lex::fix_prepare_information
2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218
      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
2219 2220
*/

2221 2222
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
2223
{
konstantin@mysql.com's avatar
konstantin@mysql.com committed
2224
  if (!thd->stmt_arena->is_conventional() && first_execution)
bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
2225 2226
  {
    first_execution= 0;
2227 2228 2229 2230 2231
    if (*conds)
    {
      prep_where= *conds;
      *conds= where= prep_where->copy_andor_structure(thd);
    }
2232 2233 2234 2235 2236
    if (*having_conds)
    {
      prep_having= *having_conds;
      *having_conds= having= prep_having->copy_andor_structure(thd);
    }
2237
    fix_prepare_info_in_table_list(thd, (TABLE_LIST *)table_list.first);
2238 2239 2240
  }
}

2241

2242
/*
bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
2243
  There are st_select_lex::add_table_to_list &
2244
  st_select_lex::set_lock_for_tables are in sql_parse.cc
2245

bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
2246
  st_select_lex::print is in sql_select.cc
2247 2248

  st_select_lex_unit::prepare, st_select_lex_unit::exec,
2249 2250
  st_select_lex_unit::cleanup, st_select_lex_unit::reinit_exec_mechanism,
  st_select_lex_unit::change_result
2251
  are in sql_union.cc
2252
*/
2253