Commit 05050867 authored by Alexander Barkov's avatar Alexander Barkov

A clean-up for MDEV-10654 add support IN, OUT, INOUT parameter qualifiers for stored functions

Changes:

1. Enabling IN/OUT/INOUT mode for sql_mode=DEFAULT,
   adding tests for sql_mode=DEFAULT based by mostly
   translating compat/oracle.sp-inout.test to SQL/PSM
   with minor changes (e.g. testing trigger OLD.column and
   NEW.column as IN/OUT parameters).

2. Removing duplicate grammar:
   sp_pdparam and sp_fdparam implemented exactly the same syntax after
   - the first patch for MDEV-10654 (for sql_mode=ORACLE)
   - the change #1 from this patch (for sql_mode=DEFAULT)
   Removing separate rules and adding a single "sp_param" rule instead,
   which now covers both PRDEDURE and FUNCTION parameters
   (and CURSOR parameters as well!).

3. Adding a helper rule sp_param_name_and_mode, which is a combination
   of the parameter name and the IN/OUT/INOUT mode. It allows to simplify
   the grammer a bit.

4. The first patch unintentionally allowed IN/OUT/INOUT mode
  to be specified in CURSOR parameters.
  This is good for the IN keyword - it is allowed in PL/SQL CURSORs.
  This is not good the the OUT/INOUT keywords - they should not be allowed.
  Adding a additional symantic post-check.
parent 4572dc23
......@@ -737,3 +737,43 @@ rec.en1
c
DROP PROCEDURE p1;
DROP TABLE t1;
#
# Start of 10.8 tests
#
#
# MDEV-10654 IN, OUT, INOUT parameters in CREATE FUNCTION
#
BEGIN NOT ATOMIC
DECLARE va INT;
DECLARE cur CURSOR (IN a INT) FOR SELECT a FROM dual;
OPEN cur(1);
FETCH cur INTO va;
CLOSE cur;
SELECT va;
END;
$$
va
1
BEGIN NOT ATOMIC
DECLARE va INT;
DECLARE cur CURSOR (OUT a INT) FOR SELECT a FROM dual;
OPEN cur(1);
FETCH cur INTO va;
CLOSE cur;
SELECT va;
END;
$$
ERROR 42000: This version of MariaDB doesn't yet support 'OUT/INOUT cursor parameter'
BEGIN NOT ATOMIC
DECLARE va INT;
DECLARE cur CURSOR (INOUT a INT) FOR SELECT a FROM dual;
OPEN cur(1);
FETCH cur INTO va;
CLOSE cur;
SELECT va;
END;
$$
ERROR 42000: This version of MariaDB doesn't yet support 'OUT/INOUT cursor parameter'
#
# End of 10.8 tests
#
......@@ -744,3 +744,54 @@ DELIMITER ;$$
CALL p1();
DROP PROCEDURE p1;
DROP TABLE t1;
--echo #
--echo # Start of 10.8 tests
--echo #
--echo #
--echo # MDEV-10654 IN, OUT, INOUT parameters in CREATE FUNCTION
--echo #
DELIMITER $$;
BEGIN NOT ATOMIC
DECLARE va INT;
DECLARE cur CURSOR (IN a INT) FOR SELECT a FROM dual;
OPEN cur(1);
FETCH cur INTO va;
CLOSE cur;
SELECT va;
END;
$$
DELIMITER ;$$
DELIMITER $$;
--error ER_NOT_SUPPORTED_YET
BEGIN NOT ATOMIC
DECLARE va INT;
DECLARE cur CURSOR (OUT a INT) FOR SELECT a FROM dual;
OPEN cur(1);
FETCH cur INTO va;
CLOSE cur;
SELECT va;
END;
$$
DELIMITER ;$$
DELIMITER $$;
--error ER_NOT_SUPPORTED_YET
BEGIN NOT ATOMIC
DECLARE va INT;
DECLARE cur CURSOR (INOUT a INT) FOR SELECT a FROM dual;
OPEN cur(1);
FETCH cur INTO va;
CLOSE cur;
SELECT va;
END;
$$
DELIMITER ;$$
--echo #
--echo # End of 10.8 tests
--echo #
This diff is collapsed.
This diff is collapsed.
......@@ -977,3 +977,46 @@ $$
CALL p1();
DROP PROCEDURE p1;
DROP TABLE t1;
#
# Start of 10.8 tests
#
#
# MDEV-10654 IN, OUT, INOUT parameters in CREATE FUNCTION
#
DECLARE
va INT;
CURSOR cur (a IN INT) IS SELECT a FROM dual;
BEGIN
OPEN cur(1);
FETCH cur INTO va;
CLOSE cur;
SELECT va;
END;
$$
va
1
DECLARE
va INT;
CURSOR cur (a OUT INT) IS SELECT a FROM dual;
BEGIN
OPEN cur(1);
FETCH cur INTO va;
CLOSE cur;
SELECT va;
END;
$$
ERROR 42000: This version of MariaDB doesn't yet support 'OUT/INOUT cursor parameter'
DECLARE
va INT;
CURSOR cur (a INOUT INT) IS SELECT a FROM dual;
BEGIN
OPEN cur(1);
FETCH cur INTO va;
CLOSE cur;
SELECT va;
END;
$$
ERROR 42000: This version of MariaDB doesn't yet support 'OUT/INOUT cursor parameter'
#
# End of 10.8 tests
#
......@@ -987,3 +987,58 @@ DELIMITER ;$$
CALL p1();
DROP PROCEDURE p1;
DROP TABLE t1;
--echo #
--echo # Start of 10.8 tests
--echo #
--echo #
--echo # MDEV-10654 IN, OUT, INOUT parameters in CREATE FUNCTION
--echo #
DELIMITER $$;
DECLARE
va INT;
CURSOR cur (a IN INT) IS SELECT a FROM dual;
BEGIN
OPEN cur(1);
FETCH cur INTO va;
CLOSE cur;
SELECT va;
END;
$$
DELIMITER ;$$
DELIMITER $$;
--error ER_NOT_SUPPORTED_YET
DECLARE
va INT;
CURSOR cur (a OUT INT) IS SELECT a FROM dual;
BEGIN
OPEN cur(1);
FETCH cur INTO va;
CLOSE cur;
SELECT va;
END;
$$
DELIMITER ;$$
DELIMITER $$;
--error ER_NOT_SUPPORTED_YET
DECLARE
va INT;
CURSOR cur (a INOUT INT) IS SELECT a FROM dual;
BEGIN
OPEN cur(1);
FETCH cur INTO va;
CLOSE cur;
SELECT va;
END;
$$
DELIMITER ;$$
--echo #
--echo # End of 10.8 tests
--echo #
......@@ -7130,6 +7130,27 @@ bool LEX::sp_declare_cursor(THD *thd, const LEX_CSTRING *name,
uint offp;
sp_instr_cpush *i;
/* In some cases param_ctx can be NULL. e.g.: FOR rec IN (SELECT...) */
if (param_ctx)
{
for (uint prm= 0; prm < param_ctx->context_var_count(); prm++)
{
const sp_variable *param= param_ctx->get_context_variable(prm);
if (param->mode != sp_variable::MODE_IN)
{
/*
PL/SQL supports the IN keyword in cursor parameters.
We also support this for compatibility. Note, OUT/INOUT parameters
will unlikely be ever supported. So "YET" may sound confusing here.
But it should be better than using a generic error. Adding a dedicated
error message for this small issue is not desirable.
*/
my_error(ER_NOT_SUPPORTED_YET, MYF(0), "OUT/INOUT cursor parameter");
return true;
}
}
}
if (spcont->find_cursor(name, &offp, true))
{
my_error(ER_SP_DUP_CURS, MYF(0), name->str);
......
......@@ -1749,8 +1749,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
%type <num> sp_handler_type sp_hcond_list
%type <spcondvalue> sp_cond sp_hcond sqlstate signal_value opt_signal_value
%type <spname> sp_name
%type <spvar> sp_param_name sp_param_name_and_type
%type <spvar> sp_param_name_and_type_anchored
%type <spvar> sp_param_name sp_param_name_and_mode sp_param
%type <spvar> sp_param_anchored
%type <for_loop> sp_for_loop_index_and_bounds
%type <for_loop_bounds> sp_for_loop_bounds
%type <trim> trim_operands
......@@ -3051,8 +3051,8 @@ sp_fdparam_list:
;
sp_fdparams:
sp_fdparams ',' sp_param_name_and_type
| sp_param_name_and_type
sp_fdparams ',' sp_param
| sp_param
;
sp_param_name:
......@@ -3070,8 +3070,8 @@ sp_pdparam_list:
;
sp_pdparams:
sp_pdparams ',' sp_pdparam
| sp_pdparam
sp_pdparams ',' sp_param
| sp_param
;
sp_parameter_type:
......@@ -18001,11 +18001,6 @@ sp_opt_default:
| DEFAULT expr { $$ = $2; }
;
sp_pdparam:
sp_parameter_type sp_param_name_and_type { $2->mode=$1; }
| sp_param_name_and_type { $1->mode= sp_variable::MODE_IN; }
;
sp_decl_variable_list_anchored:
sp_decl_idents_init_vars
TYPE_SYM OF_SYM optionally_qualified_column_ident
......@@ -18025,40 +18020,49 @@ sp_decl_variable_list_anchored:
}
;
sp_param_name_and_type:
sp_param_name field_type
sp_param_name_and_mode:
sp_parameter_type sp_param_name
{
$2->mode= $1;
$$= $2;
}
| sp_param_name
;
sp_param:
sp_param_name_and_mode field_type
{
if (unlikely(Lex->sp_param_fill_definition($$= $1, $2)))
MYSQL_YYABORT;
}
| sp_param_name ROW_SYM row_type_body
| sp_param_name_and_mode ROW_SYM row_type_body
{
if (unlikely(Lex->sphead->spvar_fill_row(thd, $$= $1, $3)))
MYSQL_YYABORT;
}
| sp_param_name_and_type_anchored
| sp_param_anchored
;
sp_param_name_and_type_anchored:
sp_param_name TYPE_SYM OF_SYM ident '.' ident
sp_param_anchored:
sp_param_name_and_mode TYPE_SYM OF_SYM ident '.' ident
{
if (unlikely(Lex->sphead->spvar_fill_type_reference(thd,
$$= $1, $4,
$6)))
MYSQL_YYABORT;
}
| sp_param_name TYPE_SYM OF_SYM ident '.' ident '.' ident
| sp_param_name_and_mode TYPE_SYM OF_SYM ident '.' ident '.' ident
{
if (unlikely(Lex->sphead->spvar_fill_type_reference(thd, $$= $1,
$4, $6, $8)))
MYSQL_YYABORT;
}
| sp_param_name ROW_SYM TYPE_SYM OF_SYM ident
| sp_param_name_and_mode ROW_SYM TYPE_SYM OF_SYM ident
{
if (unlikely(Lex->sphead->spvar_fill_table_rowtype_reference(thd, $$= $1, $5)))
MYSQL_YYABORT;
}
| sp_param_name ROW_SYM TYPE_SYM OF_SYM ident '.' ident
| sp_param_name_and_mode ROW_SYM TYPE_SYM OF_SYM ident '.' ident
{
if (unlikely(Lex->sphead->spvar_fill_table_rowtype_reference(thd, $$= $1, $5, $7)))
MYSQL_YYABORT;
......@@ -18442,46 +18446,6 @@ sp_opt_inout:
| IN_SYM OUT_SYM { $$= sp_variable::MODE_INOUT; }
;
sp_pdparam:
sp_param_name sp_opt_inout field_type
{
$1->mode= $2;
if (unlikely(Lex->sp_param_fill_definition($1, $3)))
MYSQL_YYABORT;
}
| sp_param_name sp_opt_inout sp_decl_ident '.' ident PERCENT_ORACLE_SYM TYPE_SYM
{
$1->mode= $2;
if (unlikely(Lex->sphead->spvar_fill_type_reference(thd, $1, $3, $5)))
MYSQL_YYABORT;
}
| sp_param_name sp_opt_inout sp_decl_ident '.' ident '.' ident PERCENT_ORACLE_SYM TYPE_SYM
{
$1->mode= $2;
if (unlikely(Lex->sphead->spvar_fill_type_reference(thd, $1, $3, $5, $7)))
MYSQL_YYABORT;
}
| sp_param_name sp_opt_inout sp_decl_ident PERCENT_ORACLE_SYM ROWTYPE_ORACLE_SYM
{
$1->mode= $2;
if (unlikely(Lex->sphead->spvar_fill_table_rowtype_reference(thd, $1, $3)))
MYSQL_YYABORT;
}
| sp_param_name sp_opt_inout sp_decl_ident '.' ident PERCENT_ORACLE_SYM ROWTYPE_ORACLE_SYM
{
$1->mode= $2;
if (unlikely(Lex->sphead->spvar_fill_table_rowtype_reference(thd, $1, $3, $5)))
MYSQL_YYABORT;
}
| sp_param_name sp_opt_inout ROW_SYM row_type_body
{
$1->mode= $2;
if (unlikely(Lex->sphead->spvar_fill_row(thd, $1, $4)))
MYSQL_YYABORT;
}
;
sp_proc_stmts1_implicit_block:
{
Lex->sp_block_init(thd);
......@@ -18913,45 +18877,47 @@ sp_decl_variable_list_anchored:
}
;
sp_param_name_and_type:
sp_param_name sp_opt_inout field_type
sp_param_name_and_mode:
sp_param_name sp_opt_inout
{
$1->mode= $2;
$$= $1;
}
;
sp_param:
sp_param_name_and_mode field_type
{
$1->mode= $2;
if (unlikely(Lex->sp_param_fill_definition($$= $1, $3)))
if (unlikely(Lex->sp_param_fill_definition($$= $1, $2)))
MYSQL_YYABORT;
}
| sp_param_name sp_opt_inout ROW_SYM row_type_body
| sp_param_name_and_mode ROW_SYM row_type_body
{
$1->mode= $2;
if (unlikely(Lex->sphead->spvar_fill_row(thd, $$= $1, $4)))
if (unlikely(Lex->sphead->spvar_fill_row(thd, $$= $1, $3)))
MYSQL_YYABORT;
}
| sp_param_name_and_type_anchored
| sp_param_anchored
;
sp_param_name_and_type_anchored:
sp_param_name sp_opt_inout sp_decl_ident '.' ident PERCENT_ORACLE_SYM TYPE_SYM
sp_param_anchored:
sp_param_name_and_mode sp_decl_ident '.' ident PERCENT_ORACLE_SYM TYPE_SYM
{
$1->mode= $2;
if (unlikely(Lex->sphead->spvar_fill_type_reference(thd, $$= $1, $3, $5)))
if (unlikely(Lex->sphead->spvar_fill_type_reference(thd, $$= $1, $2, $4)))
MYSQL_YYABORT;
}
| sp_param_name sp_opt_inout sp_decl_ident '.' ident '.' ident PERCENT_ORACLE_SYM TYPE_SYM
| sp_param_name_and_mode sp_decl_ident '.' ident '.' ident PERCENT_ORACLE_SYM TYPE_SYM
{
$1->mode= $2;
if (unlikely(Lex->sphead->spvar_fill_type_reference(thd, $$= $1, $3, $5, $7)))
if (unlikely(Lex->sphead->spvar_fill_type_reference(thd, $$= $1, $2, $4, $6)))
MYSQL_YYABORT;
}
| sp_param_name sp_opt_inout sp_decl_ident PERCENT_ORACLE_SYM ROWTYPE_ORACLE_SYM
| sp_param_name_and_mode sp_decl_ident PERCENT_ORACLE_SYM ROWTYPE_ORACLE_SYM
{
$1->mode= $2;
if (unlikely(Lex->sphead->spvar_fill_table_rowtype_reference(thd, $$= $1, $3)))
if (unlikely(Lex->sphead->spvar_fill_table_rowtype_reference(thd, $$= $1, $2)))
MYSQL_YYABORT;
}
| sp_param_name sp_opt_inout sp_decl_ident '.' ident PERCENT_ORACLE_SYM ROWTYPE_ORACLE_SYM
| sp_param_name_and_mode sp_decl_ident '.' ident PERCENT_ORACLE_SYM ROWTYPE_ORACLE_SYM
{
$1->mode= $2;
if (unlikely(Lex->sphead->spvar_fill_table_rowtype_reference(thd, $$= $1, $3, $5)))
if (unlikely(Lex->sphead->spvar_fill_table_rowtype_reference(thd, $$= $1, $2, $4)))
MYSQL_YYABORT;
}
;
......
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