33
33
#include <drizzled/item/subselect.h>
34
34
#include <drizzled/statement.h>
35
35
#include <drizzled/sql_lex.h>
36
#include <drizzled/plugin.h>
37
#include <drizzled/lex_input_stream.h>
42
#include <drizzled/message/alter_table.pb.h>
42
46
using namespace std;
44
48
/* Stay outside of the namespace because otherwise bison goes nuts */
45
49
int base_sql_lex(ParserType *arg, drizzled::Session *yysession);
50
53
static int lex_one_token(ParserType *arg, drizzled::Session *yysession);
53
56
save order by and tables in own lists.
55
static bool add_to_list(Session *session, SQL_LIST &list, Item *item, bool asc)
58
static void add_to_list(Session *session, SQL_LIST &list, Item *item, bool asc)
59
if (!(order = (Order *) session->getMemRoot()->allocate(sizeof(Order))))
60
Order* order = new (session->mem) Order;
62
61
order->item_ptr= item;
63
62
order->item= &order->item_ptr;
67
66
order->counter_used= 0;
68
67
list.link_in_list((unsigned char*) order, (unsigned char**) &order->next);
74
LEX_STRING constant for null-string to be used in parser and other places.
76
const LEX_STRING null_lex_str= {NULL, 0};
78
70
Lex_input_stream::Lex_input_stream(Session *session,
79
71
const char* buffer,
80
72
unsigned int length) :
102
94
in_comment(NO_COMMENT)
104
m_cpp_buf= (char*) session->getMemRoot()->allocate(length + 1);
96
m_cpp_buf= (char*) session->mem.alloc(length + 1);
105
97
m_cpp_ptr= m_cpp_buf;
108
Lex_input_stream::~Lex_input_stream()
112
The operation is called from the parser in order to
113
1) designate the intention to have utf8 body;
114
1) Indicate to the lexer that we will need a utf8 representation of this
116
2) Determine the beginning of the body.
118
@param session Thread context.
119
@param begin_ptr Pointer to the start of the body in the pre-processed
122
void Lex_input_stream::body_utf8_start(Session *session, const char *begin_ptr)
125
assert(m_cpp_buf <= begin_ptr && begin_ptr <= m_cpp_buf + m_buf_length);
127
uint32_t body_utf8_length=
128
(m_buf_length / default_charset_info->mbminlen) *
129
my_charset_utf8_bin.mbmaxlen;
131
m_body_utf8= (char *) session->getMemRoot()->allocate(body_utf8_length + 1);
132
m_body_utf8_ptr= m_body_utf8;
135
m_cpp_utf8_processed_ptr= begin_ptr;
139
101
@brief The operation appends unprocessed part of pre-processed buffer till
140
102
the given pointer (ptr) and sets m_cpp_utf8_processed_ptr to end_ptr.
155
117
m_cpp_utf8_processed_ptr will be set in the end of the
158
void Lex_input_stream::body_utf8_append(const char *ptr,
120
void Lex_input_stream::body_utf8_append(const char *ptr, const char *end_ptr)
161
122
assert(m_cpp_buf <= ptr && ptr <= m_cpp_buf + m_buf_length);
162
123
assert(m_cpp_buf <= end_ptr && end_ptr <= m_cpp_buf + m_buf_length);
199
160
m_cpp_utf8_processed_ptr will be set in the end of the
202
void Lex_input_stream::body_utf8_append_literal(const LEX_STRING *txt,
163
void Lex_input_stream::body_utf8_append_literal(str_ref txt, const char *end_ptr)
205
165
if (!m_cpp_utf8_processed_ptr)
208
168
/* NOTE: utf_txt.length is in bytes, not in symbols. */
210
memcpy(m_body_utf8_ptr, txt->str, txt->length);
211
m_body_utf8_ptr += txt->length;
170
memcpy(m_body_utf8_ptr, txt.data(), txt.size());
171
m_body_utf8_ptr += txt.size();
212
172
*m_body_utf8_ptr= 0;
214
174
m_cpp_utf8_processed_ptr= end_ptr;
312
273
const char *tok= lip->get_tok_start();
313
274
uint32_t tok_pos= 0;
314
275
for (;tok_pos<len && tok_pos<63;tok_pos++)
315
tok_upper[tok_pos]=my_toupper(system_charset_info, tok[tok_pos]);
276
tok_upper[tok_pos]= system_charset_info->toupper(tok[tok_pos]);
316
277
tok_upper[tok_pos]=0;
318
279
const SYMBOL *symbol= lookup_symbol(tok_upper, len, function);
331
bool is_lex_native_function(const LEX_STRING *name)
333
assert(name != NULL);
334
return (lookup_symbol(name->str, name->length, 1) != 0);
337
292
/* make a copy of token before ptr and set yytoklen */
338
static LEX_STRING get_token(Lex_input_stream *lip, uint32_t skip, uint32_t length)
293
static lex_string_t get_token(Lex_input_stream *lip, uint32_t skip, uint32_t length)
341
295
lip->yyUnget(); // ptr points now after last token char
342
tmp.length=lip->yytoklen=length;
343
tmp.str= lip->m_session->strmake(lip->get_tok_start() + skip, tmp.length);
296
lip->yytoklen= length;
298
tmp.assign(lip->m_session->mem.strdup(lip->get_tok_start() + skip, length), length);
345
299
lip->m_cpp_text_start= lip->get_cpp_tok_start() + skip;
346
lip->m_cpp_text_end= lip->m_cpp_text_start + tmp.length;
300
lip->m_cpp_text_end= lip->m_cpp_text_start + tmp.size();
354
307
get_quoted_token yet. But it should be fixed in the
355
308
future to operate multichar strings (like ucs2)
357
static LEX_STRING get_quoted_token(Lex_input_stream *lip,
310
static lex_string_t get_quoted_token(Lex_input_stream *lip,
359
312
uint32_t length, char quote)
362
const char *from, *end;
364
314
lip->yyUnget(); // ptr points now after last token char
365
tmp.length= lip->yytoklen=length;
366
tmp.str=(char*) lip->m_session->getMemRoot()->allocate(tmp.length+1);
367
from= lip->get_tok_start() + skip;
315
lip->yytoklen= length;
317
tmp.assign((char*)lip->m_session->mem.alloc(length + 1), length);
318
const char* from= lip->get_tok_start() + skip;
319
char* to= (char*)tmp.data();
320
const char* end= to+length;
371
322
lip->m_cpp_text_start= lip->get_cpp_tok_start() + skip;
372
323
lip->m_cpp_text_end= lip->m_cpp_text_start + length;
391
342
static char *get_text(Lex_input_stream *lip, int pre_skip, int post_skip)
394
344
bool found_escape= false;
395
const CHARSET_INFO * const cs= lip->m_session->charset();
345
const charset_info_st* const cs= lip->m_session->charset();
397
347
lip->tok_bitmap= 0;
398
sep= lip->yyGetLast(); // String should end with this
348
unsigned char sep= lip->yyGetLast(); // String should end with this
349
while (not lip->eof())
351
unsigned char c= lip->yyGet();
402
352
lip->tok_bitmap|= c;
431
381
/* Found end. Unescape and return string */
432
const char *str, *end;
435
str= lip->get_tok_start();
382
const char* str= lip->get_tok_start();
383
const char* end= lip->get_ptr();
437
384
/* Extract the text from the token */
440
387
assert(end >= str);
442
if (!(start= (char*) lip->m_session->getMemRoot()->allocate((uint32_t) (end-str)+1)))
443
return (char*) ""; // memory::SqlAlloc has set error flag
389
char* start= (char*) lip->m_session->mem.alloc((uint32_t) (end-str)+1);
445
391
lip->m_cpp_text_start= lip->get_cpp_tok_start() + pre_skip;
446
392
lip->m_cpp_text_end= lip->get_cpp_ptr() - post_skip;
674
620
enum my_lex_states state;
675
621
Lex_input_stream *lip= session->m_lip;
676
622
LEX *lex= &session->lex();
677
const CHARSET_INFO * const cs= session->charset();
623
const charset_info_st * const cs= session->charset();
678
624
unsigned char *state_map= cs->state_map;
679
625
unsigned char *ident_map= cs->ident_map;
705
651
case MY_LEX_ESCAPE:
706
652
if (lip->yyGet() == 'N')
707
653
{ // Allow \N as shortcut for NULL
708
yylval->lex_str.str=(char*) "\\N";
709
yylval->lex_str.length=2;
654
yylval->lex_str.assign("\\N", 2);
712
657
case MY_LEX_CHAR: // Unknown or single char token
713
658
case MY_LEX_SKIP: // This should not happen
714
659
if (c == '-' && lip->yyPeek() == '-' &&
715
(my_isspace(cs,lip->yyPeekn(1)) ||
716
my_iscntrl(cs,lip->yyPeekn(1))))
660
(cs->isspace(lip->yyPeekn(1)) ||
661
cs->iscntrl(lip->yyPeekn(1))))
718
663
state=MY_LEX_COMMENT;
806
751
lip->yySkip(); // next state does a unget
808
yylval->lex_str=get_token(lip, 0, length);
753
yylval->lex_str= get_token(lip, 0, length);
810
755
lip->body_utf8_append(lip->m_cpp_text_start);
812
lip->body_utf8_append_literal(&yylval->lex_str, lip->m_cpp_text_end);
757
lip->body_utf8_append_literal(yylval->lex_str, lip->m_cpp_text_end);
814
759
return(result_state); // IDENT or IDENT_QUOTED
816
761
case MY_LEX_IDENT_SEP: // Found ident and now '.'
817
yylval->lex_str.str= (char*) lip->get_ptr();
818
yylval->lex_str.length= 1;
762
yylval->lex_str.assign(lip->get_ptr(), 1);
819
763
c= lip->yyGet(); // should be '.'
820
764
lip->next_state= MY_LEX_IDENT_START;// Next is an ident (not a keyword)
821
765
if (!ident_map[(uint8_t)lip->yyPeek()]) // Probably ` or "
831
while (my_isxdigit(cs,(c = lip->yyGet()))) ;
775
while (cs->isxdigit((c = lip->yyGet()))) ;
832
776
if ((lip->yyLength() >= 3) && !ident_map[c])
835
yylval->lex_str=get_token(lip, 2, lip->yyLength()-2);
779
yylval->lex_str= get_token(lip, 2, lip->yyLength()-2);
836
780
return (HEX_NUM);
864
808
if (c == 'e' || c == 'E')
866
810
// The following test is written this way to allow numbers of type 1e1
867
if (my_isdigit(cs,lip->yyPeek()) ||
811
if (cs->isdigit(lip->yyPeek()) ||
868
812
(c=(lip->yyGet())) == '+' || c == '-')
870
if (my_isdigit(cs,lip->yyPeek())) // Number must have digit after sign
814
if (cs->isdigit(lip->yyPeek())) // Number must have digit after sign
873
while (my_isdigit(cs,lip->yyGet())) ;
874
yylval->lex_str=get_token(lip, 0, lip->yyLength());
817
while (cs->isdigit(lip->yyGet())) ;
818
yylval->lex_str= get_token(lip, 0, lip->yyLength());
875
819
return(FLOAT_NUM);
906
850
yylval->lex_str= get_token(lip, 0, lip->yyLength());
908
852
lip->body_utf8_append(lip->m_cpp_text_start);
910
lip->body_utf8_append_literal(&yylval->lex_str, lip->m_cpp_text_end);
853
lip->body_utf8_append_literal(yylval->lex_str, lip->m_cpp_text_end);
912
855
return(result_state);
934
877
lip->skip_binary(var_length-1);
937
yylval->lex_str=get_quoted_token(lip, 1, lip->yyLength() - double_quotes -1, quote_char);
939
yylval->lex_str=get_token(lip, 1, lip->yyLength() -1);
879
yylval->lex_str= double_quotes
880
? get_quoted_token(lip, 1, lip->yyLength() - double_quotes - 1, quote_char)
881
: get_token(lip, 1, lip->yyLength() - 1);
940
882
if (c == quote_char)
941
883
lip->yySkip(); // Skip end `
942
884
lip->next_state= MY_LEX_START;
943
885
lip->body_utf8_append(lip->m_cpp_text_start);
944
lip->body_utf8_append_literal(&yylval->lex_str, lip->m_cpp_text_end);
945
return(IDENT_QUOTED);
886
lip->body_utf8_append_literal(yylval->lex_str, lip->m_cpp_text_end);
947
889
case MY_LEX_INT_OR_REAL: // Complete int or incomplete real
949
891
{ // Found complete integer number.
950
892
yylval->lex_str=get_token(lip, 0, lip->yyLength());
951
return int_token(yylval->lex_str.str,yylval->lex_str.length);
893
return int_token(yylval->lex_str.data(), yylval->lex_str.size());
954
896
case MY_LEX_REAL: // Incomplete real number
955
while (my_isdigit(cs,c = lip->yyGet())) ;
897
while (cs->isdigit(c = lip->yyGet())) ;
957
899
if (c == 'e' || c == 'E')
959
901
c = lip->yyGet();
960
902
if (c == '-' || c == '+')
961
903
c = lip->yyGet(); // Skip sign
962
if (!my_isdigit(cs,c))
963
905
{ // No digit after sign
964
906
state= MY_LEX_CHAR;
967
while (my_isdigit(cs,lip->yyGet())) ;
909
while (cs->isdigit(lip->yyGet())) ;
968
910
yylval->lex_str=get_token(lip, 0, lip->yyLength());
969
911
return(FLOAT_NUM);
974
916
case MY_LEX_HEX_NUMBER: // Found x'hexstring'
975
917
lip->yySkip(); // Accept opening '
976
while (my_isxdigit(cs, (c= lip->yyGet()))) ;
918
while (cs->isxdigit((c= lip->yyGet()))) ;
978
920
return(ABORT_SYM); // Illegal hex constant
979
921
lip->yySkip(); // Accept closing '
980
922
length= lip->yyLength(); // Length of hexnum+3
981
if ((length % 2) == 0)
982
return(ABORT_SYM); // odd number of hex digits
924
return ABORT_SYM; // odd number of hex digits
983
925
yylval->lex_str=get_token(lip,
985
927
length-3); // don't count x' and last '
1045
987
/* " used for strings */
1046
988
case MY_LEX_STRING: // Incomplete text string
1047
if (!(yylval->lex_str.str = get_text(lip, 1, 1)))
989
if (!(yylval->lex_str.str_ = get_text(lip, 1, 1)))
1049
991
state= MY_LEX_CHAR; // Read char by char
1052
yylval->lex_str.length=lip->yytoklen;
994
yylval->lex_str.assign(yylval->lex_str.data(), lip->yytoklen);
1054
996
lip->body_utf8_append(lip->m_cpp_text_start);
1056
lip->body_utf8_append_literal(&yylval->lex_str, lip->m_cpp_text_end);
997
lip->body_utf8_append_literal(yylval->lex_str, lip->m_cpp_text_end);
1058
999
lex->text_string_is_7bit= (lip->tok_bitmap & 0x80) ? 0 : 1;
1059
1000
return(TEXT_STRING);
1221
1162
/* Actually real shouldn't start with . but allow them anyhow */
1223
1164
case MY_LEX_REAL_OR_POINT:
1224
if (my_isdigit(cs,lip->yyPeek()))
1165
if (cs->isdigit(lip->yyPeek()))
1225
1166
state= MY_LEX_REAL; // Real
1243
1184
lip->next_state=MY_LEX_HOSTNAME;
1246
yylval->lex_str.str=(char*) lip->get_ptr();
1247
yylval->lex_str.length=1;
1187
yylval->lex_str.assign(lip->get_ptr(), 1);
1250
1190
case MY_LEX_HOSTNAME: // end '@' of user@hostname
1251
1191
for (c=lip->yyGet() ;
1252
my_isalnum(cs,c) || c == '.' || c == '_' || c == '$';
1192
cs->isalnum(c) || c == '.' || c == '_' || c == '$';
1253
1193
c= lip->yyGet()) ;
1254
1194
yylval->lex_str=get_token(lip, 0, lip->yyLength());
1255
1195
return(LEX_HOSTNAME);
1257
1197
case MY_LEX_SYSTEM_VAR:
1258
yylval->lex_str.str=(char*) lip->get_ptr();
1259
yylval->lex_str.length=1;
1198
yylval->lex_str.assign(lip->get_ptr(), 1);
1260
1199
lip->yySkip(); // Skip '@'
1261
1200
lip->next_state= (state_map[(uint8_t)lip->yyPeek()] ==
1262
1201
MY_LEX_USER_VARIABLE_DELIMITER ?
1290
1229
yylval->lex_str=get_token(lip, 0, length);
1292
1231
lip->body_utf8_append(lip->m_cpp_text_start);
1294
lip->body_utf8_append_literal(&yylval->lex_str, lip->m_cpp_text_end);
1296
return(result_state);
1232
lip->body_utf8_append_literal(yylval->lex_str, lip->m_cpp_text_end);
1234
return result_state;
1301
void trim_whitespace(const CHARSET_INFO * const cs, LEX_STRING *str)
1305
This code assumes that there are no multi-bytes characters
1306
that can be considered white-space.
1308
while ((str->length > 0) && (my_isspace(cs, str->str[0])))
1316
Also, parsing backward is not safe with multi bytes characters
1318
while ((str->length > 0) && (my_isspace(cs, str->str[str->length-1])))
1325
1240
Select_Lex structures initialisations
1668
1583
return (Select_Lex*) master;
1671
bool Select_Lex::add_order_to_list(Session *session, Item *item, bool asc)
1673
return add_to_list(session, order_list, item, asc);
1676
bool Select_Lex::add_item_to_list(Session *, Item *item)
1678
return(item_list.push_back(item));
1681
bool Select_Lex::add_group_to_list(Session *session, Item *item, bool asc)
1683
return add_to_list(session, group_list, item, asc);
1586
void Select_Lex::add_order_to_list(Session *session, Item *item, bool asc)
1588
add_to_list(session, order_list, item, asc);
1591
void Select_Lex::add_item_to_list(Session *, Item *item)
1593
item_list.push_back(item);
1596
void Select_Lex::add_group_to_list(Session *session, Item *item, bool asc)
1598
add_to_list(session, group_list, item, asc);
1686
1601
Select_Lex_Unit* Select_Lex::master_unit()
1720
1635
return &item_list;
1724
bool Select_Lex::setup_ref_array(Session *session, uint32_t order_group_num)
1638
void Select_Lex::setup_ref_array(Session *session, uint32_t order_group_num)
1726
if (ref_pointer_array)
1729
return (ref_pointer_array=
1730
(Item **)session->getMemRoot()->allocate(sizeof(Item*) * (n_child_sum_items +
1732
select_n_having_items +
1733
select_n_where_fields +
1734
order_group_num)*5)) == 0;
1640
if (not ref_pointer_array)
1641
ref_pointer_array= new (session->mem) Item*[5 * (n_child_sum_items + item_list.size() + select_n_having_items + select_n_where_fields + order_group_num)];
1737
1644
void Select_Lex_Unit::print(String *str)
1890
1798
cacheable(true),
1891
1799
sum_expr_used(false),
1892
1800
_create_table(NULL),
1893
1802
_create_field(NULL),
1896
1805
reset_query_tables_list(true);
1900
This method should be called only during parsing.
1901
It is aware of compound statements (stored routine bodies)
1902
and will initialize the destination with the default
1903
database of the stored routine, rather than the default
1904
database of the connection it is parsed in.
1905
E.g. if one has no current database selected, or current database
1906
set to 'bar' and then issues:
1908
CREATE PROCEDURE foo.p1() BEGIN SELECT * FROM t1 END//
1910
t1 is meant to refer to foo.t1, not to bar.t1.
1912
This method is needed to support this rule.
1914
@return true in case of error (parsing should be aborted, false in
1917
bool LEX::copy_db_to(char **p_db, size_t *p_db_length) const
1919
return session->copy_db_to(p_db, p_db_length);
1923
1809
initialize limit counters
2130
2016
Then the context variable index_hint_type can be reset to the
2131
2017
next hint type.
2133
void Select_Lex::set_index_hint_type(enum index_hint_type type_arg, index_clause_map clause)
2019
void Select_Lex::set_index_hint_type(index_hint_type type_arg, index_clause_map clause)
2135
2021
current_index_hint_type= type_arg;
2136
2022
current_index_hint_clause= clause;
2162
2048
0 on success, non-zero otherwise
2164
bool Select_Lex::add_index_hint (Session *session, char *str, uint32_t length)
2166
return index_hints->push_front (new (session->mem_root)
2167
Index_hint(current_index_hint_type,
2168
current_index_hint_clause,
2172
bool check_for_sql_keyword(drizzled::lex_string_t const& string)
2174
if (sql_reserved_words::in_word_set(string.str, string.length))
2180
bool check_for_sql_keyword(drizzled::st_lex_symbol const& string)
2182
if (sql_reserved_words::in_word_set(string.str, string.length))
2050
void Select_Lex::add_index_hint(Session *session, const char *str)
2052
index_hints->push_front(new (session->mem_root) Index_hint(current_index_hint_type, current_index_hint_clause, str));
2055
message::AlterTable *LEX::alter_table()
2057
if (not _alter_table)
2058
_alter_table= new message::AlterTable;
2060
return _alter_table;
2189
2063
} /* namespace drizzled */