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.cc188
1 files changed, 154 insertions, 34 deletions
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 87f50d41b31..df4d8d7b94c 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -693,6 +693,7 @@ void LEX::start(THD *thd_arg)
curr_with_clause= 0;
with_clauses_list= 0;
with_clauses_list_last_next= &with_clauses_list;
+ clone_spec_offset= 0;
create_view= NULL;
field_list.empty();
value_list.empty();
@@ -744,7 +745,7 @@ void LEX::start(THD *thd_arg)
profile_options= PROFILE_NONE;
nest_level= 0;
builtin_select.nest_level_base= &unit;
- allow_sum_func= 0;
+ allow_sum_func.clear_all();
in_sum_func= NULL;
used_tables= 0;
@@ -855,6 +856,32 @@ int Lex_input_stream::find_keyword(Lex_ident_cli_st *kwd,
DBUG_ASSERT(tok >= get_buf());
DBUG_ASSERT(tok < get_end_of_query());
+ if (m_thd->variables.sql_mode & MODE_ORACLE)
+ {
+ switch (symbol->tok) {
+ case BEGIN_MARIADB_SYM: return BEGIN_ORACLE_SYM;
+ case BLOB_MARIADB_SYM: return BLOB_ORACLE_SYM;
+ case BODY_MARIADB_SYM: return BODY_ORACLE_SYM;
+ case CLOB_MARIADB_SYM: return CLOB_ORACLE_SYM;
+ case CONTINUE_MARIADB_SYM: return CONTINUE_ORACLE_SYM;
+ case DECLARE_MARIADB_SYM: return DECLARE_ORACLE_SYM;
+ case DECODE_MARIADB_SYM: return DECODE_ORACLE_SYM;
+ case ELSEIF_MARIADB_SYM: return ELSEIF_ORACLE_SYM;
+ case ELSIF_MARIADB_SYM: return ELSIF_ORACLE_SYM;
+ case EXCEPTION_MARIADB_SYM: return EXCEPTION_ORACLE_SYM;
+ case EXIT_MARIADB_SYM: return EXIT_ORACLE_SYM;
+ case GOTO_MARIADB_SYM: return GOTO_ORACLE_SYM;
+ case NUMBER_MARIADB_SYM: return NUMBER_ORACLE_SYM;
+ case OTHERS_MARIADB_SYM: return OTHERS_ORACLE_SYM;
+ case PACKAGE_MARIADB_SYM: return PACKAGE_ORACLE_SYM;
+ case RAISE_MARIADB_SYM: return RAISE_ORACLE_SYM;
+ case RAW_MARIADB_SYM: return RAW_ORACLE_SYM;
+ case RETURN_MARIADB_SYM: return RETURN_ORACLE_SYM;
+ case ROWTYPE_MARIADB_SYM: return ROWTYPE_ORACLE_SYM;
+ case VARCHAR2_MARIADB_SYM: return VARCHAR2_ORACLE_SYM;
+ }
+ }
+
if ((symbol->tok == NOT_SYM) &&
(m_thd->variables.sql_mode & MODE_HIGH_NOT_PRECEDENCE))
return NOT2_SYM;
@@ -1469,6 +1496,12 @@ int Lex_input_stream::lex_one_token(YYSTYPE *yylval, THD *thd)
}
/* Fall through */
case MY_LEX_CHAR: // Unknown or single char token
+ if (c == '%' && (m_thd->variables.sql_mode & MODE_ORACLE))
+ {
+ next_state= MY_LEX_START;
+ return PERCENT_ORACLE_SYM;
+ }
+ /* Fall through */
case MY_LEX_SKIP: // This should not happen
if (c != ')')
next_state= MY_LEX_START; // Allow signed numbers
@@ -1827,7 +1860,7 @@ int Lex_input_stream::lex_one_token(YYSTYPE *yylval, THD *thd)
else
{
#ifdef WITH_WSREP
- if (WSREP(thd) && version == 99997 && thd->wsrep_exec_mode == LOCAL_STATE)
+ if (WSREP(thd) && version == 99997 && wsrep_thd_is_local(thd))
{
WSREP_DEBUG("consistency check: %s", thd->query());
thd->wsrep_consistency_check= CONSISTENCY_CHECK_DECLARED;
@@ -1907,8 +1940,13 @@ int Lex_input_stream::lex_one_token(YYSTYPE *yylval, THD *thd)
case MY_LEX_SET_VAR: // Check if ':='
if (yyPeek() != '=')
{
- state= MY_LEX_CHAR; // Return ':'
- break;
+ next_state= MY_LEX_START;
+ if (m_thd->variables.sql_mode & MODE_ORACLE)
+ {
+ yylval->kwd.set_keyword(m_tok_start, 1);
+ return COLON_ORACLE_SYM;
+ }
+ return (int) ':';
}
yySkip();
return (SET_VAR);
@@ -2389,7 +2427,7 @@ void st_select_lex::init_select()
m_non_agg_field_used= false;
m_agg_func_used= false;
m_custom_agg_func_used= false;
- name_visibility_map= 0;
+ name_visibility_map.clear_all();
with_dep= 0;
join= 0;
lock_type= TL_READ_DEFAULT;
@@ -3170,7 +3208,7 @@ LEX::LEX()
INITIAL_LEX_PLUGIN_LIST_SIZE, 0);
reset_query_tables_list(TRUE);
mi.init();
- init_dynamic_array2(&delete_gtid_domain, sizeof(ulong*),
+ init_dynamic_array2(&delete_gtid_domain, sizeof(uint32),
gtid_domain_static_buffer,
initial_gtid_domain_buffer_size,
initial_gtid_domain_buffer_size, 0);
@@ -3507,12 +3545,8 @@ void LEX::set_trg_event_type_for_tables()
On a LOCK TABLE, all triggers must be pre-loaded for this TABLE_LIST
when opening an associated TABLE.
*/
- new_trg_event_map= static_cast<uint8>
- (1 << static_cast<int>(TRG_EVENT_INSERT)) |
- static_cast<uint8>
- (1 << static_cast<int>(TRG_EVENT_UPDATE)) |
- static_cast<uint8>
- (1 << static_cast<int>(TRG_EVENT_DELETE));
+ new_trg_event_map= trg2bit(TRG_EVENT_INSERT) | trg2bit(TRG_EVENT_UPDATE) |
+ trg2bit(TRG_EVENT_DELETE);
break;
/*
Basic INSERT. If there is an additional ON DUPLIATE KEY UPDATE
@@ -3543,20 +3577,17 @@ void LEX::set_trg_event_type_for_tables()
*/
case SQLCOM_CREATE_TABLE:
case SQLCOM_CREATE_SEQUENCE:
- new_trg_event_map|= static_cast<uint8>
- (1 << static_cast<int>(TRG_EVENT_INSERT));
+ new_trg_event_map|= trg2bit(TRG_EVENT_INSERT);
break;
/* Basic update and multi-update */
case SQLCOM_UPDATE: /* fall through */
case SQLCOM_UPDATE_MULTI:
- new_trg_event_map|= static_cast<uint8>
- (1 << static_cast<int>(TRG_EVENT_UPDATE));
+ new_trg_event_map|= trg2bit(TRG_EVENT_UPDATE);
break;
/* Basic delete and multi-delete */
case SQLCOM_DELETE: /* fall through */
case SQLCOM_DELETE_MULTI:
- new_trg_event_map|= static_cast<uint8>
- (1 << static_cast<int>(TRG_EVENT_DELETE));
+ new_trg_event_map|= trg2bit(TRG_EVENT_DELETE);
break;
default:
break;
@@ -3564,12 +3595,10 @@ void LEX::set_trg_event_type_for_tables()
switch (duplicates) {
case DUP_UPDATE:
- new_trg_event_map|= static_cast<uint8>
- (1 << static_cast<int>(TRG_EVENT_UPDATE));
+ new_trg_event_map|= trg2bit(TRG_EVENT_UPDATE);
break;
case DUP_REPLACE:
- new_trg_event_map|= static_cast<uint8>
- (1 << static_cast<int>(TRG_EVENT_DELETE));
+ new_trg_event_map|= trg2bit(TRG_EVENT_DELETE);
break;
case DUP_ERROR:
default:
@@ -4101,6 +4130,7 @@ bool st_select_lex::optimize_unflattened_subqueries(bool const_only)
inner_join->select_options|= SELECT_DESCRIBE;
}
res= inner_join->optimize();
+ sl->update_used_tables();
sl->update_correlated_cache();
is_correlated_unit|= sl->is_correlated;
inner_join->select_options= save_options;
@@ -5257,6 +5287,9 @@ LEX::create_unit(SELECT_LEX *first_sel)
SELECT_LEX_UNIT *unit;
DBUG_ENTER("LEX::create_unit");
+ if (first_sel->master_unit())
+ DBUG_RETURN(first_sel->master_unit());
+
if (!(unit= alloc_unit()))
DBUG_RETURN(NULL);
@@ -5930,7 +5963,7 @@ bool LEX::sp_for_loop_implicit_cursor_statement(THD *thd,
return true;
DBUG_ASSERT(thd->lex == this);
bounds->m_direction= 1;
- bounds->m_upper_bound= NULL;
+ bounds->m_target_bound= NULL;
bounds->m_implicit_cursor= true;
return false;
}
@@ -5974,7 +6007,7 @@ bool LEX::sp_for_loop_condition(THD *thd, const Lex_for_loop_st &loop)
Item_splocal *args[2];
for (uint i= 0 ; i < 2; i++)
{
- sp_variable *src= i == 0 ? loop.m_index : loop.m_upper_bound;
+ sp_variable *src= i == 0 ? loop.m_index : loop.m_target_bound;
args[i]= new (thd->mem_root)
Item_splocal(thd, &sp_rcontext_handler_local,
&src->name, src->offset, src->type_handler());
@@ -6037,7 +6070,7 @@ bool LEX::sp_for_loop_intrange_declarations(THD *thd, Lex_for_loop_st *loop,
my_error(ER_SP_UNDECLARED_VAR, MYF(0), item->full_name());
return true;
}
- if ((item= bounds.m_upper_bound->get_item())->type() == Item::FIELD_ITEM)
+ if ((item= bounds.m_target_bound->get_item())->type() == Item::FIELD_ITEM)
{
// We're here is the upper bound is unknown identifier
my_error(ER_SP_UNDECLARED_VAR, MYF(0), item->full_name());
@@ -6047,11 +6080,11 @@ bool LEX::sp_for_loop_intrange_declarations(THD *thd, Lex_for_loop_st *loop,
bounds.m_index->sp_add_for_loop_variable(thd, index,
bounds.m_index->get_item())))
return true;
- if (unlikely(!(loop->m_upper_bound=
- bounds.m_upper_bound->
- sp_add_for_loop_upper_bound(thd,
- bounds.
- m_upper_bound->get_item()))))
+ if (unlikely(!(loop->m_target_bound=
+ bounds.m_target_bound->
+ sp_add_for_loop_target_bound(thd,
+ bounds.
+ m_target_bound->get_item()))))
return true;
loop->m_direction= bounds.m_direction;
loop->m_implicit_cursor= 0;
@@ -6114,7 +6147,7 @@ bool LEX::sp_for_loop_cursor_declarations(THD *thd,
bounds.m_index,
item_func_sp)))
return true;
- loop->m_upper_bound= NULL;
+ loop->m_target_bound= NULL;
loop->m_direction= bounds.m_direction;
loop->m_cursor_offset= coffs;
loop->m_implicit_cursor= bounds.m_implicit_cursor;
@@ -6920,6 +6953,30 @@ Item *LEX::make_item_colon_ident_ident(THD *thd,
}
+Item *LEX::make_item_plsql_cursor_attr(THD *thd, const LEX_CSTRING *name,
+ plsql_cursor_attr_t attr)
+{
+ uint offset;
+ if (unlikely(!spcont || !spcont->find_cursor(name, &offset, false)))
+ {
+ my_error(ER_SP_CURSOR_MISMATCH, MYF(0), name->str);
+ return NULL;
+ }
+ switch (attr) {
+ case PLSQL_CURSOR_ATTR_ISOPEN:
+ return new (thd->mem_root) Item_func_cursor_isopen(thd, name, offset);
+ case PLSQL_CURSOR_ATTR_FOUND:
+ return new (thd->mem_root) Item_func_cursor_found(thd, name, offset);
+ case PLSQL_CURSOR_ATTR_NOTFOUND:
+ return new (thd->mem_root) Item_func_cursor_notfound(thd, name, offset);
+ case PLSQL_CURSOR_ATTR_ROWCOUNT:
+ return new (thd->mem_root) Item_func_cursor_rowcount(thd, name, offset);
+ }
+ DBUG_ASSERT(0);
+ return NULL;
+}
+
+
Item *LEX::make_item_sysvar(THD *thd,
enum_var_type type,
const LEX_CSTRING *name,
@@ -6945,6 +7002,14 @@ Item *LEX::make_item_sysvar(THD *thd,
}
+static bool param_push_or_clone(THD *thd, LEX *lex, Item_param *item)
+{
+ return !lex->clone_spec_offset ?
+ lex->param_list.push_back(item, thd->mem_root) :
+ item->add_as_clone(thd);
+}
+
+
Item_param *LEX::add_placeholder(THD *thd, const LEX_CSTRING *name,
const char *start, const char *end)
{
@@ -6961,7 +7026,7 @@ Item_param *LEX::add_placeholder(THD *thd, const LEX_CSTRING *name,
Query_fragment pos(thd, sphead, start, end);
Item_param *item= new (thd->mem_root) Item_param(thd, name,
pos.pos(), pos.length());
- if (unlikely(!item) || unlikely(param_list.push_back(item, thd->mem_root)))
+ if (unlikely(!item) || unlikely(param_push_or_clone(thd, this, item)))
{
my_error(ER_OUT_OF_RESOURCES, MYF(0));
return NULL;
@@ -9277,7 +9342,7 @@ bool LEX::parsed_insert_select(SELECT_LEX *first_select)
return true;
// fix "main" select
- SELECT_LEX *blt= pop_select();
+ SELECT_LEX *blt __attribute__((unused))= pop_select();
DBUG_ASSERT(blt == &builtin_select);
push_select(first_select);
return false;
@@ -9466,4 +9531,59 @@ bool SELECT_LEX::make_unique_derived_name(THD *thd, LEX_CSTRING *alias)
alias->str= thd->strmake(buff, alias->length);
return !alias->str;
}
-
+
+
+/*
+ Make a new sp_instr_stmt and set its m_query to a concatenation
+ of two strings.
+*/
+bool LEX::new_sp_instr_stmt(THD *thd,
+ const LEX_CSTRING &prefix,
+ const LEX_CSTRING &suffix)
+{
+ LEX_STRING qbuff;
+ sp_instr_stmt *i;
+
+ if (!(i= new (thd->mem_root) sp_instr_stmt(sphead->instructions(),
+ spcont, this)))
+ return true;
+
+ qbuff.length= prefix.length + suffix.length;
+ if (!(qbuff.str= (char*) alloc_root(thd->mem_root, qbuff.length + 1)))
+ return true;
+ memcpy(qbuff.str, prefix.str, prefix.length);
+ strmake(qbuff.str + prefix.length, suffix.str, suffix.length);
+ i->m_query= qbuff;
+ return sphead->add_instr(i);
+}
+
+
+bool LEX::sp_proc_stmt_statement_finalize_buf(THD *thd, const LEX_CSTRING &qbuf)
+{
+ sphead->m_flags|= sp_get_flags_for_command(this);
+ /* "USE db" doesn't work in a procedure */
+ if (unlikely(sql_command == SQLCOM_CHANGE_DB))
+ {
+ my_error(ER_SP_BADSTATEMENT, MYF(0), "USE");
+ return true;
+ }
+ /*
+ Don't add an instruction for SET statements, since all
+ instructions for them were already added during processing
+ of "set" rule.
+ */
+ DBUG_ASSERT(sql_command != SQLCOM_SET_OPTION || var_list.is_empty());
+ if (sql_command != SQLCOM_SET_OPTION)
+ return new_sp_instr_stmt(thd, empty_clex_str, qbuf);
+ return false;
+}
+
+
+bool LEX::sp_proc_stmt_statement_finalize(THD *thd, bool no_lookahead)
+{
+ // Extract the query statement from the tokenizer
+ Lex_input_stream *lip= &thd->m_parser_state->m_lip;
+ Lex_cstring qbuf(sphead->m_tmp_query, no_lookahead ? lip->get_ptr() :
+ lip->get_tok_start());
+ return LEX::sp_proc_stmt_statement_finalize_buf(thd, qbuf);
+}