~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_lex.cc

  • Committer: Brian Aker
  • Date: 2009-05-18 23:23:17 UTC
  • mfrom: (1014.4.10 refactor-lex)
  • Revision ID: brian@gaz-20090518232317-50gdzwjsp7osgh35
Merge Jay

Show diffs side-by-side

added added

removed removed

Lines of Context:
31
31
 
32
32
static int lex_one_token(void *arg, void *yysession);
33
33
 
34
 
 
35
34
/*
36
35
  We are using pointer to this variable for distinguishing between assignment
37
36
  to NEW row field (when parsing trigger definition) and structured variable.
38
37
*/
39
 
 
40
38
sys_var *trg_new_row_fake_var= (sys_var*) 0x01;
41
39
 
42
40
/**
44
42
*/
45
43
const LEX_STRING null_lex_str= {NULL, 0};
46
44
 
47
 
void
48
 
st_parsing_options::reset()
49
 
{
50
 
  allows_select_procedure= true;
51
 
}
52
 
 
53
45
Lex_input_stream::Lex_input_stream(Session *session,
54
46
                                   const char* buffer,
55
47
                                   unsigned int length)
96
88
  @param begin_ptr  Pointer to the start of the body in the pre-processed
97
89
                    buffer.
98
90
*/
99
 
 
100
91
void Lex_input_stream::body_utf8_start(Session *session, const char *begin_ptr)
101
92
{
102
93
  assert(begin_ptr);
133
124
                  m_cpp_utf8_processed_ptr will be set in the end of the
134
125
                  operation.
135
126
*/
136
 
 
137
127
void Lex_input_stream::body_utf8_append(const char *ptr,
138
128
                                        const char *end_ptr)
139
129
{
162
152
  @param ptr  Pointer in the pre-processed buffer, which specifies the end
163
153
              of the chunk, which should be appended to the utf8 body.
164
154
*/
165
 
 
166
155
void Lex_input_stream::body_utf8_append(const char *ptr)
167
156
{
168
157
  body_utf8_append(ptr, ptr);
179
168
                  m_cpp_utf8_processed_ptr will be set in the end of the
180
169
                  operation.
181
170
*/
182
 
 
183
171
void Lex_input_stream::body_utf8_append_literal(Session *session,
184
172
                                                const LEX_STRING *txt,
185
173
                                                const CHARSET_INFO * const txt_cs,
212
200
  m_cpp_utf8_processed_ptr= end_ptr;
213
201
}
214
202
 
215
 
 
216
203
/*
217
204
  This is called before every query that is to be parsed.
218
205
  Because of this, it's critical to not do too much things here.
219
206
  (We already do too much here)
220
207
*/
221
 
 
222
208
void lex_start(Session *session)
223
209
{
224
210
  LEX *lex= session->lex;
248
234
  lex->select_lex.init_order();
249
235
  lex->select_lex.group_list.empty();
250
236
  lex->describe= 0;
251
 
  lex->subqueries= false;
252
237
  lex->derived_tables= 0;
253
238
  lex->lock_option= TL_READ;
254
239
  lex->leaf_tables_insert= 0;
255
 
  lex->parsing_options.reset();
256
240
  lex->select_lex.select_number= 1;
257
241
  lex->length=0;
258
242
  lex->select_lex.in_sum_expr=0;
290
274
  lex->result= 0;
291
275
}
292
276
 
293
 
 
294
277
static int find_keyword(Lex_input_stream *lip, uint32_t len, bool function)
295
278
{
296
279
  /* Plenty of memory for the largest lex symbol we have */
314
297
  return 0;
315
298
}
316
299
 
317
 
 
318
300
bool is_lex_native_function(const LEX_STRING *name)
319
301
{
320
302
  assert(name != NULL);
322
304
}
323
305
 
324
306
/* make a copy of token before ptr and set yytoklen */
325
 
 
326
307
static LEX_STRING get_token(Lex_input_stream *lip, uint32_t skip, uint32_t length)
327
308
{
328
309
  LEX_STRING tmp;
342
323
   get_quoted_token yet. But it should be fixed in the
343
324
   future to operate multichar strings (like ucs2)
344
325
*/
345
 
 
346
326
static LEX_STRING get_quoted_token(Lex_input_stream *lip,
347
327
                                   uint32_t skip,
348
328
                                   uint32_t length, char quote)
377
357
  Return an unescaped text literal without quotes
378
358
  Fix sometimes to do only one scan of the string
379
359
*/
380
 
 
381
360
static char *get_text(Lex_input_stream *lip, int pre_skip, int post_skip)
382
361
{
383
362
  register unsigned char c,sep;
384
 
  uint32_t found_escape=0;
 
363
  bool found_escape= false;
385
364
  const CHARSET_INFO * const cs= lip->m_session->charset();
386
365
 
387
366
  lip->tok_bitmap= 0;
392
371
    lip->tok_bitmap|= c;
393
372
#ifdef USE_MB
394
373
    {
395
 
      int l;
396
 
      if (use_mb(cs) &&
397
 
          (l = my_ismbchar(cs,
398
 
                           lip->get_ptr() -1,
399
 
                           lip->get_end_of_query()))) {
400
 
        lip->skip_binary(l-1);
401
 
        continue;
 
374
      if (use_mb(cs))
 
375
      {
 
376
        int l= my_ismbchar(cs, lip->get_ptr() -1, lip->get_end_of_query());
 
377
        if (l != 0) 
 
378
        {
 
379
          lip->skip_binary(l-1);
 
380
          continue;
 
381
        }
402
382
      }
403
383
    }
404
384
#endif
405
385
    if (c == '\\')
406
386
    {                                   // Escaped character
407
 
      found_escape=1;
 
387
      found_escape= true;
408
388
      if (lip->eof())
409
 
        return 0;
 
389
        return 0;
410
390
      lip->yySkip();
411
391
    }
412
392
    else if (c == sep)
413
393
    {
414
394
      if (c == lip->yyGet())            // Check if two separators in a row
415
395
      {
416
 
        found_escape=1;                 // duplicate. Remember for delete
417
 
        continue;
 
396
        found_escape= true;                 // duplicate. Remember for delete
 
397
        continue;
418
398
      }
419
399
      else
420
400
        lip->yyUnget();
426
406
      str= lip->get_tok_start();
427
407
      end= lip->get_ptr();
428
408
      /* Extract the text from the token */
429
 
      str += pre_skip;
430
 
      end -= post_skip;
 
409
      str+= pre_skip;
 
410
      end-= post_skip;
431
411
      assert(end >= str);
432
412
 
433
413
      if (!(start= (char*) lip->m_session->alloc((uint32_t) (end-str)+1)))
434
 
        return (char*) "";              // Sql_alloc has set error flag
 
414
        return (char*) "";              // Sql_alloc has set error flag
435
415
 
436
416
      lip->m_cpp_text_start= lip->get_cpp_tok_start() + pre_skip;
437
417
      lip->m_cpp_text_end= lip->get_cpp_ptr() - post_skip;
438
418
 
439
 
      if (!found_escape)
 
419
      if (! found_escape)
440
420
      {
441
 
        lip->yytoklen=(uint32_t) (end-str);
442
 
        memcpy(start,str,lip->yytoklen);
443
 
        start[lip->yytoklen]=0;
 
421
        lip->yytoklen= (uint32_t) (end-str);
 
422
        memcpy(start, str, lip->yytoklen);
 
423
        start[lip->yytoklen]= 0;
444
424
      }
445
425
      else
446
426
      {
447
427
        char *to;
448
428
 
449
 
        for (to=start ; str != end ; str++)
450
 
        {
 
429
        for (to= start; str != end; str++)
 
430
        {
451
431
#ifdef USE_MB
452
 
          int l;
453
 
          if (use_mb(cs) &&
454
 
              (l = my_ismbchar(cs, str, end))) {
455
 
              while (l--)
456
 
                  *to++ = *str++;
457
 
              str--;
458
 
              continue;
459
 
          }
 
432
          if (use_mb(cs))
 
433
          {
 
434
            int l= my_ismbchar(cs, str, end);
 
435
            if (l != 0)
 
436
            {
 
437
              while (l--)
 
438
                *to++= *str++;
 
439
              str--;
 
440
              continue;
 
441
            }
 
442
          }
460
443
#endif
461
 
          if (*str == '\\' && str+1 != end)
462
 
          {
463
 
            switch(*++str) {
464
 
            case 'n':
465
 
              *to++='\n';
466
 
              break;
467
 
            case 't':
468
 
              *to++= '\t';
469
 
              break;
470
 
            case 'r':
471
 
              *to++ = '\r';
472
 
              break;
473
 
            case 'b':
474
 
              *to++ = '\b';
475
 
              break;
476
 
            case '0':
477
 
              *to++= 0;                 // Ascii null
478
 
              break;
479
 
            case 'Z':                   // ^Z must be escaped on Win32
480
 
              *to++='\032';
481
 
              break;
482
 
            case '_':
483
 
            case '%':
484
 
              *to++= '\\';              // remember prefix for wildcard
485
 
              /* Fall through */
486
 
            default:
 
444
          if (*str == '\\' && (str + 1) != end)
 
445
          {
 
446
            switch (*++str) {
 
447
            case 'n':
 
448
              *to++= '\n';
 
449
              break;
 
450
            case 't':
 
451
              *to++= '\t';
 
452
              break;
 
453
            case 'r':
 
454
              *to++= '\r';
 
455
              break;
 
456
            case 'b':
 
457
              *to++= '\b';
 
458
              break;
 
459
            case '0':
 
460
              *to++= 0;                 // Ascii null
 
461
              break;
 
462
            case 'Z':                   // ^Z must be escaped on Win32
 
463
              *to++= '\032';
 
464
              break;
 
465
            case '_':
 
466
            case '%':
 
467
              *to++= '\\';              // remember prefix for wildcard
 
468
              /* Fall through */
 
469
            default:
487
470
              *to++= *str;
488
 
              break;
489
 
            }
490
 
          }
491
 
          else if (*str == sep)
492
 
            *to++= *str++;              // Two ' or "
493
 
          else
494
 
            *to++ = *str;
495
 
        }
496
 
        *to=0;
497
 
        lip->yytoklen=(uint32_t) (to-start);
 
471
              break;
 
472
            }
 
473
          }
 
474
          else if (*str == sep)
 
475
            *to++= *str++;              // Two ' or "
 
476
          else
 
477
            *to++ = *str;
 
478
        }
 
479
        *to= 0;
 
480
        lip->yytoklen= (uint32_t) (to - start);
498
481
      }
499
482
      return start;
500
483
    }
511
494
** is done with int64_t or double.
512
495
*/
513
496
 
514
 
static const char *long_str="2147483647";
515
 
static const uint32_t long_len=10;
516
 
static const char *signed_long_str="-2147483648";
517
 
static const char *int64_t_str="9223372036854775807";
518
 
static const uint32_t int64_t_len=19;
519
 
static const char *signed_int64_t_str="-9223372036854775808";
520
 
static const uint32_t signed_int64_t_len=19;
521
 
static const char *unsigned_int64_t_str="18446744073709551615";
522
 
static const uint32_t unsigned_int64_t_len=20;
 
497
static const char *long_str= "2147483647";
 
498
static const uint32_t long_len= 10;
 
499
static const char *signed_long_str= "-2147483648";
 
500
static const char *int64_t_str= "9223372036854775807";
 
501
static const uint32_t int64_t_len= 19;
 
502
static const char *signed_int64_t_str= "-9223372036854775808";
 
503
static const uint32_t signed_int64_t_len= 19;
 
504
static const char *unsigned_int64_t_str= "18446744073709551615";
 
505
static const uint32_t unsigned_int64_t_len= 20;
523
506
 
524
507
static inline uint32_t int_token(const char *str,uint32_t length)
525
508
{
593
576
  return ((unsigned char) str[-1] <= (unsigned char) cmp[-1]) ? smaller : bigger;
594
577
}
595
578
 
596
 
 
597
579
/*
598
580
  DRIZZLElex remember the following states from the following DRIZZLElex()
599
581
 
601
583
  - MY_LEX_OPERATOR_OR_IDENT    Last state was an ident, text or number
602
584
                                (which can't be followed by a signed number)
603
585
*/
604
 
 
605
586
int DRIZZLElex(void *arg, void *yysession)
606
587
{
607
588
  Session *session= (Session *)yysession;
683
664
      // Skip starting whitespace
684
665
      while(state_map[c= lip->yyPeek()] == MY_LEX_SKIP)
685
666
      {
686
 
        if (c == '\n')
687
 
          lip->yylineno++;
 
667
        if (c == '\n')
 
668
          lip->yylineno++;
688
669
 
689
670
        lip->yySkip();
690
671
      }
697
678
    case MY_LEX_ESCAPE:
698
679
      if (lip->yyGet() == 'N')
699
680
      {                                 // Allow \N as shortcut for NULL
700
 
        yylval->lex_str.str=(char*) "\\N";
701
 
        yylval->lex_str.length=2;
702
 
        return NULL_SYM;
 
681
        yylval->lex_str.str=(char*) "\\N";
 
682
        yylval->lex_str.length=2;
 
683
        return NULL_SYM;
703
684
      }
704
685
    case MY_LEX_CHAR:                   // Unknown or single char token
705
686
    case MY_LEX_SKIP:                   // This should not happen
712
693
      }
713
694
 
714
695
      if (c != ')')
715
 
        lip->next_state= MY_LEX_START;  // Allow signed numbers
 
696
        lip->next_state= MY_LEX_START;  // Allow signed numbers
716
697
 
717
698
      if (c == ',')
718
699
      {
733
714
    case MY_LEX_IDENT_OR_HEX:
734
715
      if (lip->yyPeek() == '\'')
735
716
      {                                 // Found x'hex-number'
736
 
        state= MY_LEX_HEX_NUMBER;
737
 
        break;
 
717
        state= MY_LEX_HEX_NUMBER;
 
718
        break;
738
719
      }
739
720
    case MY_LEX_IDENT_OR_BIN:
740
721
      if (lip->yyPeek() == '\'')
747
728
#if defined(USE_MB) && defined(USE_MB_IDENT)
748
729
      if (use_mb(cs))
749
730
      {
750
 
        result_state= IDENT_QUOTED;
 
731
        result_state= IDENT_QUOTED;
751
732
        if (my_mbcharlen(cs, lip->yyGetLast()) > 1)
752
733
        {
753
734
          int l = my_ismbchar(cs,
763
744
        {
764
745
          if (my_mbcharlen(cs, c) > 1)
765
746
          {
766
 
            int l;
767
 
            if ((l = my_ismbchar(cs,
768
 
                                 lip->get_ptr() -1,
769
 
                                 lip->get_end_of_query())) == 0)
 
747
            int l= my_ismbchar(cs, lip->get_ptr() -1, lip->get_end_of_query());
 
748
            if (l == 0)
770
749
              break;
771
750
            lip->skip_binary(l-1);
772
751
          }
790
769
        for (; state_map[c] == MY_LEX_SKIP ; c= lip->yyGet()) {};
791
770
      }
792
771
      if (start == lip->get_ptr() && c == '.' && ident_map[(uint8_t)lip->yyPeek()])
793
 
        lip->next_state=MY_LEX_IDENT_SEP;
 
772
              lip->next_state=MY_LEX_IDENT_SEP;
794
773
      else
795
774
      {                                 // '(' must follow directly if function
796
775
        lip->yyUnget();
797
 
        if ((tokval = find_keyword(lip, length, c == '(')))
798
 
        {
799
 
          lip->next_state= MY_LEX_START;        // Allow signed numbers
800
 
          return(tokval);               // Was keyword
801
 
        }
 
776
        if ((tokval = find_keyword(lip, length, c == '(')))
 
777
        {
 
778
          lip->next_state= MY_LEX_START;        // Allow signed numbers
 
779
          return(tokval);               // Was keyword
 
780
        }
802
781
        lip->yySkip();                  // next state does a unget
803
782
      }
804
783
      yylval->lex_str=get_token(lip, 0, length);
816
795
      c= lip->yyGet();                  // should be '.'
817
796
      lip->next_state= MY_LEX_IDENT_START;// Next is an ident (not a keyword)
818
797
      if (!ident_map[(uint8_t)lip->yyPeek()])            // Probably ` or "
819
 
        lip->next_state= MY_LEX_START;
 
798
        lip->next_state= MY_LEX_START;
820
799
      return((int) c);
821
800
 
822
801
    case MY_LEX_NUMBER_IDENT:           // number or ident which num-start
855
834
      while (my_isdigit(cs, (c = lip->yyGet()))) ;
856
835
      if (!ident_map[c])
857
836
      {                                 // Can't be identifier
858
 
        state=MY_LEX_INT_OR_REAL;
859
 
        break;
 
837
        state=MY_LEX_INT_OR_REAL;
 
838
        break;
860
839
      }
861
840
      if (c == 'e' || c == 'E')
862
841
      {
863
 
        // The following test is written this way to allow numbers of type 1e1
 
842
        // The following test is written this way to allow numbers of type 1e1
864
843
        if (my_isdigit(cs,lip->yyPeek()) ||
865
844
            (c=(lip->yyGet())) == '+' || c == '-')
866
 
        {                               // Allow 1E+10
 
845
        {                               // Allow 1E+10
867
846
          if (my_isdigit(cs,lip->yyPeek()))     // Number must have digit after sign
868
 
          {
 
847
          {
869
848
            lip->yySkip();
870
849
            while (my_isdigit(cs,lip->yyGet())) ;
871
850
            yylval->lex_str=get_token(lip, 0, lip->yyLength());
872
 
            return(FLOAT_NUM);
873
 
          }
874
 
        }
 
851
            return(FLOAT_NUM);
 
852
          }
 
853
        }
875
854
        lip->yyUnget();
876
855
      }
877
856
      // fall through
880
859
#if defined(USE_MB) && defined(USE_MB_IDENT)
881
860
      if (use_mb(cs))
882
861
      {
883
 
        result_state= IDENT_QUOTED;
 
862
        result_state= IDENT_QUOTED;
884
863
        while (ident_map[c=lip->yyGet()])
885
864
        {
886
865
          if (my_mbcharlen(cs, c) > 1)
887
866
          {
888
 
            int l;
889
 
            if ((l = my_ismbchar(cs,
890
 
                                 lip->get_ptr() -1,
891
 
                                 lip->get_end_of_query())) == 0)
 
867
            int l= my_ismbchar(cs, lip->get_ptr() -1, lip->get_end_of_query());
 
868
            if (l == 0)
892
869
              break;
893
870
            lip->skip_binary(l-1);
894
871
          }
902
879
        result_state= result_state & 0x80 ? IDENT_QUOTED : IDENT;
903
880
      }
904
881
      if (c == '.' && ident_map[(uint8_t)lip->yyPeek()])
905
 
        lip->next_state=MY_LEX_IDENT_SEP;// Next is '.'
 
882
        lip->next_state=MY_LEX_IDENT_SEP;// Next is '.'
906
883
 
907
884
      yylval->lex_str= get_token(lip, 0, lip->yyLength());
908
885
 
919
896
      char quote_char= c;                       // Used char
920
897
      while ((c=lip->yyGet()))
921
898
      {
922
 
        int var_length;
923
 
        if ((var_length= my_mbcharlen(cs, c)) == 1)
924
 
        {
925
 
          if (c == quote_char)
926
 
          {
927
 
            if (lip->yyPeek() != quote_char)
928
 
              break;
929
 
            c=lip->yyGet();
930
 
            double_quotes++;
931
 
            continue;
932
 
          }
933
 
        }
 
899
        int var_length;
 
900
        if ((var_length= my_mbcharlen(cs, c)) == 1)
 
901
        {
 
902
          if (c == quote_char)
 
903
          {
 
904
                  if (lip->yyPeek() != quote_char)
 
905
              break;
 
906
                  c=lip->yyGet();
 
907
            double_quotes++;
 
908
            continue;
 
909
          }
 
910
        }
934
911
#ifdef USE_MB
935
 
        else if (var_length < 1)
936
 
          break;                                // Error
 
912
        else if (var_length < 1)
 
913
          break;                                // Error
937
914
        lip->skip_binary(var_length-1);
938
915
#endif
939
916
      }
940
917
      if (double_quotes)
941
 
        yylval->lex_str=get_quoted_token(lip, 1,
942
 
                                         lip->yyLength() - double_quotes -1,
943
 
                                         quote_char);
 
918
              yylval->lex_str=get_quoted_token(lip, 1, lip->yyLength() - double_quotes -1, quote_char);
944
919
      else
945
920
        yylval->lex_str=get_token(lip, 1, lip->yyLength() -1);
946
921
      if (c == quote_char)
947
922
        lip->yySkip();                  // Skip end `
948
923
      lip->next_state= MY_LEX_START;
949
 
 
950
924
      lip->body_utf8_append(lip->m_cpp_text_start);
951
 
 
952
 
      lip->body_utf8_append_literal(session, &yylval->lex_str, cs,
953
 
                                    lip->m_cpp_text_end);
954
 
 
 
925
      lip->body_utf8_append_literal(session, &yylval->lex_str, cs, lip->m_cpp_text_end);
955
926
      return(IDENT_QUOTED);
956
927
    }
957
928
    case MY_LEX_INT_OR_REAL:            // Complete int or incomplete real
958
929
      if (c != '.')
959
930
      {                                 // Found complete integer number.
960
931
        yylval->lex_str=get_token(lip, 0, lip->yyLength());
961
 
        return int_token(yylval->lex_str.str,yylval->lex_str.length);
 
932
        return int_token(yylval->lex_str.str,yylval->lex_str.length);
962
933
      }
963
934
      // fall through
964
935
    case MY_LEX_REAL:                   // Incomplete real number
967
938
      if (c == 'e' || c == 'E')
968
939
      {
969
940
        c = lip->yyGet();
970
 
        if (c == '-' || c == '+')
971
 
          c = lip->yyGet();                     // Skip sign
972
 
        if (!my_isdigit(cs,c))
973
 
        {                               // No digit after sign
974
 
          state= MY_LEX_CHAR;
975
 
          break;
976
 
        }
 
941
        if (c == '-' || c == '+')
 
942
                c = lip->yyGet();                     // Skip sign
 
943
        if (!my_isdigit(cs,c))
 
944
        {                               // No digit after sign
 
945
          state= MY_LEX_CHAR;
 
946
          break;
 
947
        }
977
948
        while (my_isdigit(cs,lip->yyGet())) ;
978
949
        yylval->lex_str=get_token(lip, 0, lip->yyLength());
979
 
        return(FLOAT_NUM);
 
950
        return(FLOAT_NUM);
980
951
      }
981
952
      yylval->lex_str=get_token(lip, 0, lip->yyLength());
982
953
      return(DECIMAL_NUM);
1013
984
        lip->yySkip();
1014
985
      if ((tokval = find_keyword(lip, lip->yyLength() + 1, 0)))
1015
986
      {
1016
 
        lip->next_state= MY_LEX_START;  // Allow signed numbers
1017
 
        return(tokval);
 
987
        lip->next_state= MY_LEX_START;  // Allow signed numbers
 
988
        return(tokval);
1018
989
      }
1019
990
      state = MY_LEX_CHAR;              // Something fishy found
1020
991
      break;
1029
1000
      }
1030
1001
      if ((tokval = find_keyword(lip, lip->yyLength() + 1, 0)))
1031
1002
      {
1032
 
        lip->next_state= MY_LEX_START;  // Found long op
1033
 
        return(tokval);
 
1003
        lip->next_state= MY_LEX_START;  // Found long op
 
1004
        return(tokval);
1034
1005
      }
1035
1006
      state = MY_LEX_CHAR;              // Something fishy found
1036
1007
      break;
1038
1009
    case MY_LEX_BOOL:
1039
1010
      if (c != lip->yyPeek())
1040
1011
      {
1041
 
        state=MY_LEX_CHAR;
1042
 
        break;
 
1012
        state=MY_LEX_CHAR;
 
1013
        break;
1043
1014
      }
1044
1015
      lip->yySkip();
1045
1016
      tokval = find_keyword(lip,2,0);   // Is a bool operator
1056
1027
    case MY_LEX_STRING:                 // Incomplete text string
1057
1028
      if (!(yylval->lex_str.str = get_text(lip, 1, 1)))
1058
1029
      {
1059
 
        state= MY_LEX_CHAR;             // Read char by char
1060
 
        break;
 
1030
        state= MY_LEX_CHAR;             // Read char by char
 
1031
        break;
1061
1032
      }
1062
1033
      yylval->lex_str.length=lip->yytoklen;
1063
1034
 
1081
1052
    case MY_LEX_LONG_COMMENT:           /* Long C comment? */
1082
1053
      if (lip->yyPeek() != '*')
1083
1054
      {
1084
 
        state=MY_LEX_CHAR;              // Probable division
1085
 
        break;
 
1055
        state=MY_LEX_CHAR;              // Probable division
 
1056
        break;
1086
1057
      }
1087
1058
      lex->select_lex.options|= OPTION_FOUND_COMMENT;
1088
1059
      /* Reject '/' '*', since we might need to turn off the echo */
1189
1160
        state=MY_LEX_START;
1190
1161
      }
1191
1162
      else
1192
 
        state=MY_LEX_CHAR;              // Return '*'
 
1163
        state=MY_LEX_CHAR;              // Return '*'
1193
1164
      break;
1194
1165
    case MY_LEX_SET_VAR:                // Check if ':='
1195
1166
      if (lip->yyPeek() != '=')
1196
1167
      {
1197
 
        state=MY_LEX_CHAR;              // Return ':'
1198
 
        break;
 
1168
        state=MY_LEX_CHAR;              // Return ':'
 
1169
        break;
1199
1170
      }
1200
1171
      lip->yySkip();
1201
1172
      return (SET_VAR);
1211
1182
          return (END_OF_INPUT);
1212
1183
        }
1213
1184
        state= MY_LEX_CHAR;             // Return ';'
1214
 
        break;
 
1185
        break;
1215
1186
      }
1216
1187
      lip->next_state=MY_LEX_END;       // Mark for next loop
1217
1188
      return(END_OF_INPUT);
1237
1208
      /* Actually real shouldn't start with . but allow them anyhow */
1238
1209
    case MY_LEX_REAL_OR_POINT:
1239
1210
      if (my_isdigit(cs,lip->yyPeek()))
1240
 
        state = MY_LEX_REAL;            // Real
 
1211
        state= MY_LEX_REAL;             // Real
1241
1212
      else
1242
1213
      {
1243
 
        state= MY_LEX_IDENT_SEP;        // return '.'
 
1214
        state= MY_LEX_IDENT_SEP;        // return '.'
1244
1215
        lip->yyUnget();                 // Put back '.'
1245
1216
      }
1246
1217
      break;
1249
1220
      case MY_LEX_STRING:
1250
1221
      case MY_LEX_USER_VARIABLE_DELIMITER:
1251
1222
      case MY_LEX_STRING_OR_DELIMITER:
1252
 
        break;
 
1223
        break;
1253
1224
      case MY_LEX_USER_END:
1254
 
        lip->next_state=MY_LEX_SYSTEM_VAR;
1255
 
        break;
 
1225
        lip->next_state=MY_LEX_SYSTEM_VAR;
 
1226
        break;
1256
1227
      default:
1257
 
        lip->next_state=MY_LEX_HOSTNAME;
1258
 
        break;
 
1228
        lip->next_state=MY_LEX_HOSTNAME;
 
1229
        break;
1259
1230
      }
1260
1231
      yylval->lex_str.str=(char*) lip->get_ptr();
1261
1232
      yylval->lex_str.length=1;
1262
1233
      return((int) '@');
1263
1234
    case MY_LEX_HOSTNAME:               // end '@' of user@hostname
1264
1235
      for (c=lip->yyGet() ;
1265
 
           my_isalnum(cs,c) || c == '.' || c == '_' ||  c == '$';
 
1236
           my_isalnum(cs,c) || c == '.' || c == '_' ||  c == '$';
1266
1237
           c= lip->yyGet()) ;
1267
1238
      yylval->lex_str=get_token(lip, 0, lip->yyLength());
1268
1239
      return(LEX_HOSTNAME);
1277
1248
      return((int) '@');
1278
1249
    case MY_LEX_IDENT_OR_KEYWORD:
1279
1250
      /*
1280
 
        We come here when we have found two '@' in a row.
1281
 
        We should now be able to handle:
1282
 
        [(global | local | session) .]variable_name
 
1251
        We come here when we have found two '@' in a row.
 
1252
        We should now be able to handle:
 
1253
        [(global | local | session) .]variable_name
1283
1254
      */
1284
1255
 
1285
1256
      for (result_state= 0; ident_map[c= lip->yyGet()]; result_state|= c) {};
1287
1258
      result_state= result_state & 0x80 ? IDENT_QUOTED : IDENT;
1288
1259
 
1289
1260
      if (c == '.')
1290
 
        lip->next_state=MY_LEX_IDENT_SEP;
 
1261
        lip->next_state=MY_LEX_IDENT_SEP;
1291
1262
      length= lip->yyLength();
1292
1263
      if (length == 0)
1293
1264
        return(ABORT_SYM);              // Names must be nonempty.
1294
1265
      if ((tokval= find_keyword(lip, length,0)))
1295
1266
      {
1296
1267
        lip->yyUnget();                         // Put back 'c'
1297
 
        return(tokval);                         // Was keyword
 
1268
        return(tokval);                         // Was keyword
1298
1269
      }
1299
1270
      yylval->lex_str=get_token(lip, 0, length);
1300
1271
 
1308
1279
  }
1309
1280
}
1310
1281
 
1311
 
 
1312
1282
/**
1313
1283
  Construct a copy of this object to be used for mysql_alter_table
1314
1284
  and mysql_create_table.
1321
1291
  @return You need to use check the error in Session for out
1322
1292
  of memory condition after calling this function.
1323
1293
*/
1324
 
 
1325
1294
Alter_info::Alter_info(const Alter_info &rhs, MEM_ROOT *mem_root)
1326
1295
  :drop_list(rhs.drop_list, mem_root),
1327
1296
  alter_list(rhs.alter_list, mem_root),
1350
1319
  list_copy_and_replace_each_value(create_list, mem_root);
1351
1320
}
1352
1321
 
1353
 
 
1354
1322
void trim_whitespace(const CHARSET_INFO * const cs, LEX_STRING *str)
1355
1323
{
1356
1324
  /*
1358
1326
    This code assumes that there are no multi-bytes characters
1359
1327
    that can be considered white-space.
1360
1328
  */
1361
 
 
1362
1329
  while ((str->length > 0) && (my_isspace(cs, str->str[0])))
1363
1330
  {
1364
 
    str->length --;
1365
 
    str->str ++;
 
1331
    str->length--;
 
1332
    str->str++;
1366
1333
  }
1367
1334
 
1368
1335
  /*
1371
1338
  */
1372
1339
  while ((str->length > 0) && (my_isspace(cs, str->str[str->length-1])))
1373
1340
  {
1374
 
    str->length --;
 
1341
    str->length--;
1375
1342
  }
1376
1343
}
1377
1344
 
1378
 
 
1379
1345
/*
1380
1346
  Select_Lex structures initialisations
1381
1347
*/
1382
 
 
1383
1348
void Select_Lex_Node::init_query()
1384
1349
{
1385
1350
  options= 0;
1450
1415
 
1451
1416
void Select_Lex::init_select()
1452
1417
{
1453
 
  Select_Lex_Node::init_select();
1454
1418
  sj_nests.empty();
1455
1419
  group_list.empty();
1456
1420
  type= db= 0;
1612
1576
  }
1613
1577
}
1614
1578
 
1615
 
 
1616
1579
/*
1617
1580
  Exclude subtree of current unit from tree of SELECTs
1618
 
 
1619
 
  SYNOPSYS
1620
 
    Select_Lex_Unit::exclude_tree()
1621
1581
*/
1622
1582
void Select_Lex_Unit::exclude_tree()
1623
1583
{
1639
1599
    next->prev= prev;
1640
1600
}
1641
1601
 
1642
 
 
1643
 
/*
1644
 
  Select_Lex_Node::mark_as_dependent mark all Select_Lex struct from
1645
 
  this to 'last' as dependent
1646
 
 
1647
 
  SYNOPSIS
1648
 
    last - pointer to last Select_Lex struct, before wich all
1649
 
           Select_Lex have to be marked as dependent
1650
 
 
1651
 
  NOTE
1652
 
    'last' should be reachable from this Select_Lex_Node
1653
 
*/
1654
 
 
 
1602
/**
 
1603
 * Mark all Select_Lex struct from this to 'last' as dependent
 
1604
 *
 
1605
 * @param Pointer to last Select_Lex struct, before wich all
 
1606
 *        Select_Lex have to be marked as dependent
 
1607
 * @note 'last' should be reachable from this Select_Lex_Node
 
1608
 */
1655
1609
void Select_Lex::mark_as_dependent(Select_Lex *last)
1656
1610
{
1657
1611
  /*
1724
1678
  return false;
1725
1679
}
1726
1680
 
1727
 
 
1728
1681
Select_Lex_Unit* Select_Lex_Unit::master_unit()
1729
1682
{
1730
 
    return this;
 
1683
  return this;
1731
1684
}
1732
1685
 
1733
 
 
1734
1686
Select_Lex* Select_Lex_Unit::outer_select()
1735
1687
{
1736
1688
  return (Select_Lex*) master;
1737
1689
}
1738
1690
 
1739
 
 
1740
1691
bool Select_Lex::add_order_to_list(Session *session, Item *item, bool asc)
1741
1692
{
1742
1693
  return add_to_list(session, order_list, item, asc);
1743
1694
}
1744
1695
 
1745
 
 
1746
1696
bool Select_Lex::add_item_to_list(Session *, Item *item)
1747
1697
{
1748
1698
  return(item_list.push_back(item));
1749
1699
}
1750
1700
 
1751
 
 
1752
1701
bool Select_Lex::add_group_to_list(Session *session, Item *item, bool asc)
1753
1702
{
1754
1703
  return add_to_list(session, group_list, item, asc);
1755
1704
}
1756
1705
 
1757
 
 
1758
1706
Select_Lex_Unit* Select_Lex::master_unit()
1759
1707
{
1760
1708
  return (Select_Lex_Unit*) master;
1761
1709
}
1762
1710
 
1763
 
 
1764
1711
Select_Lex* Select_Lex::outer_select()
1765
1712
{
1766
1713
  return (Select_Lex*) master->get_master();
1767
1714
}
1768
1715
 
1769
 
 
1770
1716
bool Select_Lex::set_braces(bool value)
1771
1717
{
1772
1718
  braces= value;
1773
 
 
1774
1719
  return false;
1775
1720
}
1776
1721
 
1777
 
 
1778
1722
bool Select_Lex::inc_in_sum_expr()
1779
1723
{
1780
1724
  in_sum_expr++;
1781
 
 
1782
1725
  return false;
1783
1726
}
1784
1727
 
1785
 
 
1786
1728
uint32_t Select_Lex::get_in_sum_expr()
1787
1729
{
1788
1730
  return in_sum_expr;
1789
1731
}
1790
1732
 
1791
 
 
1792
1733
TableList* Select_Lex::get_table_list()
1793
1734
{
1794
1735
  return (TableList*) table_list.first;
1804
1745
  return table_join_options;
1805
1746
}
1806
1747
 
1807
 
 
1808
1748
bool Select_Lex::setup_ref_array(Session *session, uint32_t order_group_num)
1809
1749
{
1810
1750
  if (ref_pointer_array)
1818
1758
                                                 order_group_num)*5)) == 0;
1819
1759
}
1820
1760
 
1821
 
 
1822
1761
void Select_Lex_Unit::print(String *str, enum_query_type query_type)
1823
1762
{
1824
1763
  bool union_all= !union_distinct;
1852
1791
  }
1853
1792
}
1854
1793
 
1855
 
 
1856
1794
void Select_Lex::print_order(String *str,
1857
1795
                                order_st *order,
1858
1796
                                enum_query_type query_type)
1874
1812
  }
1875
1813
}
1876
1814
 
1877
 
 
1878
1815
void Select_Lex::print_limit(Session *, String *str,
1879
1816
                                enum_query_type query_type)
1880
1817
{
1925
1862
  rule in the grammar file itself, this function should be used
1926
1863
  to implement the clean up.
1927
1864
*/
1928
 
 
1929
1865
void LEX::cleanup_lex_after_parse_error(Session *)
1930
1866
{
1931
1867
}
1947
1883
    this method to reset state of already initialized Query_tables_list
1948
1884
    so it can be used for processing of new statement.
1949
1885
*/
1950
 
 
1951
1886
void Query_tables_list::reset_query_tables_list(bool init)
1952
1887
{
1953
1888
  if (!init && query_tables)
1965
1900
  query_tables_own_last= 0;
1966
1901
}
1967
1902
 
1968
 
 
1969
1903
/*
1970
1904
  Initialize LEX object.
1971
1905
 
1979
1913
    statement parsing. On should use lex_start() function to prepare LEX
1980
1914
    for this.
1981
1915
*/
1982
 
 
1983
1916
LEX::LEX()
1984
1917
  :result(0), yacc_yyss(0), yacc_yyvs(0),
1985
1918
   sql_command(SQLCOM_END), option_type(OPT_DEFAULT), is_lex_started(0)
1997
1930
    true yes, we need only structure
1998
1931
    false no, we need data
1999
1932
*/
2000
 
 
2001
1933
bool LEX::only_view_structure()
2002
1934
{
2003
1935
  switch (sql_command) {
2010
1942
  }
2011
1943
}
2012
1944
 
2013
 
 
2014
1945
/*
2015
1946
  Should Items_ident be printed correctly
2016
1947
 
2021
1952
    true yes, we need only structure
2022
1953
    false no, we need data
2023
1954
*/
2024
 
 
2025
 
 
2026
1955
bool LEX::need_correct_ident()
2027
1956
{
2028
1957
  switch(sql_command)
2035
1964
  }
2036
1965
}
2037
1966
 
2038
 
 
2039
1967
/**
2040
1968
  This method should be called only during parsing.
2041
1969
  It is aware of compound statements (stored routine bodies)
2054
1982
  @return true in case of error (parsing should be aborted, false in
2055
1983
  case of success
2056
1984
*/
2057
 
 
2058
 
bool
2059
 
LEX::copy_db_to(char **p_db, size_t *p_db_length) const
 
1985
bool LEX::copy_db_to(char **p_db, size_t *p_db_length) const
2060
1986
{
2061
1987
  return session->copy_db_to(p_db, p_db_length);
2062
1988
}
2068
1994
    Select_Lex_Unit::set_limit()
2069
1995
    values      - Select_Lex with initial values for counters
2070
1996
*/
2071
 
 
2072
1997
void Select_Lex_Unit::set_limit(Select_Lex *sl)
2073
1998
{
2074
1999
  ha_rows select_limit_val;
2089
2014
    select_limit_cnt= HA_POS_ERROR;             // no limit
2090
2015
}
2091
2016
 
2092
 
 
2093
2017
/*
2094
2018
  Unlink the first table from the global table list and the first table from
2095
2019
  outer select (lex->select_lex) local list
2142
2066
  return first;
2143
2067
}
2144
2068
 
2145
 
 
2146
2069
/*
2147
2070
  Bring first local table of first most outer select to first place in global
2148
2071
  table list
2158
2081
    the select list, as only in this case tables of sub-queries will go to
2159
2082
    the global list first.
2160
2083
*/
2161
 
 
2162
2084
void LEX::first_lists_tables_same()
2163
2085
{
2164
2086
  TableList *first_table= (TableList*) select_lex.table_list.first;
2183
2105
  }
2184
2106
}
2185
2107
 
2186
 
 
2187
2108
/*
2188
2109
  Link table back that was unlinked with unlink_first_table()
2189
2110
 
2194
2115
  RETURN
2195
2116
    global list
2196
2117
*/
2197
 
 
2198
 
void LEX::link_first_table_back(TableList *first,
2199
 
                                   bool link_to_local)
 
2118
void LEX::link_first_table_back(TableList *first, bool link_to_local)
2200
2119
{
2201
2120
  if (first)
2202
2121
  {
2216
2135
  }
2217
2136
}
2218
2137
 
2219
 
 
2220
 
 
2221
2138
/*
2222
2139
  cleanup lex for case when we open table by table for processing
2223
2140
 
2229
2146
    derived tables state. To rollback changes in Query_tables_list one has
2230
2147
    to call Query_tables_list::reset_query_tables_list(false).
2231
2148
*/
2232
 
 
2233
2149
void LEX::cleanup_after_one_table_open()
2234
2150
{
2235
2151
  /*
2255
2171
  }
2256
2172
}
2257
2173
 
2258
 
 
2259
2174
/*
2260
2175
  There are Select_Lex::add_table_to_list &
2261
2176
  Select_Lex::set_lock_for_tables are in sql_parse.cc
2283
2198
    Then the context variable index_hint_type can be reset to the
2284
2199
    next hint type.
2285
2200
*/
2286
 
void Select_Lex::set_index_hint_type(enum index_hint_type type_arg,
2287
 
                                        index_clause_map clause)
 
2201
void Select_Lex::set_index_hint_type(enum index_hint_type type_arg, index_clause_map clause)
2288
2202
{
2289
2203
  current_index_hint_type= type_arg;
2290
2204
  current_index_hint_clause= clause;
2291
2205
}
2292
2206
 
2293
 
 
2294
2207
/*
2295
2208
  Makes an array to store index usage hints (ADD/FORCE/IGNORE INDEX).
2296
2209
 
2298
2211
    alloc_index_hints()
2299
2212
      session         current thread.
2300
2213
*/
2301
 
 
2302
2214
void Select_Lex::alloc_index_hints (Session *session)
2303
2215
{
2304
2216
  index_hints= new (session->mem_root) List<Index_hint>();
2305
2217
}
2306
2218
 
2307
 
 
2308
 
 
2309
2219
/*
2310
2220
  adds an element to the array storing index usage hints
2311
2221
  (ADD/FORCE/IGNORE INDEX).