summaryrefslogtreecommitdiff
path: root/sql/sql_lex.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_lex.cc')
-rw-r--r--sql/sql_lex.cc294
1 files changed, 187 insertions, 107 deletions
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 7bcdc499011..65e5f8035e4 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -28,14 +28,15 @@
We are using pointer to this variable for distinguishing between assignment
to NEW row field (when parsing trigger definition) and structured variable.
*/
-sys_var_long_ptr trg_new_row_fake_var(0, 0);
+
+sys_var *trg_new_row_fake_var= (sys_var*) 0x01;
/* Macros to look like lex */
-#define yyGet() *(lip->ptr++)
-#define yyGetLast() lip->ptr[-1]
-#define yyPeek() lip->ptr[0]
-#define yyPeek2() lip->ptr[1]
+#define yyGet() ((uchar) *(lip->ptr++))
+#define yyGetLast() ((uchar) lip->ptr[-1])
+#define yyPeek() ((uchar) lip->ptr[0])
+#define yyPeek2() ((uchar) lip->ptr[1])
#define yyUnget() lip->ptr--
#define yySkip() lip->ptr++
#define yyLength() ((uint) (lip->ptr - lip->tok_start)-1)
@@ -68,6 +69,17 @@ static uchar to_upper_lex[]=
208,209,210,211,212,213,214,247,216,217,218,219,220,221,222,255
};
+/*
+ Names of the index hints (for error messages). Keep in sync with
+ index_hint_type
+*/
+
+const char * index_hint_type_name[] =
+{
+ "IGNORE INDEX",
+ "USE INDEX",
+ "FORCE INDEX"
+};
inline int lex_casecmp(const char *s, const char *t, uint len)
{
@@ -76,7 +88,7 @@ inline int lex_casecmp(const char *s, const char *t, uint len)
return (int) len+1;
}
-#include "lex_hash.h"
+#include <lex_hash.h>
void lex_init(void)
@@ -176,35 +188,53 @@ void lex_start(THD *thd)
lex->derived_tables= 0;
lex->lock_option= TL_READ;
lex->safe_to_cache_query= 1;
- lex->time_zone_tables_used= 0;
lex->leaf_tables_insert= 0;
lex->parsing_options.reset();
lex->empty_field_list_on_rset= 0;
lex->select_lex.select_number= 1;
-
lex->in_comment=0;
lex->length=0;
+ lex->part_info= 0;
lex->select_lex.in_sum_expr=0;
lex->select_lex.expr_list.empty();
lex->select_lex.ftfunc_list_alloc.empty();
lex->select_lex.ftfunc_list= &lex->select_lex.ftfunc_list_alloc;
lex->select_lex.group_list.empty();
lex->select_lex.order_list.empty();
- lex->select_lex.udf_list.empty();
- lex->current_select= &lex->select_lex;
- lex->yacc_yyss=lex->yacc_yyvs=0;
- lex->sql_command= lex->orig_sql_command= SQLCOM_END;
+ lex->sql_command= SQLCOM_END;
lex->duplicates= DUP_ERROR;
lex->ignore= 0;
+ lex->spname= NULL;
lex->sphead= NULL;
lex->spcont= NULL;
lex->proc_list.first= 0;
lex->escape_used= FALSE;
+ lex->query_tables= 0;
lex->reset_query_tables_list(FALSE);
+ lex->expr_allows_subselect= TRUE;
+
+ lex->name.str= 0;
+ lex->name.length= 0;
+ lex->event_parse_data= NULL;
lex->nest_level=0 ;
lex->allow_sum_func= 0;
lex->in_sum_func= NULL;
+ /*
+ ok, there must be a better solution for this, long-term
+ I tried "bzero" in the sql_yacc.yy code, but that for
+ some reason made the values zero, even if they were set
+ */
+ lex->server_options.server_name= 0;
+ lex->server_options.server_name_length= 0;
+ lex->server_options.host= 0;
+ lex->server_options.db= 0;
+ lex->server_options.username= 0;
+ lex->server_options.password= 0;
+ lex->server_options.scheme= 0;
+ lex->server_options.socket= 0;
+ lex->server_options.owner= 0;
+ lex->server_options.port= -1;
DBUG_VOID_RETURN;
}
@@ -212,8 +242,19 @@ void lex_end(LEX *lex)
{
DBUG_ENTER("lex_end");
DBUG_PRINT("enter", ("lex: 0x%lx", (long) lex));
- x_free(lex->yacc_yyss);
- x_free(lex->yacc_yyvs);
+ 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;
+ }
+
+ /* release used plugins */
+ plugin_unlock_list(0, (plugin_ref*)lex->plugins.buffer,
+ lex->plugins.elements);
+ reset_dynamic(&lex->plugins);
+
DBUG_VOID_RETURN;
}
@@ -228,14 +269,14 @@ static int find_keyword(Lex_input_stream *lip, uint len, bool function)
lip->yylval->symbol.symbol=symbol;
lip->yylval->symbol.str= (char*) tok;
lip->yylval->symbol.length=len;
-
+
if ((symbol->tok == NOT_SYM) &&
(lip->m_thd->variables.sql_mode & MODE_HIGH_NOT_PRECEDENCE))
return NOT2_SYM;
if ((symbol->tok == OR_OR_SYM) &&
!(lip->m_thd->variables.sql_mode & MODE_PIPES_AS_CONCAT))
return OR2_SYM;
-
+
return symbol->tok;
}
return 0;
@@ -260,6 +301,12 @@ bool is_keyword(const char *name, uint len)
return get_hash_symbol(name,len,0)!=0;
}
+bool is_lex_native_function(const LEX_STRING *name)
+{
+ DBUG_ASSERT(name != NULL);
+ return (get_hash_symbol(name->str, name->length, 1) != 0);
+}
+
/* make a copy of token before ptr and set yytoklen */
static LEX_STRING get_token(Lex_input_stream *lip, uint skip, uint length)
@@ -283,12 +330,13 @@ static LEX_STRING get_quoted_token(Lex_input_stream *lip,
uint length, char quote)
{
LEX_STRING tmp;
- byte *from, *to, *end;
+ const char *from, *end;
+ char *to;
yyUnget(); // ptr points now after last token char
- tmp.length=lip->yytoklen=length;
+ tmp.length= lip->yytoklen=length;
tmp.str=(char*) lip->m_thd->alloc(tmp.length+1);
- from= (byte*) lip->tok_start + skip;
- to= (byte*) tmp.str;
+ from= lip->tok_start + skip;
+ to= tmp.str;
end= to+length;
for ( ; to != end; )
{
@@ -319,16 +367,14 @@ static char *get_text(Lex_input_stream *lip)
{
int l;
if (use_mb(cs) &&
- (l = my_ismbchar(cs,
- lip->ptr-1,
- lip->end_of_query))) {
+ (l = my_ismbchar(cs, lip->ptr-1, lip->end_of_query))) {
lip->ptr += l-1;
continue;
}
}
#endif
if (c == '\\' &&
- !(lip->m_thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES))
+ !(lip->m_thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES))
{ // Escaped character
found_escape=1;
if (lip->ptr == lip->end_of_query)
@@ -346,13 +392,12 @@ static char *get_text(Lex_input_stream *lip)
yyUnget();
/* Found end. Unescape and return string */
- const char *str;
- const char *end;
+ const char *str, *end;
char *start;
str=lip->tok_start+1;
end=lip->ptr-1;
- if (!(start=(char*) lip->m_thd->alloc((uint) (end-str)+1)))
+ if (!(start= (char*) lip->m_thd->alloc((uint) (end-str)+1)))
return (char*) ""; // Sql_alloc has set error flag
if (!found_escape)
{
@@ -362,15 +407,14 @@ static char *get_text(Lex_input_stream *lip)
}
else
{
- char *to;
+ char *to;
for (to=start ; str != end ; str++)
{
#ifdef USE_MB
int l;
if (use_mb(cs) &&
- (l = my_ismbchar(cs,
- (const char *)str, (const char *)end))) {
+ (l = my_ismbchar(cs, str, end))) {
while (l--)
*to++ = *str++;
str--;
@@ -416,7 +460,7 @@ static char *get_text(Lex_input_stream *lip)
*to=0;
lip->yytoklen=(uint) (to-start);
}
- return (char*) start;
+ return start;
}
}
return 0; // unexpected end of query
@@ -627,9 +671,7 @@ int MYSQLlex(void *arg, void *yythd)
result_state= IDENT_QUOTED;
if (my_mbcharlen(cs, yyGetLast()) > 1)
{
- int l = my_ismbchar(cs,
- lip->ptr-1,
- lip->end_of_query);
+ int l = my_ismbchar(cs, lip->ptr-1, lip->end_of_query);
if (l == 0) {
state = MY_LEX_CHAR;
continue;
@@ -641,9 +683,7 @@ int MYSQLlex(void *arg, void *yythd)
if (my_mbcharlen(cs, c) > 1)
{
int l;
- if ((l = my_ismbchar(cs,
- lip->ptr-1,
- lip->end_of_query)) == 0)
+ if ((l = my_ismbchar(cs, lip->ptr-1, lip->end_of_query)) == 0)
break;
lip->ptr += l-1;
}
@@ -671,7 +711,7 @@ int MYSQLlex(void *arg, void *yythd)
else
{ // '(' must follow directly if function
yyUnget();
- if ((tokval = find_keyword(lip, length, c == '(')))
+ if ((tokval = find_keyword(lip, length,c == '(')))
{
lip->next_state= MY_LEX_START; // Allow signed numbers
return(tokval); // Was keyword
@@ -762,9 +802,7 @@ int MYSQLlex(void *arg, void *yythd)
if (my_mbcharlen(cs, c) > 1)
{
int l;
- if ((l = my_ismbchar(cs,
- lip->ptr-1,
- lip->end_of_query)) == 0)
+ if ((l = my_ismbchar(cs, lip->ptr-1, lip->end_of_query)) == 0)
break;
lip->ptr += l-1;
}
@@ -792,8 +830,6 @@ int MYSQLlex(void *arg, void *yythd)
int var_length;
if ((var_length= my_mbcharlen(cs, c)) == 1)
{
- if (c == (uchar) NAMES_SEP_CHAR)
- break; /* Old .frm format can't handle this char */
if (c == quote_char)
{
if (yyPeek() != quote_char)
@@ -877,7 +913,7 @@ int MYSQLlex(void *arg, void *yythd)
if (state_map[yyPeek()] == MY_LEX_CMP_OP ||
state_map[yyPeek()] == MY_LEX_LONG_CMP_OP)
yySkip();
- if ((tokval = find_keyword(lip,(uint) (lip->ptr - lip->tok_start),0)))
+ if ((tokval = find_keyword(lip, (uint) (lip->ptr - lip->tok_start),0)))
{
lip->next_state= MY_LEX_START; // Allow signed numbers
return(tokval);
@@ -893,7 +929,7 @@ int MYSQLlex(void *arg, void *yythd)
if (state_map[yyPeek()] == MY_LEX_CMP_OP)
yySkip();
}
- if ((tokval = find_keyword(lip,(uint) (lip->ptr - lip->tok_start),0)))
+ if ((tokval = find_keyword(lip, (uint) (lip->ptr - lip->tok_start),0)))
{
lip->next_state= MY_LEX_START; // Found long op
return(tokval);
@@ -994,7 +1030,7 @@ int MYSQLlex(void *arg, void *yythd)
lex->safe_to_cache_query= 0;
lip->found_semicolon= lip->ptr;
thd->server_status|= SERVER_MORE_RESULTS_EXISTS;
- lip->next_state= MY_LEX_END;
+ lip->next_state= MY_LEX_END;
return (END_OF_INPUT);
}
state= MY_LEX_CHAR; // Return ';'
@@ -1082,17 +1118,6 @@ int MYSQLlex(void *arg, void *yythd)
}
-Alter_info::Alter_info(const Alter_info &rhs, MEM_ROOT *mem_root)
- :drop_list(rhs.drop_list, mem_root),
- alter_list(rhs.alter_list, mem_root),
- key_list(rhs.key_list, mem_root),
- create_list(rhs.create_list, mem_root),
- flags(rhs.flags),
- keys_onoff(rhs.keys_onoff),
- tablespace_op(rhs.tablespace_op)
-{}
-
-
/*
Skip comment in the end of statement.
@@ -1108,7 +1133,7 @@ Alter_info::Alter_info(const Alter_info &rhs, MEM_ROOT *mem_root)
Pointer to the last non-comment symbol of the statement.
*/
-char *skip_rear_comments(char *begin, char *end)
+const char *skip_rear_comments(const char *begin, const char *end)
{
while (begin < end && (end[-1] <= ' ' || end[-1] == '*' ||
end[-1] == '/' || end[-1] == ';'))
@@ -1197,16 +1222,13 @@ void st_select_lex::init_select()
group_list.empty();
type= db= 0;
having= 0;
- use_index_ptr= ignore_index_ptr= 0;
table_join_options= 0;
in_sum_expr= with_wild= 0;
options= 0;
sql_cache= SQL_CACHE_UNSPECIFIED;
braces= 0;
expr_list.empty();
- udf_list.empty();
interval_list.empty();
- use_index.empty();
ftfunc_list_alloc.empty();
inner_sum_func_list= 0;
ftfunc_list= &ftfunc_list_alloc;
@@ -1433,14 +1455,11 @@ 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; }
-TABLE_LIST *st_select_lex_node::add_table_to_list(THD *thd, Table_ident *table,
+TABLE_LIST *st_select_lex_node::add_table_to_list (THD *thd, Table_ident *table,
LEX_STRING *alias,
ulong table_join_options,
thr_lock_type flags,
- List<String> *use_index,
- List<String> *ignore_index,
+ List<index_hint> *hints,
LEX_STRING *option)
{
return 0;
@@ -1488,7 +1507,7 @@ bool st_select_lex::add_order_to_list(THD *thd, Item *item, bool asc)
bool st_select_lex::add_item_to_list(THD *thd, Item *item)
{
DBUG_ENTER("st_select_lex::add_item_to_list");
- DBUG_PRINT("info", ("Item: %p", item));
+ DBUG_PRINT("info", ("Item: 0x%lx", (long) item));
DBUG_RETURN(item_list.push_back(item));
}
@@ -1547,19 +1566,6 @@ List<Item>* st_select_lex::get_item_list()
return &item_list;
}
-
-List<String>* st_select_lex::get_use_index()
-{
- return use_index_ptr;
-}
-
-
-List<String>* st_select_lex::get_ignore_index()
-{
- return ignore_index_ptr;
-}
-
-
ulong st_select_lex::get_table_join_options()
{
return table_join_options;
@@ -1715,6 +1721,17 @@ void st_lex::cleanup_lex_after_parse_error(THD *thd)
void Query_tables_list::reset_query_tables_list(bool init)
{
+ if (!init && query_tables)
+ {
+ TABLE_LIST *table= query_tables;
+ for (;;)
+ {
+ delete table->view;
+ if (query_tables_last == &table->next_global ||
+ !(table= table->next_global))
+ break;
+ }
+ }
query_tables= 0;
query_tables_last= &query_tables;
query_tables_own_last= 0;
@@ -1734,6 +1751,7 @@ void Query_tables_list::reset_query_tables_list(bool init)
sroutines_list.empty();
sroutines_list_own_last= sroutines_list.next;
sroutines_list_own_elements= 0;
+ binlog_row_based_if_mixed= FALSE;
}
@@ -1766,8 +1784,15 @@ void Query_tables_list::destroy_query_tables_list()
st_lex::st_lex()
:result(0), yacc_yyss(0), yacc_yyvs(0),
- sql_command(SQLCOM_END)
+ sql_command(SQLCOM_END), option_type(OPT_DEFAULT)
{
+ /* Check that plugins_static_buffer is declared immediately after plugins */
+ compile_time_assert((&plugins + 1) == (DYNAMIC_ARRAY*)plugins_static_buffer);
+
+ my_init_dynamic_array2(&plugins, sizeof(plugin_ref),
+ plugins_static_buffer,
+ INITIAL_LEX_PLUGIN_LIST_SIZE,
+ INITIAL_LEX_PLUGIN_LIST_SIZE);
reset_query_tables_list(TRUE);
}
@@ -2090,31 +2115,6 @@ void st_lex::first_lists_tables_same()
/*
- 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_arg)
-{
- /* We should not add these tables twice */
- if (!time_zone_tables_used)
- {
- time_zone_tables_used= my_tz_get_table_list(thd_arg, &query_tables_last);
- if (time_zone_tables_used == &fake_time_zone_tables_list)
- return TRUE;
- }
- return FALSE;
-}
-
-/*
Link table back that was unlinked with unlink_first_table()
SYNOPSIS
@@ -2183,7 +2183,6 @@ void st_lex::cleanup_after_one_table_open()
/* remove underlying units (units of VIEW) subtree */
select_lex.cut_subtree();
}
- time_zone_tables_used= 0;
}
@@ -2223,6 +2222,28 @@ void st_lex::restore_backup_query_tables_list(Query_tables_list *backup)
/*
+ 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);
+}
+
+
+/*
Do end-of-prepare fixup for list of tables and their merge-VIEWed tables
SYNOPSIS
@@ -2289,6 +2310,7 @@ void st_select_lex::fix_prepare_information(THD *thd, Item **conds,
}
}
+
/*
There are st_select_lex::add_table_to_list &
st_select_lex::set_lock_for_tables are in sql_parse.cc
@@ -2301,3 +2323,61 @@ void st_select_lex::fix_prepare_information(THD *thd, Item **conds,
are in sql_union.cc
*/
+/*
+ Sets the kind of hints to be added by the calls to add_index_hint().
+
+ SYNOPSIS
+ set_index_hint_type()
+ type the kind of hints to be added from now on.
+ clause the clause to use for hints to be added from now on.
+
+ DESCRIPTION
+ Used in filling up the tagged hints list.
+ This list is filled by first setting the kind of the hint as a
+ context variable and then adding hints of the current kind.
+ Then the context variable index_hint_type can be reset to the
+ next hint type.
+*/
+void st_select_lex::set_index_hint_type(enum index_hint_type type,
+ index_clause_map clause)
+{
+ current_index_hint_type= type;
+ current_index_hint_clause= clause;
+}
+
+
+/*
+ Makes an array to store index usage hints (ADD/FORCE/IGNORE INDEX).
+
+ SYNOPSIS
+ alloc_index_hints()
+ thd current thread.
+*/
+
+void st_select_lex::alloc_index_hints (THD *thd)
+{
+ index_hints= new (thd->mem_root) List<index_hint>();
+}
+
+
+
+/*
+ adds an element to the array storing index usage hints
+ (ADD/FORCE/IGNORE INDEX).
+
+ SYNOPSIS
+ add_index_hint()
+ thd current thread.
+ str name of the index.
+ length number of characters in str.
+
+ RETURN VALUE
+ 0 on success, non-zero otherwise
+*/
+bool st_select_lex::add_index_hint (THD *thd, char *str, uint length)
+{
+ return index_hints->push_front (new (thd->mem_root)
+ index_hint(current_index_hint_type,
+ current_index_hint_clause,
+ str, length));
+}