summaryrefslogtreecommitdiff
path: root/sql/sql_lex.cc
diff options
context:
space:
mode:
authorSergey Petrunya <psergey@askmonty.org>2009-09-08 00:50:10 +0400
committerSergey Petrunya <psergey@askmonty.org>2009-09-08 00:50:10 +0400
commit29f0dcb56337a3e352ad7a70dcff6b25bb605325 (patch)
tree84935c21dc958724ae7dcbeeca0c0f08986fc430 /sql/sql_lex.cc
parent915a624cbcb58a10a2cfb2e2e4fd5029191fa86a (diff)
parent8a2454f8e9fce648272577fcf8006ae6e6806cf9 (diff)
downloadmariadb-git-29f0dcb56337a3e352ad7a70dcff6b25bb605325.tar.gz
Merge MySQL->MariaDB
* Finished Monty and Jani's merge * Some InnoDB tests still fail (because it's old xtradb code run against newer testsuite). They are expected to go after mergning with the latest xtradb.
Diffstat (limited to 'sql/sql_lex.cc')
-rw-r--r--sql/sql_lex.cc113
1 files changed, 87 insertions, 26 deletions
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index da00ab7a239..54c06b1fb98 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -348,6 +348,7 @@ void lex_start(THD *thd)
lex->nest_level=0 ;
lex->allow_sum_func= 0;
lex->in_sum_func= NULL;
+ lex->protect_against_global_read_lock= FALSE;
/*
ok, there must be a better solution for this, long-term
I tried "bzero" in the sql_yacc.yy code, but that for
@@ -432,6 +433,16 @@ bool is_keyword(const char *name, uint len)
return get_hash_symbol(name,len,0)!=0;
}
+/**
+ Check if name is a sql function
+
+ @param name checked name
+
+ @return is this a native function or not
+ @retval 0 name is a function
+ @retval 1 name isn't a function
+*/
+
bool is_lex_native_function(const LEX_STRING *name)
{
DBUG_ASSERT(name != NULL);
@@ -712,6 +723,53 @@ static inline uint int_token(const char *str,uint length)
return ((uchar) str[-1] <= (uchar) cmp[-1]) ? smaller : bigger;
}
+
+/**
+ Given a stream that is advanced to the first contained character in
+ an open comment, consume the comment. Optionally, if we are allowed,
+ recurse so that we understand comments within this current comment.
+
+ At this level, we do not support version-condition comments. We might
+ have been called with having just passed one in the stream, though. In
+ that case, we probably want to tolerate mundane comments inside. Thus,
+ the case for recursion.
+
+ @retval Whether EOF reached before comment is closed.
+*/
+bool consume_comment(Lex_input_stream *lip, int remaining_recursions_permitted)
+{
+ reg1 uchar c;
+ while (! lip->eof())
+ {
+ c= lip->yyGet();
+
+ if (remaining_recursions_permitted > 0)
+ {
+ if ((c == '/') && (lip->yyPeek() == '*'))
+ {
+ lip->yySkip(); /* Eat asterisk */
+ consume_comment(lip, remaining_recursions_permitted-1);
+ continue;
+ }
+ }
+
+ if (c == '*')
+ {
+ if (lip->yyPeek() == '/')
+ {
+ lip->yySkip(); /* Eat slash */
+ return FALSE;
+ }
+ }
+
+ if (c == '\n')
+ lip->yylineno++;
+ }
+
+ return TRUE;
+}
+
+
/*
MYSQLlex remember the following states from the following MYSQLlex()
@@ -735,12 +793,12 @@ int MYSQLlex(void *arg, void *yythd)
uchar *state_map= cs->state_map;
uchar *ident_map= cs->ident_map;
+ LINT_INIT(c);
lip->yylval=yylval; // The global state
lip->start_token();
state=lip->next_state;
lip->next_state=MY_LEX_OPERATOR_OR_IDENT;
- LINT_INIT(c);
for (;;)
{
switch (state) {
@@ -1056,9 +1114,12 @@ int MYSQLlex(void *arg, void *yythd)
}
}
#ifdef USE_MB
- else if (var_length < 1)
- break; // Error
- lip->skip_binary(var_length-1);
+ else if (use_mb(cs))
+ {
+ if ((var_length= my_ismbchar(cs, lip->get_ptr() - 1,
+ lip->get_end_of_query())))
+ lip->skip_binary(var_length-1);
+ }
#endif
}
if (double_quotes)
@@ -1213,6 +1274,8 @@ int MYSQLlex(void *arg, void *yythd)
/* Reject '/' '*', since we might need to turn off the echo */
lip->yyUnget();
+ lip->save_in_comment_state();
+
if (lip->yyPeekn(2) == '!')
{
lip->in_comment= DISCARD_COMMENT;
@@ -1255,11 +1318,17 @@ int MYSQLlex(void *arg, void *yythd)
/* Expand the content of the special comment as real code */
lip->set_echo(TRUE);
state=MY_LEX_START;
- break;
+ break; /* Do not treat contents as a comment. */
+ }
+ else
+ {
+ comment_closed= ! consume_comment(lip, 1);
+ /* version allowed to have one level of comment inside. */
}
}
else
{
+ /* Not a version comment. */
state=MY_LEX_START;
lip->set_echo(TRUE);
break;
@@ -1270,38 +1339,30 @@ int MYSQLlex(void *arg, void *yythd)
lip->in_comment= PRESERVE_COMMENT;
lip->yySkip(); // Accept /
lip->yySkip(); // Accept *
+ comment_closed= ! consume_comment(lip, 0);
+ /* regular comments can have zero comments inside. */
}
/*
Discard:
- regular '/' '*' comments,
- special comments '/' '*' '!' for a future version,
by scanning until we find a closing '*' '/' marker.
- Note: There is no such thing as nesting comments,
- the first '*' '/' sequence seen will mark the end.
+
+ Nesting regular comments isn't allowed. The first
+ '*' '/' returns the parser to the previous state.
+
+ /#!VERSI oned containing /# regular #/ is allowed #/
+
+ Inside one versioned comment, another versioned comment
+ is treated as a regular discardable comment. It gets
+ no special parsing.
*/
- comment_closed= FALSE;
- while (! lip->eof())
- {
- c= lip->yyGet();
- if (c == '*')
- {
- if (lip->yyPeek() == '/')
- {
- lip->yySkip();
- comment_closed= TRUE;
- state = MY_LEX_START;
- break;
- }
- }
- else if (c == '\n')
- lip->yylineno++;
- }
+
/* Unbalanced comments with a missing '*' '/' are a syntax error */
if (! comment_closed)
return (ABORT_SYM);
state = MY_LEX_START; // Try again
- lip->in_comment= NO_COMMENT;
- lip->set_echo(TRUE);
+ lip->restore_in_comment_state();
break;
case MY_LEX_END_LONG_COMMENT:
if ((lip->in_comment != NO_COMMENT) && lip->yyPeek() == '/')