Commit ffca1e48 authored by Alexander Barkov's avatar Alexander Barkov

MDEV-10578 sql_mode=ORACLE: SP control functions SQLCODE, SQLERRM

parent de6d4059
SET sql_mode=ORACLE;
#
# MDEV-10578 sql_mode=ORACLE: SP control functions SQLCODE, SQLERRM
#
#
# Using SQLCODE and SQLERRM outside of an SP
#
SELECT SQLCODE;
ERROR 42S22: Unknown column 'SQLCODE' in 'field list'
SELECT SQLERRM;
ERROR 42S22: Unknown column 'SQLERRM' in 'field list'
CREATE TABLE t1 (SQLCODE INT, SQLERRM VARCHAR(10));
INSERT INTO t1 VALUES (10, 'test');
SELECT SQLCODE, SQLERRM FROM t1;
SQLCODE SQLERRM
10 test
DROP TABLE t1;
#
# Normal SQLCODE and SQLERRM usage
#
CREATE PROCEDURE p1(stmt VARCHAR)
AS
BEGIN
EXECUTE IMMEDIATE stmt;
SELECT 'Error1: ' || SQLCODE || ' ' || SQLERRM;
EXCEPTION
WHEN OTHERS THEN
SELECT 'Error2: ' || SQLCODE || ' ' || SQLERRM;
END;
$$
CALL p1('SELECT 1');
1
1
'Error1: ' || SQLCODE || ' ' || SQLERRM
Error1: 0 normal, successful completition
CALL p1('xxx');
'Error2: ' || SQLCODE || ' ' || SQLERRM
Error2: 1193 Unknown system variable 'xxx'
CALL p1('SELECT 1');
1
1
'Error1: ' || SQLCODE || ' ' || SQLERRM
Error1: 0 normal, successful completition
DROP PROCEDURE p1;
#
# SQLCODE and SQLERRM hidden by local variables
#
CREATE PROCEDURE p1()
AS
sqlcode INT:= 10;
sqlerrm VARCHAR(64) := 'test';
BEGIN
SELECT 'Error: ' || SQLCODE || ' ' || SQLERRM;
END;
$$
CALL p1;
'Error: ' || SQLCODE || ' ' || SQLERRM
Error: 10 test
DROP PROCEDURE p1;
CREATE PROCEDURE p1()
AS
sqlcode INT;
sqlerrm VARCHAR(64);
BEGIN
SQLCODE:= 10;
sqlerrm:= 'test';
SELECT 'Error: ' || SQLCODE || ' ' || SQLERRM;
END;
$$
CALL p1;
'Error: ' || SQLCODE || ' ' || SQLERRM
Error: 10 test
DROP PROCEDURE p1;
#
# SQLCODE and SQLERRM hidden by parameters
#
CREATE PROCEDURE p1(sqlcode INT, sqlerrm VARCHAR)
AS
BEGIN
SELECT 'Error: ' || SQLCODE || ' ' || SQLERRM;
END;
$$
CALL p1(10, 'test');
'Error: ' || SQLCODE || ' ' || SQLERRM
Error: 10 test
DROP PROCEDURE p1;
#
# SQLCODE and SQLERRM in CREATE..SELECT
#
CREATE PROCEDURE p1
AS
BEGIN
CREATE TABLE t1 AS SELECT SQLCODE, SQLERRM;
END;
$$
CALL p1;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE "t1" (
"SQLCODE" int(11) NOT NULL,
"SQLERRM" varchar(512) CHARACTER SET utf8 NOT NULL
)
DROP TABLE t1;
DROP PROCEDURE p1;
#
# SQLCODE and SQLERRM in EXPLAIN EXTENDED SELECT
#
CREATE PROCEDURE p1
AS
BEGIN
EXPLAIN EXTENDED SELECT SQLCode, SQLErrm;
END;
$$
CALL p1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1003 select SQLCODE AS "SQLCode",SQLERRM AS "SQLErrm"
DROP PROCEDURE p1;
#
# Warning-alike errors in stored functions
#
CREATE TABLE t1 (a INT);
CREATE FUNCTION f1 RETURN VARCHAR
AS
a INT;
BEGIN
SELECT a INTO a FROM t1;
RETURN 'No exception ' || SQLCODE || ' ' || SQLERRM;
EXCEPTION
WHEN NO_DATA_FOUND THEN
RETURN 'Exception ' || SQLCODE || ' ' || SQLERRM;
END;
$$
SELECT f1() FROM DUAL;
f1()
Exception 1329 No data - zero rows fetched, selected, or processed
DROP FUNCTION f1;
DROP TABLE t1;
CREATE TABLE t1 (a INT);
CREATE FUNCTION f1 RETURN VARCHAR
AS
a INT;
BEGIN
SELECT a INTO a FROM t1;
RETURN 'No exception ' || SQLCODE || ' ' || SQLERRM;
EXCEPTION
WHEN OTHERS THEN
RETURN 'Exception ' || SQLCODE || ' ' || SQLERRM;
END;
$$
SELECT f1() FROM DUAL;
f1()
Exception 1329 No data - zero rows fetched, selected, or processed
DROP FUNCTION f1;
DROP TABLE t1;
#
# Warning-alike errors in stored procedures
#
CREATE TABLE t1 (a INT);
CREATE PROCEDURE p1(res OUT VARCHAR)
AS
a INT;
BEGIN
SELECT a INTO a FROM t1;
res:= 'No exception ' || SQLCODE || ' ' || SQLERRM;
EXCEPTION
WHEN NO_DATA_FOUND THEN
res:= 'Exception ' || SQLCODE || ' ' || SQLERRM;
END;
$$
CALL p1(@a);
SELECT @a;
@a
Exception 1329 No data - zero rows fetched, selected, or processed
DROP PROCEDURE p1;
DROP TABLE t1;
CREATE TABLE t1 (a INT);
CREATE PROCEDURE p1(res OUT VARCHAR)
AS
a INT;
BEGIN
SELECT a INTO a FROM t1;
res:= 'No exception ' || SQLCODE || ' ' || SQLERRM;
EXCEPTION
WHEN OTHERS THEN
res:= 'Exception ' || SQLCODE || ' ' || SQLERRM;
END;
$$
CALL p1(@a);
SELECT @a;
@a
Exception 1329 No data - zero rows fetched, selected, or processed
DROP PROCEDURE p1;
DROP TABLE t1;
#
# SQLCODE and SQLERRM are cleared on RETURN
#
CREATE TABLE t1 (a INT);
CREATE FUNCTION f1 RETURN VARCHAR
AS
a INT:=10;
BEGIN
SELECT a INTO a FROM t1;
RETURN 'Value=' || a;
EXCEPTION
WHEN NO_DATA_FOUND THEN RETURN 'Exception|' || SQLCODE || ' ' || SQLERRM;
END;
$$
CREATE FUNCTION f2 RETURN VARCHAR
AS
a VARCHAR(128);
BEGIN
RETURN f1() || '|' || SQLCODE || ' ' || SQLERRM;
END;
$$
SELECT f1() FROM DUAL;
f1()
Exception|1329 No data - zero rows fetched, selected, or processed
SELECT f2() FROM DUAL;
f2()
Exception|1329 No data - zero rows fetched, selected, or processed|0 normal, successful completition
DROP TABLE t1;
DROP FUNCTION f2;
DROP FUNCTION f1;
CREATE TABLE t1 (a INT);
CREATE FUNCTION f1 RETURN VARCHAR
AS
a INT:=10;
BEGIN
SELECT a INTO a FROM t1;
RETURN 'Value=' || a;
EXCEPTION
WHEN OTHERS THEN RETURN 'Exception|' || SQLCODE || ' ' || SQLERRM;
END;
$$
CREATE FUNCTION f2 RETURN VARCHAR
AS
a VARCHAR(128);
BEGIN
RETURN f1() || '|' || SQLCODE || ' ' || SQLERRM;
END;
$$
SELECT f1() FROM DUAL;
f1()
Exception|1329 No data - zero rows fetched, selected, or processed
SELECT f2() FROM DUAL;
f2()
Exception|1329 No data - zero rows fetched, selected, or processed|0 normal, successful completition
DROP TABLE t1;
DROP FUNCTION f2;
DROP FUNCTION f1;
#
# SQLCODE and SQLERRM are cleared on a return from a PROCEDURE
#
CREATE TABLE t1 (a INT);
CREATE PROCEDURE p1(res OUT VARCHAR)
AS
a INT:=10;
BEGIN
SELECT a INTO a FROM t1;
res:='Value=' || a;
EXCEPTION
WHEN NO_DATA_FOUND THEN res:='Exception|' || SQLCODE || ' ' || SQLERRM;
END;
$$
CREATE FUNCTION f2 RETURN VARCHAR
AS
res VARCHAR(128);
BEGIN
CALL p1(res);
RETURN res || '|' || SQLCODE || ' ' || SQLERRM;
END;
$$
SELECT f2() FROM DUAL;
f2()
Exception|1329 No data - zero rows fetched, selected, or processed|0 normal, successful completition
DROP FUNCTION f2;
DROP PROCEDURE p1;
DROP TABLE t1;
CREATE TABLE t1 (a INT);
CREATE PROCEDURE p1(res OUT VARCHAR)
AS
a INT:=10;
BEGIN
SELECT a INTO a FROM t1;
res:='Value=' || a;
EXCEPTION
WHEN OTHERS THEN res:='Exception|' || SQLCODE || ' ' || SQLERRM;
END;
$$
CREATE FUNCTION f2 RETURN VARCHAR
AS
res VARCHAR(128);
BEGIN
CALL p1(res);
RETURN res || '|' || SQLCODE || ' ' || SQLERRM;
END;
$$
SELECT f2() FROM DUAL;
f2()
Exception|1329 No data - zero rows fetched, selected, or processed|0 normal, successful completition
DROP FUNCTION f2;
DROP PROCEDURE p1;
DROP TABLE t1;
#
# End of MDEV-10578 sql_mode=ORACLE: SP control functions SQLCODE, SQLERRM
#
SET sql_mode=ORACLE;
--echo #
--echo # MDEV-10578 sql_mode=ORACLE: SP control functions SQLCODE, SQLERRM
--echo #
--echo #
--echo # Using SQLCODE and SQLERRM outside of an SP
--echo #
--error ER_BAD_FIELD_ERROR
SELECT SQLCODE;
--error ER_BAD_FIELD_ERROR
SELECT SQLERRM;
CREATE TABLE t1 (SQLCODE INT, SQLERRM VARCHAR(10));
INSERT INTO t1 VALUES (10, 'test');
SELECT SQLCODE, SQLERRM FROM t1;
DROP TABLE t1;
--echo #
--echo # Normal SQLCODE and SQLERRM usage
--echo #
DELIMITER $$;
CREATE PROCEDURE p1(stmt VARCHAR)
AS
BEGIN
EXECUTE IMMEDIATE stmt;
SELECT 'Error1: ' || SQLCODE || ' ' || SQLERRM;
EXCEPTION
WHEN OTHERS THEN
SELECT 'Error2: ' || SQLCODE || ' ' || SQLERRM;
END;
$$
DELIMITER ;$$
CALL p1('SELECT 1');
CALL p1('xxx');
CALL p1('SELECT 1');
DROP PROCEDURE p1;
--echo #
--echo # SQLCODE and SQLERRM hidden by local variables
--echo #
DELIMITER $$;
CREATE PROCEDURE p1()
AS
sqlcode INT:= 10;
sqlerrm VARCHAR(64) := 'test';
BEGIN
SELECT 'Error: ' || SQLCODE || ' ' || SQLERRM;
END;
$$
DELIMITER ;$$
CALL p1;
DROP PROCEDURE p1;
DELIMITER $$;
CREATE PROCEDURE p1()
AS
sqlcode INT;
sqlerrm VARCHAR(64);
BEGIN
SQLCODE:= 10;
sqlerrm:= 'test';
SELECT 'Error: ' || SQLCODE || ' ' || SQLERRM;
END;
$$
DELIMITER ;$$
CALL p1;
DROP PROCEDURE p1;
--echo #
--echo # SQLCODE and SQLERRM hidden by parameters
--echo #
DELIMITER $$;
CREATE PROCEDURE p1(sqlcode INT, sqlerrm VARCHAR)
AS
BEGIN
SELECT 'Error: ' || SQLCODE || ' ' || SQLERRM;
END;
$$
DELIMITER ;$$
CALL p1(10, 'test');
DROP PROCEDURE p1;
--echo #
--echo # SQLCODE and SQLERRM in CREATE..SELECT
--echo #
DELIMITER $$;
CREATE PROCEDURE p1
AS
BEGIN
CREATE TABLE t1 AS SELECT SQLCODE, SQLERRM;
END;
$$
DELIMITER ;$$
CALL p1;
SHOW CREATE TABLE t1;
DROP TABLE t1;
DROP PROCEDURE p1;
--echo #
--echo # SQLCODE and SQLERRM in EXPLAIN EXTENDED SELECT
--echo #
DELIMITER $$;
CREATE PROCEDURE p1
AS
BEGIN
EXPLAIN EXTENDED SELECT SQLCode, SQLErrm;
END;
$$
DELIMITER ;$$
CALL p1;
DROP PROCEDURE p1;
--echo #
--echo # Warning-alike errors in stored functions
--echo #
CREATE TABLE t1 (a INT);
DELIMITER $$;
CREATE FUNCTION f1 RETURN VARCHAR
AS
a INT;
BEGIN
SELECT a INTO a FROM t1;
RETURN 'No exception ' || SQLCODE || ' ' || SQLERRM;
EXCEPTION
WHEN NO_DATA_FOUND THEN
RETURN 'Exception ' || SQLCODE || ' ' || SQLERRM;
END;
$$
DELIMITER ;$$
SELECT f1() FROM DUAL;
DROP FUNCTION f1;
DROP TABLE t1;
CREATE TABLE t1 (a INT);
DELIMITER $$;
CREATE FUNCTION f1 RETURN VARCHAR
AS
a INT;
BEGIN
SELECT a INTO a FROM t1;
RETURN 'No exception ' || SQLCODE || ' ' || SQLERRM;
EXCEPTION
WHEN OTHERS THEN
RETURN 'Exception ' || SQLCODE || ' ' || SQLERRM;
END;
$$
DELIMITER ;$$
SELECT f1() FROM DUAL;
DROP FUNCTION f1;
DROP TABLE t1;
--echo #
--echo # Warning-alike errors in stored procedures
--echo #
CREATE TABLE t1 (a INT);
DELIMITER $$;
CREATE PROCEDURE p1(res OUT VARCHAR)
AS
a INT;
BEGIN
SELECT a INTO a FROM t1;
res:= 'No exception ' || SQLCODE || ' ' || SQLERRM;
EXCEPTION
WHEN NO_DATA_FOUND THEN
res:= 'Exception ' || SQLCODE || ' ' || SQLERRM;
END;
$$
DELIMITER ;$$
CALL p1(@a);
SELECT @a;
DROP PROCEDURE p1;
DROP TABLE t1;
CREATE TABLE t1 (a INT);
DELIMITER $$;
CREATE PROCEDURE p1(res OUT VARCHAR)
AS
a INT;
BEGIN
SELECT a INTO a FROM t1;
res:= 'No exception ' || SQLCODE || ' ' || SQLERRM;
EXCEPTION
WHEN OTHERS THEN
res:= 'Exception ' || SQLCODE || ' ' || SQLERRM;
END;
$$
DELIMITER ;$$
CALL p1(@a);
SELECT @a;
DROP PROCEDURE p1;
DROP TABLE t1;
--echo #
--echo # SQLCODE and SQLERRM are cleared on RETURN
--echo #
CREATE TABLE t1 (a INT);
DELIMITER $$;
CREATE FUNCTION f1 RETURN VARCHAR
AS
a INT:=10;
BEGIN
SELECT a INTO a FROM t1;
RETURN 'Value=' || a;
EXCEPTION
WHEN NO_DATA_FOUND THEN RETURN 'Exception|' || SQLCODE || ' ' || SQLERRM;
END;
$$
CREATE FUNCTION f2 RETURN VARCHAR
AS
a VARCHAR(128);
BEGIN
RETURN f1() || '|' || SQLCODE || ' ' || SQLERRM;
END;
$$
DELIMITER ;$$
SELECT f1() FROM DUAL;
SELECT f2() FROM DUAL;
DROP TABLE t1;
DROP FUNCTION f2;
DROP FUNCTION f1;
CREATE TABLE t1 (a INT);
DELIMITER $$;
CREATE FUNCTION f1 RETURN VARCHAR
AS
a INT:=10;
BEGIN
SELECT a INTO a FROM t1;
RETURN 'Value=' || a;
EXCEPTION
WHEN OTHERS THEN RETURN 'Exception|' || SQLCODE || ' ' || SQLERRM;
END;
$$
CREATE FUNCTION f2 RETURN VARCHAR
AS
a VARCHAR(128);
BEGIN
RETURN f1() || '|' || SQLCODE || ' ' || SQLERRM;
END;
$$
DELIMITER ;$$
SELECT f1() FROM DUAL;
SELECT f2() FROM DUAL;
DROP TABLE t1;
DROP FUNCTION f2;
DROP FUNCTION f1;
--echo #
--echo # SQLCODE and SQLERRM are cleared on a return from a PROCEDURE
--echo #
CREATE TABLE t1 (a INT);
DELIMITER $$;
CREATE PROCEDURE p1(res OUT VARCHAR)
AS
a INT:=10;
BEGIN
SELECT a INTO a FROM t1;
res:='Value=' || a;
EXCEPTION
WHEN NO_DATA_FOUND THEN res:='Exception|' || SQLCODE || ' ' || SQLERRM;
END;
$$
CREATE FUNCTION f2 RETURN VARCHAR
AS
res VARCHAR(128);
BEGIN
CALL p1(res);
RETURN res || '|' || SQLCODE || ' ' || SQLERRM;
END;
$$
DELIMITER ;$$
SELECT f2() FROM DUAL;
DROP FUNCTION f2;
DROP PROCEDURE p1;
DROP TABLE t1;
CREATE TABLE t1 (a INT);
DELIMITER $$;
CREATE PROCEDURE p1(res OUT VARCHAR)
AS
a INT:=10;
BEGIN
SELECT a INTO a FROM t1;
res:='Value=' || a;
EXCEPTION
WHEN OTHERS THEN res:='Exception|' || SQLCODE || ' ' || SQLERRM;
END;
$$
CREATE FUNCTION f2 RETURN VARCHAR
AS
res VARCHAR(128);
BEGIN
CALL p1(res);
RETURN res || '|' || SQLCODE || ' ' || SQLERRM;
END;
$$
DELIMITER ;$$
SELECT f2() FROM DUAL;
DROP FUNCTION f2;
DROP PROCEDURE p1;
DROP TABLE t1;
--echo #
--echo # End of MDEV-10578 sql_mode=ORACLE: SP control functions SQLCODE, SQLERRM
--echo #
...@@ -6647,6 +6647,19 @@ longlong Item_func_oracle_sql_rowcount::val_int() ...@@ -6647,6 +6647,19 @@ longlong Item_func_oracle_sql_rowcount::val_int()
} }
longlong Item_func_sqlcode::val_int()
{
DBUG_ASSERT(fixed);
DBUG_ASSERT(!null_value);
Diagnostics_area::Sql_condition_iterator it=
current_thd->get_stmt_da()->sql_conditions();
const Sql_condition *err;
if ((err= it++))
return err->get_sql_errno();
return 0;
}
/** /**
@brief Checks if requested access to function can be granted to user. @brief Checks if requested access to function can be granted to user.
If function isn't found yet, it searches function first. If function isn't found yet, it searches function first.
......
...@@ -2688,6 +2688,30 @@ class Item_func_oracle_sql_rowcount :public Item_int_func ...@@ -2688,6 +2688,30 @@ class Item_func_oracle_sql_rowcount :public Item_int_func
}; };
class Item_func_sqlcode: public Item_int_func
{
public:
Item_func_sqlcode(THD *thd): Item_int_func(thd) { }
longlong val_int();
const char *func_name() const { return "SQLCODE"; }
void print(String *str, enum_query_type query_type)
{
str->append(func_name());
}
bool check_vcol_func_processor(void *arg)
{
return mark_unsupported_function(func_name(), "()", arg, VCOL_IMPOSSIBLE);
}
void fix_length_and_dec()
{
maybe_null= null_value= false;
max_length= 11;
}
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_func_sqlcode>(thd, mem_root, this); }
};
void uuid_short_init(); void uuid_short_init();
class Item_func_uuid_short :public Item_int_func class Item_func_uuid_short :public Item_int_func
......
...@@ -2289,6 +2289,25 @@ String *Item_func_database::val_str(String *str) ...@@ -2289,6 +2289,25 @@ String *Item_func_database::val_str(String *str)
} }
String *Item_func_sqlerrm::val_str(String *str)
{
DBUG_ASSERT(fixed);
DBUG_ASSERT(!null_value);
Diagnostics_area::Sql_condition_iterator it=
current_thd->get_stmt_da()->sql_conditions();
const Sql_condition *err;
if ((err= it++))
{
str->copy(err->get_message_text(), err->get_message_octet_length(),
system_charset_info);
return str;
}
str->copy(C_STRING_WITH_LEN("normal, successful completition"),
system_charset_info);
return str;
}
/** /**
@note USER() is replicated correctly if binlog_format=ROW or (as of @note USER() is replicated correctly if binlog_format=ROW or (as of
BUG#28086) binlog_format=MIXED, but is incorrectly replicated to '' BUG#28086) binlog_format=MIXED, but is incorrectly replicated to ''
......
...@@ -719,6 +719,27 @@ class Item_func_database :public Item_func_sysconst ...@@ -719,6 +719,27 @@ class Item_func_database :public Item_func_sysconst
}; };
class Item_func_sqlerrm :public Item_func_sysconst
{
public:
Item_func_sqlerrm(THD *thd): Item_func_sysconst(thd) {}
String *val_str(String *);
const char *func_name() const { return "SQLERRM"; }
const char *fully_qualified_func_name() const { return "SQLERRM"; }
void print(String *str, enum_query_type query_type)
{
str->append(func_name());
}
void fix_length_and_dec()
{
max_length= 512 * system_charset_info->mbmaxlen;
null_value= maybe_null= false;
}
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_func_sqlerrm>(thd, mem_root, this); }
};
class Item_func_user :public Item_func_sysconst class Item_func_user :public Item_func_sysconst
{ {
protected: protected:
......
...@@ -3398,8 +3398,21 @@ sp_instr_freturn::exec_core(THD *thd, uint *nextp) ...@@ -3398,8 +3398,21 @@ sp_instr_freturn::exec_core(THD *thd, uint *nextp)
That means, Diagnostics Area should be clean before its execution. That means, Diagnostics Area should be clean before its execution.
*/ */
Diagnostics_area *da= thd->get_stmt_da(); if (!(thd->variables.sql_mode & MODE_ORACLE))
da->clear_warning_info(da->warning_info_id()); {
/*
Don't clean warnings in ORACLE mode,
as they are needed for SQLCODE and SQLERRM:
BEGIN
SELECT a INTO a FROM t1;
RETURN 'No exception ' || SQLCODE || ' ' || SQLERRM;
EXCEPTION WHEN NO_DATA_FOUND THEN
RETURN 'Exception ' || SQLCODE || ' ' || SQLERRM;
END;
*/
Diagnostics_area *da= thd->get_stmt_da();
da->clear_warning_info(da->warning_info_id());
}
/* /*
Change <next instruction pointer>, so that this will be the last Change <next instruction pointer>, so that this will be the last
......
...@@ -5951,6 +5951,67 @@ bool LEX::set_variable(struct sys_var_with_base *variable, Item *item) ...@@ -5951,6 +5951,67 @@ bool LEX::set_variable(struct sys_var_with_base *variable, Item *item)
} }
Item *LEX::create_item_ident_nosp(THD *thd, LEX_STRING name)
{
if (current_select->parsing_place != IN_HAVING ||
current_select->get_in_sum_expr() > 0)
return new (thd->mem_root) Item_field(thd, current_context(),
NullS, NullS, name.str);
return new (thd->mem_root) Item_ref(thd, current_context(),
NullS, NullS, name.str);
}
Item *LEX::create_item_ident_sp(THD *thd, LEX_STRING name,
uint start_in_q,
uint length_in_q)
{
sp_variable *spv;
DBUG_ASSERT(spcont);
if ((spv= spcont->find_variable(name, false)))
{
/* We're compiling a stored procedure and found a variable */
if (!parsing_options.allows_variable)
{
my_error(ER_VIEW_SELECT_VARIABLE, MYF(0));
return NULL;
}
Item_splocal *splocal;
splocal= new (thd->mem_root) Item_splocal(thd, name,
spv->offset, spv->sql_type(),
start_in_q, length_in_q);
if (splocal == NULL)
return NULL;
#ifndef DBUG_OFF
splocal->m_sp= sphead;
#endif
safe_to_cache_query= 0;
return splocal;
}
if (thd->variables.sql_mode & MODE_ORACLE)
{
if (!my_strcasecmp(system_charset_info, name.str, "SQLCODE"))
return new (thd->mem_root) Item_func_sqlcode(thd);
if (!my_strcasecmp(system_charset_info, name.str, "SQLERRM"))
return new (thd->mem_root) Item_func_sqlerrm(thd);
}
return create_item_ident_nosp(thd, name);
}
Item *LEX::create_item_ident_sp(THD *thd, LEX_STRING name,
const char *start_in_q,
const char *end_in_q)
{
DBUG_ASSERT(sphead);
return create_item_ident_sp(thd, name, start_in_q - sphead->m_tmp_query,
end_in_q - start_in_q);
}
#ifdef MYSQL_SERVER #ifdef MYSQL_SERVER
uint binlog_unsafe_map[256]; uint binlog_unsafe_map[256];
......
...@@ -3118,6 +3118,21 @@ struct LEX: public Query_tables_list ...@@ -3118,6 +3118,21 @@ struct LEX: public Query_tables_list
const char *start_in_q, const char *start_in_q,
const char *end_in_q); const char *end_in_q);
Item *create_item_ident_nosp(THD *thd, LEX_STRING name);
Item *create_item_ident_sp(THD *thd, LEX_STRING name,
uint start_in_q,
uint length_in_q);
Item *create_item_ident_sp(THD *thd, LEX_STRING name,
const char *start_in_q,
const char *end_in_q);
Item *create_item_ident(THD *thd, LEX_STRING name,
const char *start_in_q,
const char *end_in_q)
{
return sphead ?
create_item_ident_sp(thd, name, start_in_q, end_in_q) :
create_item_ident_nosp(thd, name);
}
bool is_trigger_new_or_old_reference(const LEX_STRING name); bool is_trigger_new_or_old_reference(const LEX_STRING name);
Item *create_and_link_Item_trigger_field(THD *thd, const char *name, Item *create_and_link_Item_trigger_field(THD *thd, const char *name,
......
...@@ -13745,46 +13745,11 @@ order_ident: ...@@ -13745,46 +13745,11 @@ order_ident:
simple_ident: simple_ident:
ident ident
{ {
LEX *lex= thd->lex;
Lex_input_stream *lip= YYLIP; Lex_input_stream *lip= YYLIP;
sp_variable *spv; if (!($$= Lex->create_item_ident(thd, $1,
sp_pcontext *spc = lex->spcont; lip->get_tok_start_prev(),
if (spc && (spv = spc->find_variable($1, false))) lip->get_tok_end())))
{ MYSQL_YYABORT;
/* We're compiling a stored procedure and found a variable */
if (! lex->parsing_options.allows_variable)
my_yyabort_error((ER_VIEW_SELECT_VARIABLE, MYF(0)));
Item_splocal *splocal;
splocal= new (thd->mem_root)
Item_splocal(thd, $1, spv->offset, spv->sql_type(),
lip->get_tok_start_prev() - lex->sphead->m_tmp_query,
lip->get_tok_end() - lip->get_tok_start_prev());
if (splocal == NULL)
MYSQL_YYABORT;
#ifndef DBUG_OFF
splocal->m_sp= lex->sphead;
#endif
$$= splocal;
lex->safe_to_cache_query=0;
}
else
{
SELECT_LEX *sel=Select;
if ((sel->parsing_place != IN_HAVING) ||
(sel->get_in_sum_expr() > 0))
{
$$= new (thd->mem_root) Item_field(thd, Lex->current_context(),
NullS, NullS, $1.str);
}
else
{
$$= new (thd->mem_root) Item_ref(thd, Lex->current_context(),
NullS, NullS, $1.str);
}
if ($$ == NULL)
MYSQL_YYABORT;
}
} }
| simple_ident_q { $$= $1; } | simple_ident_q { $$= $1; }
; ;
...@@ -13792,19 +13757,7 @@ simple_ident: ...@@ -13792,19 +13757,7 @@ simple_ident:
simple_ident_nospvar: simple_ident_nospvar:
ident ident
{ {
SELECT_LEX *sel=Select; if (!($$= Lex->create_item_ident_nosp(thd, $1)))
if ((sel->parsing_place != IN_HAVING) ||
(sel->get_in_sum_expr() > 0))
{
$$= new (thd->mem_root) Item_field(thd, Lex->current_context(),
NullS, NullS, $1.str);
}
else
{
$$= new (thd->mem_root) Item_ref(thd, Lex->current_context(),
NullS, NullS, $1.str);
}
if ($$ == NULL)
MYSQL_YYABORT; MYSQL_YYABORT;
} }
| simple_ident_q { $$= $1; } | simple_ident_q { $$= $1; }
......
...@@ -13674,46 +13674,11 @@ order_ident: ...@@ -13674,46 +13674,11 @@ order_ident:
simple_ident: simple_ident:
ident ident
{ {
LEX *lex= thd->lex;
Lex_input_stream *lip= YYLIP; Lex_input_stream *lip= YYLIP;
sp_variable *spv; if (!($$= Lex->create_item_ident(thd, $1,
sp_pcontext *spc = lex->spcont; lip->get_tok_start_prev(),
if (spc && (spv = spc->find_variable($1, false))) lip->get_tok_end())))
{ MYSQL_YYABORT;
/* We're compiling a stored procedure and found a variable */
if (! lex->parsing_options.allows_variable)
my_yyabort_error((ER_VIEW_SELECT_VARIABLE, MYF(0)));
Item_splocal *splocal;
splocal= new (thd->mem_root)
Item_splocal(thd, $1, spv->offset, spv->sql_type(),
lip->get_tok_start_prev() - lex->sphead->m_tmp_query,
lip->get_tok_end() - lip->get_tok_start_prev());
if (splocal == NULL)
MYSQL_YYABORT;
#ifndef DBUG_OFF
splocal->m_sp= lex->sphead;
#endif
$$= splocal;
lex->safe_to_cache_query=0;
}
else
{
SELECT_LEX *sel=Select;
if ((sel->parsing_place != IN_HAVING) ||
(sel->get_in_sum_expr() > 0))
{
$$= new (thd->mem_root) Item_field(thd, Lex->current_context(),
NullS, NullS, $1.str);
}
else
{
$$= new (thd->mem_root) Item_ref(thd, Lex->current_context(),
NullS, NullS, $1.str);
}
if ($$ == NULL)
MYSQL_YYABORT;
}
} }
| simple_ident_q { $$= $1; } | simple_ident_q { $$= $1; }
; ;
...@@ -13721,19 +13686,7 @@ simple_ident: ...@@ -13721,19 +13686,7 @@ simple_ident:
simple_ident_nospvar: simple_ident_nospvar:
ident ident
{ {
SELECT_LEX *sel=Select; if (!($$= Lex->create_item_ident_nosp(thd, $1)))
if ((sel->parsing_place != IN_HAVING) ||
(sel->get_in_sum_expr() > 0))
{
$$= new (thd->mem_root) Item_field(thd, Lex->current_context(),
NullS, NullS, $1.str);
}
else
{
$$= new (thd->mem_root) Item_ref(thd, Lex->current_context(),
NullS, NullS, $1.str);
}
if ($$ == NULL)
MYSQL_YYABORT; MYSQL_YYABORT;
} }
| simple_ident_q { $$= $1; } | simple_ident_q { $$= $1; }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment